On 9/10/26 9:47 AM, Milan Tripkovic wrote:
This patch implements the shNadd.uw case from the PR.
The instruction shNadd.uw a0, a0, a0 computes:
((a0 & 0xffffffff) << N) + a0
If a0 holds a value sign extended from bit 31, with u being its low
32 bits, this formula evaluates to:
u * (2^N + 1) - 2^32
This allows us to build certain 64-bit constants using just a lui
and a single shNadd.uw.
To find u, riscv_build_integer_1 reverses the formula: it adds
2^32 to the constant and divide it by 3, 5, or 9. If the quotient
fits in 32 bits with bit 31 set, and the new sequence is cheaper,
we emit an FMA entry with use_uw set.
For 0x180005000, before:
li a0,1572864
addi t0,a0,5
slli a0,t0,12
after:
li a0,-715821056
sh1add.uw a0,a0,a0
Finally, in riscv_move_integer, the FMA check is moved above the
use_uw check. Since our shNadd.uw case sets use_uw = true,
checking use_uw first would mistakenly treat the operation as a
plain zero-extended shift instead of shNadd.uw.
2026-09-10 Milan Tripkovic <[email protected]>
gcc/ChangeLog:
* config/riscv/riscv.cc (riscv_build_integer_1): Add logic to
synthesize constants using shNadd.uw.
(riscv_move_integer): Handle FMA with use_uw for RTL emission.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/pr126074.c: New test.
Thanks! I don't know if there's constants your implementation would
catch that my exploration would have missed. I only thought about using
lui as the first step in the sequence, but yours at least potentially
works with other leading sequences.
Anyway, I've pushed this to the trunk after spinning it in my tester for
bootstraps & regression testing on the k3 and c920 designs.
Jeff