[PATCH v5 13/18] RISC-V: Add POSTINDEX_LD macro-fusion recognition

Jin Ma <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
Recognize a scalar integer or floating-point load followed by a
non-word ADDI-type in-place update of its base register.  Reuse the
indexed-memory helper shared with the pre-index rules and accept either
load-destination relationship.

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_ld): New
	function.
	(riscv_fusion_table): Add RISCV_FUSE_POSTINDEX_LD.
	* config/riscv/riscv-protos.h (enum riscv_fusion_pairs): Add
	RISCV_FUSE_POSTINDEX_LD.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/fusion-load-dest-equal-rtl-postindex.c: New test.
	* gcc.target/riscv/fusion-postindex-ldst.c: Likewise.

Signed-off-by: Jin Ma <[email protected]>
---
 gcc/config/riscv/riscv-fusion.cc              | 24 +++++++++++++
 gcc/config/riscv/riscv-protos.h               |  1 +
 .../fusion-load-dest-equal-rtl-postindex.c    | 34 +++++++++++++++++++
 .../gcc.target/riscv/fusion-postindex-ldst.c  | 34 +++++++++++++++++++
 4 files changed, 93 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-load-dest-equal-rtl-postindex.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-postindex-ldst.c

diff --git a/gcc/config/riscv/riscv-fusion.cc b/gcc/config/riscv/riscv-fusion.cc
index b8d3c6d7fa6..0d9870d4b1e 100644
--- a/gcc/config/riscv/riscv-fusion.cc
+++ b/gcc/config/riscv/riscv-fusion.cc
@@ -1217,6 +1217,28 @@ riscv_fuse_preindex_st (rtx_insn *prev, rtx_insn *curr)
   return riscv_fuse_indexed_mem_p (prev, curr, false, true);
 }
 
+/* Check for RISCV_FUSE_POSTINDEX_LD fusion.
+   prev (one of the following):
+     (load) == (set (reg rd1) (mem addr))
+     (load) == (set (reg rd1) (any_extend (mem addr)))
+     (fpload) == (set (reg frd) (mem addr))
+   addr (one of the following):
+     (rd2, offset)
+     (lo_sum (reg rd2) symbol1)
+   curr (one of the following):
+     (addi) == (set (reg rd2) (plus (reg rd2) (const_int imm12)))
+     (self-mv) == (set (reg rd2) (reg rd2))
+     (addi) == (set (reg rd2) (lo_sum (reg rd2) symbol2))
+
+   Constraints:
+     the ADDI-type instruction is not a word form.  */
+
+static bool
+riscv_fuse_postindex_ld (rtx_insn *prev, rtx_insn *curr)
+{
+  return riscv_fuse_indexed_mem_p (prev, curr, true, false);
+}
+
 /* Check for RISCV_FUSE_LUI_ADDI fusion.
    prev (one of the following):
      (lui) == (set (reg rd1) (const_int imm20))
@@ -1738,6 +1760,8 @@ static const struct riscv_fusion_entry riscv_fusion_table[] =
     riscv_fuse_ldpreincrement, "RISCV_FUSE_LDPREINCREMENT" },
   { RISCV_FUSE_PREINDEX_ST,
     riscv_fuse_preindex_st, "RISCV_FUSE_PREINDEX_ST" },
+  { RISCV_FUSE_POSTINDEX_LD,
+    riscv_fuse_postindex_ld, "RISCV_FUSE_POSTINDEX_LD" },
   { 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 a40c7d56233..557c8db9111 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -874,6 +874,7 @@ enum riscv_fusion_pairs
   RISCV_FUSE_SLLI_SRLI = HOST_WIDE_INT_1U << 18,
   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,
 };
 
 extern bool riscv_macro_fusion_p (void);
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-load-dest-equal-rtl-postindex.c b/gcc/testsuite/gcc.target/riscv/fusion-load-dest-equal-rtl-postindex.c
new file mode 100644
index 00000000000..72eb79e1ad9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-load-dest-equal-rtl-postindex.c
@@ -0,0 +1,34 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O2 -mtune=xt-c9501fdvt -fdump-rtl-sched2-details" } */
+/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_POSTINDEX_LD" 1 "sched2" { xfail *-*-* } } } */
+
+/* An unsigned load and update writing the same register should fuse.  */
+long __RTL (startwith ("sched2"))
+test_postindex_load_same_destination (void)
+{
+(function "test_postindex_load_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)
+                    (zero_extend:DI
+                      (mem:QI (reg:DI a0) [0 S1 A8]))))
+      (cinsn 4 (set (reg:DI a0)
+                    (plus:DI (reg:DI a0)
+                             (const_int 1))))
+      (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)
+    ) ;; return_rtx
+  ) ;; crtl
+) ;; function "test_postindex_load_same_destination"
+}
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-postindex-ldst.c b/gcc/testsuite/gcc.target/riscv/fusion-postindex-ldst.c
new file mode 100644
index 00000000000..6e45da46a95
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-postindex-ldst.c
@@ -0,0 +1,34 @@
+/* { 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-vectorize -fno-unroll-loops -fdump-rtl-sched2-details" } */
+/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_POSTINDEX_LD" 2 "sched2" { xfail *-*-* } } } */
+
+typedef signed char int8_t;
+
+extern void use_ptr (void *);
+
+int8_t
+post_lb (int8_t *src, int n)
+{
+  int8_t sum = 0;
+  for (int i = 0; i < n; ++i)
+    {
+      sum += *src;
+      ++src;
+    }
+  use_ptr (src);
+  return sum;
+}
+
+double
+post_fld (double *src, int n)
+{
+  double sum = 0;
+  for (int i = 0; i < n; ++i)
+    {
+      sum += *src;
+      ++src;
+    }
+  use_ptr (src);
+  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.