[PATCH v5 05/18] RISC-V: Add ADD_ST macro-fusion recognition

Jin Ma <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
Recognize ADD, ADDW, or ADD.UW followed by an undisplaced scalar
integer store that uses the add result as its address.  Keep the
store-data constraint separate from the common add-memory matcher.

Leave the fusion disabled by default.

gcc/ChangeLog:

	* config/riscv/riscv-fusion.cc (riscv_fuse_add_st): New function.
	(riscv_fusion_table): Add RISCV_FUSE_ADD_ST.
	* config/riscv/riscv-protos.h (enum riscv_fusion_pairs): Add
	RISCV_FUSE_ADD_ST.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/fusion-add-st.c: New test.
	* gcc.target/riscv/fusion-addw-adduw-st.c: Likewise.

Signed-off-by: Jin Ma <[email protected]>
---
 gcc/config/riscv/riscv-fusion.cc              | 29 ++++++++
 gcc/config/riscv/riscv-protos.h               |  1 +
 .../gcc.target/riscv/fusion-add-st.c          | 13 ++++
 .../gcc.target/riscv/fusion-addw-adduw-st.c   | 67 +++++++++++++++++++
 4 files changed, 110 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-add-st.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-addw-adduw-st.c

diff --git a/gcc/config/riscv/riscv-fusion.cc b/gcc/config/riscv/riscv-fusion.cc
index 840bad47002..bb4076e9ffc 100644
--- a/gcc/config/riscv/riscv-fusion.cc
+++ b/gcc/config/riscv/riscv-fusion.cc
@@ -773,6 +773,33 @@ riscv_fuse_ldindexed (rtx_insn *prev, rtx_insn *curr)
 	  && mem.type != SCHED_FUSION_ST);
 }
 
+/* Check for RISCV_FUSE_ADD_ST fusion.
+   prev (one of the following):
+     (add) == (set (reg rd1) (plus (reg rs1) (reg rs2)))
+     (addw) == (set (reg rd1) (sign_extend (plus:SI (reg rs1)
+						    (reg rs2))))
+     (add.uw) == (set (reg rd1) (plus (zero_extend (reg rs1))
+				      (reg rs2)))
+   curr (one of the following):
+     (store) == (set (mem (rd1, offset)) (reg rs3))
+     (store) == (set (mem (rd1, offset)) (const_int 0))
+
+   Constraints:
+     rd1 != rs3 for a register-source store
+     offset == 0.  */
+
+static bool
+riscv_fuse_add_st (rtx_insn *prev, rtx_insn *curr)
+{
+  rtx add_set, mem_set;
+  struct riscv_fusion_mem_info mem;
+
+  return (riscv_fuse_add_mem_p (prev, curr, &add_set, &mem_set, &mem)
+	  && mem.type == SCHED_FUSION_ST
+	  && !riscv_fuse_same_reg_p (SET_DEST (add_set),
+					 SET_SRC (mem_set)));
+}
+
 /* Check for RISCV_FUSE_EXPANDED_LD fusion.
    prev (one of the following):
      (add) == (set (reg rd1) (plus (reg rs1) (reg rs2)))
@@ -1211,6 +1238,8 @@ static const struct riscv_fusion_entry riscv_fusion_table[] =
     riscv_fuse_zexth, "RISCV_FUSE_ZEXTH" },
   { RISCV_FUSE_LDINDEXED,
     riscv_fuse_ldindexed, "RISCV_FUSE_LDINDEXED" },
+  { RISCV_FUSE_ADD_ST,
+    riscv_fuse_add_st, "RISCV_FUSE_ADD_ST" },
   { RISCV_FUSE_EXPANDED_LD,
     riscv_fuse_expanded_ld, "RISCV_FUSE_EXPANDED_LD" },
   { RISCV_FUSE_LDPREINCREMENT,
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 20781e14313..0bd26523a98 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -867,6 +867,7 @@ enum riscv_fusion_pairs
   RISCV_FUSE_EXPANDED_LD = HOST_WIDE_INT_1U << 11,
   RISCV_FUSE_B_ALUI = HOST_WIDE_INT_1U << 12,
   RISCV_FUSE_SUB_SEQZ = HOST_WIDE_INT_1U << 13,
+  RISCV_FUSE_ADD_ST = HOST_WIDE_INT_1U << 14,
 };
 
 extern bool riscv_macro_fusion_p (void);
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-add-st.c b/gcc/testsuite/gcc.target/riscv/fusion-add-st.c
new file mode 100644
index 00000000000..e0cebe27972
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-add-st.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */
+/* { dg-options "-march=rv64g -mabi=lp64d -mtune=xt-c9501fdvt -O2 -fdump-rtl-sched2-details" } */
+/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_ADD_ST" 1 "sched2" { xfail *-*-* } } } */
+
+typedef long int64_t;
+
+/* add + sd should fuse.  */
+void
+test_add_sd (int64_t *base, long off, int64_t v)
+{
+  *(int64_t *) ((char *) base + off) = v;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-addw-adduw-st.c b/gcc/testsuite/gcc.target/riscv/fusion-addw-adduw-st.c
new file mode 100644
index 00000000000..19989e0b902
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-addw-adduw-st.c
@@ -0,0 +1,67 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */
+/* { dg-options "-march=rv64gc_zba -mabi=lp64d -mtune=xt-c9501fdvt -O2 -fdump-rtl-sched2-details" } */
+/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_ADD_ST" 2 "sched2" { xfail *-*-* } } } */
+
+/* addw + sd should fuse.  */
+long __RTL (startwith ("sched2"))
+test_addw_sd (void)
+{
+(function "test_addw_sd"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cnote 2 NOTE_INSN_FUNCTION_BEG)
+      ;; addw a0, a1, a2
+      (cinsn 3 (set (reg:DI a0)
+                    (sign_extend:DI
+                      (plus:SI (reg:SI a1)
+                               (reg:SI a2)))))
+      ;; sd a3, 0(a0)
+      (cinsn 4 (set (mem:DI (reg:DI a0) [0  S8 A64])
+                    (reg:DI a3)))
+      (cinsn 5 (use (reg/i:DI a0)))
+      (cjump_insn 6 (simple_return))
+      (edge-to exit)
+    ) ;; block 2
+    (cbarrier 7)
+  ) ;; insn-chain
+  (crtl
+    (return_rtx
+      (reg/i:DI a0)
+    ) ;; return_rtx
+  ) ;; crtl
+) ;; function "test_addw_sd"
+}
+
+/* add.uw + sd should fuse.  */
+long __RTL (startwith ("sched2"))
+test_adduw_sd (void)
+{
+(function "test_adduw_sd"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cnote 2 NOTE_INSN_FUNCTION_BEG)
+      ;; add.uw a0, a1, a2
+      (cinsn 3 (set (reg:DI a0)
+                    (plus:DI (zero_extend:DI (reg:SI a1))
+                             (reg:DI a2))))
+      ;; sd a3, 0(a0)
+      (cinsn 4 (set (mem:DI (reg:DI a0) [0  S8 A64])
+                    (reg:DI a3)))
+      (cinsn 5 (use (reg/i:DI a0)))
+      (cjump_insn 6 (simple_return))
+      (edge-to exit)
+    ) ;; block 2
+    (cbarrier 7)
+  ) ;; insn-chain
+  (crtl
+    (return_rtx
+      (reg/i:DI a0)
+    ) ;; return_rtx
+  ) ;; crtl
+) ;; function "test_adduw_sd"
+}
-- 
2.52.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.