Hi Kito:

Thanks for the review and the detailed feedback! I agree that extending
this to soft-float targets and moving the logic to
riscv_legitimize_const_move is a much better approach. I have
implemented these changes in v2.


Kito Cheng <[email protected]> 於 2025年12月18日週四 下午5:00寫道:
>
> Hi Meng-Tsung:
>
> Thanks for your patch! that's really good insight, and that's
> generally it's a good direction,
>
> However there is some  implementation detail should be adjust a little bit:
>
> > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> > index 96519c96a2b..b4973747cfd 100644
> > --- a/gcc/config/riscv/riscv.cc
> > +++ b/gcc/config/riscv/riscv.cc
> > @@ -2614,6 +2614,24 @@ riscv_const_insns (rtx x, bool allow_new_pseudos)
> >        if (satisfies_constraint_zfli (x))
> >         return 1;
> >
> > +    /* When target support Zfinx-like extension, we can use li to
> > +      materialize FP constants.  */
> > +  if (TARGET_ZFINX)
>
> ^^^ I guess it could relax to !TARGET_HARD_FLOAT
> since this optimization can be applied when either F and ZFINX is not present.
>
> e.g. -march=rv64i -mabi=lp64
Thanks for the advice, I relaxed the condition to !TARGET_HARD_FLOAT in v2.

>
> > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> > index 6f8cd26e5c9..036873d0988 100644
> > --- a/gcc/config/riscv/riscv.md
> > +++ b/gcc/config/riscv/riscv.md
> > @@ -2481,6 +2481,34 @@
> >                       MAX_MACHINE_MODE, &operands[3]);
> >  })
> >
> > +;; Zfinx-like: Use integer instructions to materialize FP constants in GPRs
> > +(define_insn_and_split "*mov<mode>_zfinx_const"
>
> I would suggest you can implement this logic into
> riscv_legitimize_const_move, so that you don't need to add a new
> pattern here.
> and that probably means you don't need to modify any logic in 
> riscv_const_insns.
>
I have moved the logic into riscv_legitimize_const_move. However, I
found it necessary to keep the cost calculation logic inside
riscv_const_insns.

I checked `riscv_rtx_cost` and found that it relies on `riscv_const_insns`
to decide the cost strategy. If `riscv_const_insns` returns 0 (which was
the default for CONST_DOUBLE in the previous implementation),
`riscv_rtx_cost` assumes it cannot be synthesized by instructions and
forces the value into the constant pool. To prevent this, I updated
riscv_const_insns to report the correct cost for these constants.

Also, regarding predicates.md, I updated `move_operand` to return
TARGET_HARD_FLOAT for CONST_DOUBLE. This is necessary because
`riscv_emit_move` checks `move_operand` before calling
`riscv_legitimize_const_move`. If `move_operand` returns true, the expansion
logic is bypassed, causing the constant to be forced to memory.

> Another way is combine this logic into movsf_softfloat, but that might
> change much more place, although I suspect this way might help RA can
> do better especially on rematerialization, however this could be
> deferred until we found enough evidence that could improve. (or you
> can try it if you are interested in that way.)
>
>
> > +  [(set (match_operand:GPRF_XLEN 0 "register_operand" "=r")
> > +       (match_operand 1 "immediate_operand" " i"))]
> > +  "TARGET_ZFINX
> > +   && GET_CODE (operands[1]) == CONST_DOUBLE"
> > +  "#"
> > +  "&& 1"
> > +  [(const_int 0)]
> > +  {
> > +    long target_vals[2] = {0};
> > +    real_to_target (target_vals, CONST_DOUBLE_REAL_VALUE (operands[1]),
> > +                   <MODE>mode);
> > +    unsigned HOST_WIDE_INT val;
> > +
> > +    int order = BYTES_BIG_ENDIAN ? 1 : 0;
> > +    unsigned HOST_WIDE_INT lo = target_vals[order];
> > +    unsigned HOST_WIDE_INT hi = target_vals[1 - order];
> > +    val = ((hi << 32) | lo);
> > +    val &= GET_MODE_MASK (<MODE>mode);
> > +
> > +    machine_mode int_mode = (<MODE>mode == DFmode) ? DImode : SImode;
> > +    rtx int_reg = gen_lowpart (int_mode, operands[0]);
> > +    riscv_move_integer (int_reg, int_reg, val, int_mode);
> > +    DONE;
> > +  }
> > +)
> > +
> >  ;; Pretend to have the ability to load complex const_int in order to get
> >  ;; better code generation around them.
> >  ;; But avoid constants that are special cased elsewhere.
> > diff --git a/gcc/testsuite/gcc.target/riscv/zfinx-const-li.c
> > b/gcc/testsuite/gcc.target/riscv/zfinx-const-li.c
> > new file mode 100644
> > index 00000000000..22c84a48e42
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/riscv/zfinx-const-li.c
> > @@ -0,0 +1,52 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -march=rv64i_zfinx -mabi=lp64" { target rv64 } } */
> > +/* { dg-options "-O2 -march=rv32i_zfinx -mabi=ilp32" { target rv32 } } */
>
> Could you add a testcase with  -march=rv64i -mabi=lp64/-march=rv32i 
> -mabi=ilp32?
I have added a new testsuite "softfloat-const-li.c" in v2.
>
> +/* { dg-skip-if "" { *-*-* } { "-O0" } } */
>
> Also could you drop -O2 from dg-options since you already filter -O0 here
Nice catch, also fixed in v2.

I will send the v2 patch shortly.
Best regards,
Meng-Tsung Tsai

Reply via email to