From 500b3e1904d95129b2af4ce9262e8c0265a49202 Mon Sep 17 00:00:00 2001 From: lemon Date: Mon, 22 Dec 2025 09:00:41 +0100 Subject: simpl: handle multiplication by negative po2 too --- ir/simpl.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'ir/simpl.c') diff --git a/ir/simpl.c b/ir/simpl.c index 8aec043..740a5a7 100644 --- a/ir/simpl.c +++ b/ir/simpl.c @@ -5,7 +5,9 @@ mulk(struct instr *ins, struct block *blk, int *curi) { vlong iv = intconval(ins->r); enum irclass cls = ins->cls; - assert(iv > 1 && "trivial mul not handled by irbinop() ?"); + assert((uvlong)iv > 1 && "trivial mul not handled by irbinop() ?"); + bool neg = iv < 0; + if (neg) iv = -iv; /* This can be generalized to any sequence of shifts and * adds/subtracts, but whether that's worth it depends on the number of them * and the microarchitecture.. clang seems to stop after two shifts. Should @@ -15,21 +17,23 @@ mulk(struct instr *ins, struct block *blk, int *curi) /* x * 2^y ==> x << y */ ins->op = Oshl; ins->r = mkref(RICON, ilog2(iv)); - return 1; } else if (ispo2(iv-1)) { /* x * 5 ==> (x << 2) + x */ ins->op = Oadd; ins->r = ins->l; ins->l = insertinstr(blk, (*curi)++, mkinstr(Oshl, cls, ins->l, mkref(RICON, ilog2(iv-1)))); - return 1; } else if (ispo2(iv+1)) { /* x * 7 ==> (x << 3) - x */ ins->op = Osub; ins->r = ins->l; ins->l = insertinstr(blk, (*curi)++, mkinstr(Oshl, cls, ins->l, mkref(RICON, ilog2(iv+1)))); - return 1; + } else return 0; + if (neg) { + ins->l = insertinstr(blk, (*curi)++, *ins); + ins->op = Oneg; + ins->r = NOREF; } - return 0; + return 1; } static int -- cgit v1.2.3