Recognize a scalar integer or floating-point store followed by a
non-word ADDI-type in-place update of its base register. Reuse the
indexed-memory helper and store-source constraint shared with
PREINDEX_ST.
Leave the fusion disabled by default and XFAIL its positive dump
checks until a CPU enables it.
gcc/ChangeLog:
* config/riscv/riscv-fusion.cc (riscv_fuse_postindex_st): New
function.
(riscv_fusion_table): Add RISCV_FUSE_POSTINDEX_ST.
* config/riscv/riscv-protos.h (enum riscv_fusion_pairs): Add
RISCV_FUSE_POSTINDEX_ST.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/fusion-memory-rtl-shapes-postindex.c: New test.
* gcc.target/riscv/fusion-postindex-st.c: Likewise.
Signed-off-by: Jin Ma <[email protected]>
---
gcc/config/riscv/riscv-fusion.cc | 25 +++++++++++++
gcc/config/riscv/riscv-protos.h | 1 +
.../fusion-memory-rtl-shapes-postindex.c | 37 +++++++++++++++++++
.../gcc.target/riscv/fusion-postindex-st.c | 30 +++++++++++++++
4 files changed, 93 insertions(+)
create mode 100644
gcc/testsuite/gcc.target/riscv/fusion-memory-rtl-shapes-postindex.c
create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-postindex-st.c
diff --git a/gcc/config/riscv/riscv-fusion.cc b/gcc/config/riscv/riscv-fusion.cc
index 0d9870d4b1e..530c24482b2 100644
--- a/gcc/config/riscv/riscv-fusion.cc
+++ b/gcc/config/riscv/riscv-fusion.cc
@@ -1239,6 +1239,29 @@ riscv_fuse_postindex_ld (rtx_insn *prev, rtx_insn *curr)
return riscv_fuse_indexed_mem_p (prev, curr, true, false);
}
+/* Check for RISCV_FUSE_POSTINDEX_ST fusion.
+ prev (one of the following):
+ (store) == (set (mem addr) (reg rs1))
+ (store) == (set (mem addr) (const_int 0))
+ (fpstore) == (set (mem addr) (reg frs1))
+ addr (one of the following):
+ (rd1, offset)
+ (lo_sum (reg rd1) symbol1)
+ curr (one of the following):
+ (addi) == (set (reg rd1) (plus (reg rd1) (const_int imm12)))
+ (self-mv) == (set (reg rd1) (reg rd1))
+ (addi) == (set (reg rd1) (lo_sum (reg rd1) symbol2))
+
+ Constraints:
+ the ADDI-type instruction is not a word form
+ for a register-source integer store, rd1 != rs1. */
+
+static bool
+riscv_fuse_postindex_st (rtx_insn *prev, rtx_insn *curr)
+{
+ return riscv_fuse_indexed_mem_p (prev, curr, false, false);
+}
+
/* Check for RISCV_FUSE_LUI_ADDI fusion.
prev (one of the following):
(lui) == (set (reg rd1) (const_int imm20))
@@ -1762,6 +1785,8 @@ static const struct riscv_fusion_entry
riscv_fusion_table[] =
riscv_fuse_preindex_st, "RISCV_FUSE_PREINDEX_ST" },
{ RISCV_FUSE_POSTINDEX_LD,
riscv_fuse_postindex_ld, "RISCV_FUSE_POSTINDEX_LD" },
+ { RISCV_FUSE_POSTINDEX_ST,
+ riscv_fuse_postindex_st, "RISCV_FUSE_POSTINDEX_ST" },
{ RISCV_FUSE_LUI_ADDI,
riscv_fuse_lui_addi, "RISCV_FUSE_LUI_ADDI" },
{ RISCV_FUSE_AUIPC_ADDI,
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 557c8db9111..445d1f7f257 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -875,6 +875,7 @@ enum riscv_fusion_pairs
RISCV_FUSE_SRLI_ADD = HOST_WIDE_INT_1U << 19,
RISCV_FUSE_PREINDEX_ST = HOST_WIDE_INT_1U << 20,
RISCV_FUSE_POSTINDEX_LD = HOST_WIDE_INT_1U << 21,
+ RISCV_FUSE_POSTINDEX_ST = HOST_WIDE_INT_1U << 22,
};
extern bool riscv_macro_fusion_p (void);
diff --git
a/gcc/testsuite/gcc.target/riscv/fusion-memory-rtl-shapes-postindex.c
b/gcc/testsuite/gcc.target/riscv/fusion-memory-rtl-shapes-postindex.c
new file mode 100644
index 00000000000..3372274e6fd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-memory-rtl-shapes-postindex.c
@@ -0,0 +1,37 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -mexplicit-relocs -O2
-mtune=xt-c9501fdvt -fdump-rtl-sched2-details" } */
+/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_POSTINDEX_ST" 1 "sched2" {
xfail *-*-* } } } */
+
+extern long postindex_symbol;
+
+long __RTL (startwith ("sched2"))
+test_postindex_lo_sum_store (void)
+{
+(function "test_postindex_lo_sum_store"
+ (insn-chain
+ (block 2
+ (edge-from entry (flags "FALLTHRU"))
+ (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (cnote 2 NOTE_INSN_FUNCTION_BEG)
+ (cinsn 3 (set (mem:DI
+ (lo_sum:DI
+ (reg:DI a0)
+ (symbol_ref:DI ("postindex_symbol")))
+ [0 S8 A64])
+ (reg:DI a2)))
+ (cinsn 4 (set (reg:DI a0)
+ (lo_sum:DI
+ (reg:DI a0)
+ (symbol_ref:DI ("postindex_symbol")))))
+ (cinsn 5 (use (reg:DI a0)))
+ (cjump_insn 6 (simple_return))
+ (edge-to exit)
+ ) ;; block 2
+ (cbarrier 7)
+ ) ;; insn-chain
+ (crtl
+ (return_rtx (reg/i:DI a0))
+ ) ;; crtl
+) ;; function "test_postindex_lo_sum_store"
+}
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-postindex-st.c
b/gcc/testsuite/gcc.target/riscv/fusion-postindex-st.c
new file mode 100644
index 00000000000..4ea0308bf81
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-postindex-st.c
@@ -0,0 +1,30 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-funroll-loops"
"-flto" } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -mtune=xt-c9501fdvt -O2
-fno-tree-loop-distribute-patterns -fno-tree-vectorize -fno-unroll-loops
-fdump-rtl-sched2-details" } */
+/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_POSTINDEX_ST" 2 "sched2" {
xfail *-*-* } } } */
+
+typedef signed char int8_t;
+
+extern void use_ptr (void *);
+
+void
+post_sb (int8_t *dst, int8_t value, int n)
+{
+ for (int i = 0; i < n; ++i)
+ {
+ *dst = value;
+ ++dst;
+ }
+ use_ptr (dst);
+}
+
+void
+post_fsd (double *dst, double value, int n)
+{
+ for (int i = 0; i < n; ++i)
+ {
+ *dst = value;
+ ++dst;
+ }
+ use_ptr (dst);
+}
--
2.52.0