On Sun, Oct 4, 2026 at 2:21 PM Takayuki 'January June' Suwa <[email protected]> wrote: > > Generally, on 32-bit machines, 64-bit integer addition is performed by > splitting the operation into its upper and lower parts. For examole, > > dest:DI = src0:DI + src1:DI; > > is tranformed into > > dest_hi:SI = src0_hi:SI + src1_hi:SI; > dest_lo:SI = src0_lo:SI + src1_lo:SI; > if (dest_lo:SI <U src0_lo:SI) > ++dest_hi; > > or, > > dest_hi:SI = src0_hi:SI + src1_hi:SI; > dest_lo:SI = src0_lo:SI + src1_lo:SI; > dest_hi:SI += (dest_lo:SI <U src0_lo:SI); > > As in the example above, in machines that do not have a special mechanism > for determining carry-overs, it is necessary to explicitly determine that > the result of the lower part of the calculation is unsigned smaller than > the result before addition. > > Unfortunately, the same hardware register may be assigned to those two > (dest_lo and src0_lo in the example above), and as a result, an assignment > to a scratch register may be inserted (for src0_lo). > > Since addition is a commutative operation, in such cases the problem can > be simply solved by swapping the two operands of the addition. However, > without taking the preceding addition instruction into account, this is > impossible with the comparison alone. > > Fortunately, the RTL instruction combination pass provides combinations > of insns that are suitable for this type of handling, namely patterns that > handle addition and comparison of the result in parallel. > > Trying 8 -> 9: > 8: r52:SI=r48:SI+r67:SI > REG_DEAD r67:SI > 9: pc={(geu(r52:SI,r48:SI))?L11:pc} > REG_DEAD r48:SI > REG_BR_PROB 536870913 > Successfully matched this instruction: > (parallel [ > (set (pc) > (if_then_else (geu (plus:SI (reg:SI 48 [ a ]) > (reg:SI 67 [ b ])) > (reg:SI 48 [ a ])) > (label_ref 11) > (pc))) > (set (reg:SI 52 [ _3 ]) > (plus:SI (reg:SI 48 [ a ]) > (reg:SI 67 [ b ]))) > ]) > allowing combination of insns 8 and 9 > original costs 4 + 12 = 16 > replacement cost 16 > deferring deletion of insn with uid = 8. > modifying insn i3 9: > {pc={(geu(r48:SI+r67:SI,r48:SI))?L11:pc};r52:SI=r48:SI+r67:SI;} > REG_DEAD r67:SI > REG_BR_PROB 536870913 > REG_DEAD r48:SI > deferring rescan insn with uid = 9. > > This makes it possible to appropriately swap the two operands after the RA, > yielding the desired result. > > gcc/ChangeLog: > > * config/xtensa/xtensa.cc > (adddi3): Remove the previous sloppy workaround. > (adddi3_lowpart_0, adddi3_lowpart_1): New insn_and_split patterns. > --- > gcc/config/xtensa/xtensa.md | 75 +++++++++++++++++++++++++++++++++---- > 1 file changed, 67 insertions(+), 8 deletions(-)
Regtested for target=xtensa-linux-uclibc, no new regressions. Committed to master. -- Thanks. -- Max
