[PATCH v5 11/18] RISC-V: Generalize LDPREINCREMENT macro-fusion recognition

Jin Ma <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
Allow LDPREINCREMENT to match non-word ADDI-type in-place address
updates followed by scalar integer or floating-point loads.  Support
register-plus-offset and LO_SUM addresses, self moves, and either
load-destination relationship.

Put the common pre/post-index load/store constraints in a
parameterized helper for later fusion rules.

gcc/ChangeLog:

	* config/riscv/riscv-fusion.cc (riscv_fuse_indexed_mem_p): New
	function.
	(riscv_fuse_ldpreincrement): Use it and accept scalar integer or
	floating-point loads.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/fusion-preindex-load.c: New test.
	* gcc.target/riscv/fusion-preindex-load-rtl.c: Likewise.

Signed-off-by: Jin Ma <[email protected]>
---
 gcc/config/riscv/riscv-fusion.cc              | 77 +++++++++++++------
 .../riscv/fusion-preindex-load-rtl.c          | 66 ++++++++++++++++
 .../gcc.target/riscv/fusion-preindex-load.c   | 31 ++++++++
 3 files changed, 149 insertions(+), 25 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-preindex-load-rtl.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-preindex-load.c

diff --git a/gcc/config/riscv/riscv-fusion.cc b/gcc/config/riscv/riscv-fusion.cc
index c24fb29cbaf..c6e7073cb23 100644
--- a/gcc/config/riscv/riscv-fusion.cc
+++ b/gcc/config/riscv/riscv-fusion.cc
@@ -800,6 +800,45 @@ riscv_fuse_add_mem_p (rtx_insn *prev, rtx_insn *curr,
   return true;
 }
 
+/* Match an in-place ADDI-type address update and a scalar load or store using
+   the updated address.  LOAD_P selects loads rather than stores, and
+   PREINDEX_P selects whether the update precedes the memory instruction.  */
+
+static bool
+riscv_fuse_indexed_mem_p (rtx_insn *prev, rtx_insn *curr,
+			    bool load_p, bool preindex_p)
+{
+  rtx prev_set, curr_set;
+  if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
+    return false;
+
+  rtx_insn *update_insn = preindex_p ? prev : curr;
+  rtx_insn *mem_insn = preindex_p ? curr : prev;
+  rtx update_set = preindex_p ? prev_set : curr_set;
+  rtx mem_set = preindex_p ? curr_set : prev_set;
+  rtx update_dest = SET_DEST (update_set);
+  rtx update_base = NULL_RTX;
+  struct riscv_fusion_mem_info mem;
+
+  if (!riscv_insn_is_addi_type_p (update_insn, false, &update_base)
+      || update_base == NULL_RTX
+      || !riscv_fuse_mem_p (mem_insn, &mem)
+      || (load_p
+	  ? mem.type == SCHED_FUSION_ST
+	  : mem.type != SCHED_FUSION_ST)
+      || !(mem.addr.type == ADDRESS_REG
+	   || mem.addr.type == ADDRESS_LO_SUM)
+      || riscv_regno (update_dest) == INVALID_REGNUM
+      || !riscv_fuse_same_reg_p (update_base, update_dest)
+      || !riscv_fuse_same_reg_p (mem.addr.reg, update_dest))
+    return false;
+
+  if (load_p)
+    return true;
+
+  return !riscv_fuse_same_reg_p (SET_SRC (mem_set), update_dest);
+}
+
 /* Check the common RTL for ZEXTW, ZEXTWS and ZEXTH fusion.  */
 
 static bool
