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

Reply via email to