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
> 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.
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?
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
Also could you drop -O2 from dg-options since you already filter -O0 here