diff options
| author | 2025-12-10 11:43:31 +0100 | |
|---|---|---|
| committer | 2025-12-10 11:48:00 +0100 | |
| commit | de8f28eb07915fe19902cd93d01229faa7599666 (patch) | |
| tree | 41626b86e413fcefd4e50fbf2bfdf2ef8b51065a /ir/regalloc.c | |
| parent | 1ada32d3a8bee5533cab63f17c4402a20b1b8e23 (diff) | |
regalloc: optimize a little edge case better
With two-address instructions one needs to make sure the dst doesn't get
allocated to the same reg as the right-hand operand:
%r = mul %x, %y ; %y cannot be %r
Except, if the operands are the same
%r = mul %x, %x ; if %x is dead after this instr, it's fine to
allocate %r to the same reg
Diffstat (limited to 'ir/regalloc.c')
| -rw-r--r-- | ir/regalloc.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/ir/regalloc.c b/ir/regalloc.c index 3642d36..51ccdab 100644 --- a/ir/regalloc.c +++ b/ir/regalloc.c @@ -831,7 +831,7 @@ linearscan(struct rega *ra) handled = it; if (it->alloc.t == AREG) { ra->free |= 1<<it->alloc.a; - //DBG(" unblock %s\n", mctarg->rnames[it->reg]); + //DBG(" unblock %s %X\n", mctarg->rnames[it->alloc.a], ra->free); } else if (it->alloc.t == ASTACK) { freestk(ra, it->alloc.a); } @@ -905,12 +905,14 @@ linearscan(struct rega *ra) rsclr(&free, it->alloc.a); } } - /* for 2-address instrs, exclude reg from 2nd arg */ + /* for 2-address instrs, exclude reg from 2nd arg (unless arg#1 == arg#2) */ if (ins->inplace && opnarg[ins->op] == 2) { int xreg; if (ins->r.t == RREG) rsclr(&free, ins->r.i); - else if (ins->r.t == RTMP && (xreg = instrtab[ins->r.i].reg)) - rsclr(&free, xreg-1); + else if (ins->r.t == RTMP && (xreg = instrtab[ins->r.i].reg)) { + if (ins->r.bits != ins->l.bits) + rsclr(&free, xreg-1); + } } if (!free) { |