Add a future-facing capability for adjacent single- or
double-precision floating-point loads or stores whose addresses share a
base and increase by one access size. Reuse the pair matcher shared
with integer pairs.
Leave the capability disabled and XFAIL its positive dump check.
gcc/ChangeLog:
* config/riscv/riscv-fusion.cc (riscv_fuse_fldfst_pair_inc): New
function.
(riscv_fusion_table): Add RISCV_FUSE_FLDFST_PAIR_INC.
* config/riscv/riscv-protos.h (enum riscv_fusion_pairs): Add
RISCV_FUSE_FLDFST_PAIR_INC.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/fusion-fldfst-pair-inc.c: New test.
Signed-off-by: Jin Ma <[email protected]>
---
gcc/config/riscv/riscv-fusion.cc | 21 +++++++++++++
gcc/config/riscv/riscv-protos.h | 1 +
.../gcc.target/riscv/fusion-fldfst-pair-inc.c | 31 +++++++++++++++++++
3 files changed, 53 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-fldfst-pair-inc.c
diff --git a/gcc/config/riscv/riscv-fusion.cc b/gcc/config/riscv/riscv-fusion.cc
index e150b53c63b..4cb51a1ca1b 100644
--- a/gcc/config/riscv/riscv-fusion.cc
+++ b/gcc/config/riscv/riscv-fusion.cc
@@ -1553,6 +1553,25 @@ riscv_fuse_ldst_pair_dec (rtx_insn *prev, rtx_insn *curr)
return riscv_fuse_ldst_pair_p (prev, curr, false, false);
}
+/* Check for RISCV_FUSE_FLDFST_PAIR_INC fusion.
+ prev/curr (one of the following pairs):
+ prev (flw/fld) == (set (reg frd1) (mem (rs1, offset1)))
+ curr (flw/fld) == (set (reg frd2) (mem (rs1, offset2)))
+
+ prev (fsw/fsd) == (set (mem (rs1, offset1)) (reg frs1))
+ curr (fsw/fsd) == (set (mem (rs1, offset2)) (reg frs2))
+
+ Constraints:
+ access size is 4 or 8 bytes
+ offset2 - offset1 equals the access size
+ for loads, frd1 != frd2. */
+
+static bool
+riscv_fuse_fldfst_pair_inc (rtx_insn *prev, rtx_insn *curr)
+{
+ return riscv_fuse_ldst_pair_p (prev, curr, true, true);
+}
+
/* Check for RISCV_FUSE_BFEXT fusion.
prev (slli) == (set (reg rd1)
(ashift (reg rs1) (const_int shamt1)))
@@ -1900,6 +1919,8 @@ static const struct riscv_fusion_entry
riscv_fusion_table[] =
riscv_fuse_ldst_pair_inc, "RISCV_FUSE_LDST_PAIR_INC" },
{ RISCV_FUSE_LDST_PAIR_DEC,
riscv_fuse_ldst_pair_dec, "RISCV_FUSE_LDST_PAIR_DEC" },
+ { RISCV_FUSE_FLDFST_PAIR_INC,
+ riscv_fuse_fldfst_pair_inc, "RISCV_FUSE_FLDFST_PAIR_INC" },
{ RISCV_FUSE_BFEXT,
riscv_fuse_bfext, "RISCV_FUSE_BFEXT" },
{ RISCV_FUSE_SLLI_SRLI,
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 3a14108ef19..d7ebc6f9773 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -878,6 +878,7 @@ enum riscv_fusion_pairs
RISCV_FUSE_POSTINDEX_ST = HOST_WIDE_INT_1U << 22,
RISCV_FUSE_LDST_PAIR_INC = HOST_WIDE_INT_1U << 23,
RISCV_FUSE_LDST_PAIR_DEC = HOST_WIDE_INT_1U << 24,
+ RISCV_FUSE_FLDFST_PAIR_INC = HOST_WIDE_INT_1U << 25,
};
extern bool riscv_macro_fusion_p (void);
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-fldfst-pair-inc.c
b/gcc/testsuite/gcc.target/riscv/fusion-fldfst-pair-inc.c
new file mode 100644
index 00000000000..e74808c62bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-fldfst-pair-inc.c
@@ -0,0 +1,31 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -mtune=xt-c9501fdvt -O2
-fdump-rtl-sched2-details" } */
+/* No tune enables RISCV_FUSE_FLDFST_PAIR_INC yet. */
+/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_FLDFST_PAIR_INC" 4 "sched2" {
xfail *-*-* } } } */
+
+float
+test_flw_pair_inc (float *p)
+{
+ return p[0] + p[1];
+}
+
+double
+test_fld_pair_inc (double *p)
+{
+ return p[0] + p[1];
+}
+
+void
+test_fsw_pair_inc (float *p, float a, float b)
+{
+ p[0] = a;
+ p[1] = b;
+}
+
+void
+test_fsd_pair_inc (double *p, double a, double b)
+{
+ p[0] = a;
+ p[1] = b;
+}
--
2.52.0