On 3/24/2026 9:18 AM, Philipp Tomsich wrote:
From: Konstantinos Eleftheriou <[email protected]>

Non-zero floating-point constants that are not Zfa FLI candidates are
currently always loaded from the constant pool (lui + flw/fld), even
when the IEEE 754 bit pattern can be cheaply built in a GP register
and transferred via fmv.s.x/fmv.d.x with no memory access.

Add expand-time synthesis in riscv_legitimize_move: decompose the
CONST_DOUBLE into an integer build (riscv_move_integer) followed by
a GP-to-FP transfer.  The constant is synthesized when the integer
build cost is < 3 instructions, keeping the total (including fmv)
at <= 3 — competitive with the 2-instruction + memory-access
constant pool alternative.

For SFmode (RV32 and RV64 with F), every float constant qualifies
since any 32-bit value can be built in at most 2 instructions.
For DFmode (RV64 with D), constants whose bit pattern can be built
in 1-2 instructions are covered: all powers of 2, simple fractions,
small integers, and many common engineering constants.  Transcendental
constants like pi and e still use the constant pool.

Examples (RV64GC, -O2):
   1.0f:  lui+flw (2 insns + mem)  ->  li+fmv.s.x     (2 insns)
   1.0:   lui+fld (2 insns + mem)  ->  li+slli+fmv.d.x (3 insns)
   pi:    unchanged (constant pool, integer build too expensive)

gcc/ChangeLog:

        * config/riscv/riscv.cc (riscv_reinterpret_float_as_int): New
        function to extract IEEE 754 bit pattern from CONST_DOUBLE.
        (riscv_float_const_rtx_p): New function to decide if integer
        synthesis is profitable; returns the sign-extended integer
        value through an output parameter.
        (riscv_cannot_force_const_mem): Return true for synthesizable
        FP constants to prevent constant pool spilling.
        (riscv_const_insns): Return synthesis cost for eligible FP
        constants so they are treated as legitimate constants.
        (riscv_legitimize_move): Add synthesis of FP constants via
        integer instructions and fmv.[sd].x.

gcc/testsuite/ChangeLog:

        * gcc.dg/fold-overflow-1.c: Expect 2139095040 three times on
        RISC-V due to FP constant synthesis of FLT_MAX.
        * gcc.target/riscv/pr105666.c: Remove scan-assembler-not for
        fmv.d.x since it now appears for FP constant synthesis.  Keep
        the fmv.x.d check for GP-to-FP spill avoidance.
        * gcc.target/riscv/fp-const-synth-df-boundary.c: New test.
        * gcc.target/riscv/fp-const-synth-df-rv32.c: New test.
        * gcc.target/riscv/fp-const-synth-df.c: New test.
        * gcc.target/riscv/fp-const-synth-run.c: New test.
        * gcc.target/riscv/fp-const-synth-sf-rv32.c: New test.
        * gcc.target/riscv/fp-const-synth-sf.c: New test.
        * gcc.target/riscv/fp-const-synth-special-sf.c: New test.
        * gcc.target/riscv/fp-const-synth-zfa.c: New test.
Not a review, but a note that I believe this will resolve the remaining issues with 110748 as -0.0 is just a bset dst, x0, 31/63 when ZBB is available.  More importantly I think as-written it should silently "just work" for any constant we can easily synthesize.  So I'm definitely supportive of basic idea.  Just need to get inside the implementation details now.


Jeff

Reply via email to