RISC-V: Add constant synthesis using shNadd.uw instruction
Enables RISC-V compiler to synthesize constants more efficiently using the shNadd.uw instruction.
This patch introduces support for synthesizing certain 64-bit constants on RISC-V using the shNadd.uw instruction, which performs a shift and add operation. Previously, creating such constants involved multiple instructions. The compiler now identifies opportunities to use shNadd.uw for specific constant values that fit the pattern u * (2^N + 1) - 2^32, leading to more compact code. A new test case verifies this optimization, and the logic for handling fused multiply-add (FMA) with use_uw is adjusted for correctness.
In Details
The RISC-V backend's riscv_build_integer_1 function now synthesizes constants using the shNadd.uw instruction for cases where the target constant C can be expressed as C = u * (2^N + 1) - 2^32, where u is a 32-bit value with the sign bit set. This is achieved by reversing the formula to u = (C + 2^32) / (2^N + 1), checking if u fits within 32 bits. The riscv_move_integer function is updated to correctly prioritize FMA checks over use_uw checks, preventing shNadd.uw from being misinterpreted as a simple shift. This addresses PR target/126074.
- RISC-V
- An open-standard instruction set architecture based on Reduced Instruction Set Computing principles.
- shNadd.uw
- A RISC-V instruction that performs a left-shifted addition with unsigned widening. It computes
(reg1 << N) + reg2. - constant synthesis
- The process by which the compiler generates code to construct specific constant values, often optimizing for the number of instructions used.
- lui
- Load Upper Immediate. A RISC-V instruction used to load a 20-bit immediate value into the upper 20 bits of a register, often used in combination with other instructions to form full 32-bit or 64-bit constants.
- FMA
- Fused Multiply-Add. An instruction that performs multiplication and addition in a single operation, often with performance benefits.