@@ -1134,37 +1173,25 @@ riscv_fuse_expanded_ld (rtx_insn *prev, rtx_insn *curr)
 }
 
 /* Check for RISCV_FUSE_LDPREINCREMENT fusion.
-   prev (addi) == (set (reg rd1)
-		       (plus (reg rd1) (const_int offset)))
-   curr (load) == (set (reg rd2) (mem (reg rd1)))
+   prev (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) symbol1))
+   curr (one of the following):
+     (load) == (set (reg rd2) (mem addr))
+     (load) == (set (reg rd2) (any_extend (mem addr)))
+     (fpload) == (set (reg frd) (mem addr))
+   addr (one of the following):
+     (rd1, offset)
+     (lo_sum (reg rd1) symbol2)
 
    Constraints:
-     rd1 == rd2.  */
+     the ADDI-type instruction is not a word form.  */
 
 static bool
 riscv_fuse_ldpreincrement (rtx_insn *prev, rtx_insn *curr)
 {
-  rtx prev_set, curr_set;
-  if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set))
-    return false;
-
-  if (!riscv_fuse_same_dest_p (prev_set, curr_set))
-    return false;
-
-  struct riscv_fusion_mem_info mem;
-
-  if (riscv_fuse_mem_p (curr, &mem)
-      && mem.type == SCHED_FUSION_LD
-      && !mem.fp_p
-      && mem.addr.type == ADDRESS_REG
-      && INTVAL (mem.addr.offset) == 0
-      && riscv_set_is_addi_p (prev_set)
-      && riscv_fuse_same_reg_p (XEXP (SET_SRC (prev_set), 0),
-				  SET_DEST (prev_set))
-      && riscv_fuse_same_reg_p (mem.addr.reg, SET_DEST (prev_set)))
-    return true;
-
-  return false;
+  return riscv_fuse_indexed_mem_p (prev, curr, true, true);
 }
 
 /* Check for RISCV_FUSE_LUI_ADDI fusion.
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-preindex-load-rtl.c b/gcc/testsuite/gcc.target/riscv/fusion-preindex-load-rtl.c
new file mode 100644
index 00000000000..c8cceb4740a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-preindex-load-rtl.c
@@ -0,0 +1,66 @@
+/* { 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_LDPREINCREMENT" 2 "sched2" { xfail *-*-* } } } */
+
+extern double preindex_symbol;
+
+/* The load may write the address-update destination.  */
+long __RTL (startwith ("sched2"))
+test_preindex_same_destination (void)
+{
+(function "test_preindex_same_destination"
+  (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 (reg:DI a0)
+                    (plus:DI (reg:DI a0) (const_int 1))))
+      (cinsn 4 (set (reg:DI a0)
+                    (zero_extend:DI
+                      (mem:QI (reg:DI a0) [0 S1 A8]))))
+      (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))
+  ) ;; crtl
+) ;; function "test_preindex_same_destination"
+}
+
+/* LO_SUM updates and addresses are accepted for floating-point loads.  */
+long __RTL (startwith ("sched2"))
+test_preindex_lo_sum_fload (void)
+{
+(function "test_preindex_lo_sum_fload"
+  (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 (reg:DI a0)
+                    (lo_sum:DI
+                      (reg:DI a0)
+                      (symbol_ref:DI ("preindex_symbol")))))
+      (cinsn 4 (set (reg:DF fa0)
+                    (mem:DF
+                      (lo_sum:DI
+                        (reg:DI a0)
+                        (symbol_ref:DI ("preindex_symbol")))
+                      [0 S8 A64])))
+      (cinsn 5 (use (reg:DI a0)))
+      (cinsn 6 (use (reg:DF fa0)))
+      (cjump_insn 7 (simple_return))
+      (edge-to exit)
+    ) ;; block 2
+    (cbarrier 8)
+  ) ;; insn-chain
+  (crtl
+    (return_rtx (reg/i:DI a0))
+  ) ;; crtl
+) ;; function "test_preindex_lo_sum_fload"
+}
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-preindex-load.c b/gcc/testsuite/gcc.target/riscv/fusion-preindex-load.c
new file mode 100644
index 00000000000..6fd83652d55
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-preindex-load.c
@@ -0,0 +1,31 @@
+/* { 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 -fdump-rtl-sched2-details" } */
+/* No tune enables this fusion pair yet.  */
+/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_LDPREINCREMENT" 2 "sched2" { xfail *-*-* } } } */
+
+typedef signed char int8_t;
+
+int8_t
+test_preindex_lb (int8_t *p, int n)
+{
+  int8_t sum = 0;
+  for (int i = 0; i < n; ++i)
+    {
+      p += 2;
+      sum += *p;
+    }
+  return sum;
+}
+
+double
+test_preindex_fld (double *p, int n)
+{
+  double sum = 0;
+  for (int i = 0; i < n; ++i)
+    {
+      p += 2;
+      sum += *p;
+    }
+  return sum;
+}
-- 
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.