https://gcc.gnu.org/g:5de5fd66196e052c73375e80c1a232b2e1f36707

commit r17-763-g5de5fd66196e052c73375e80c1a232b2e1f36707
Author: Jin Ma <[email protected]>
Date:   Tue May 19 17:31:27 2026 +0800

    RISC-V: Fix multiple bugs in riscv_macro_fusion_pair_p
    
    Fix several correctness and minor issues in the fusion pair
    matching logic:
    
    XINT (prev_set, 1) in RISCV_FUSE_AUIPC_LD incorrectly accesses
    the SET node rather than its UNSPEC source operand.  Use
    XINT (SET_SRC (prev_set), 1) to match riscv_fuse_auipc_addi.
    
    RISCV_FUSE_CACHE_ALIGNED_STD compared base registers with != instead
    of ==, causing it to match stores with different bases rather than
    the same base which is required for cache-line alignment analysis.
    
    RISCV_FUSE_B_ALUI sub+smax pattern had a redundant CONST_INT_P
    check on the same operand already validated by the CONST0_RTX
    comparison.
    
    RISCV_FUSE_LDINDEXED had a duplicate REG_P check on the same
    operand.
    
    Also fix a typo ("hte" -> "the") in a comment and correct the
    dump output string from "RISCV_FUSE_ALIGNED_STD" to
    "RISCV_FUSE_CACHE_ALIGNED_STD" for the cache-aligned case.
    
    Tests are marked XFAIL as no upstream mtune currently enables
    AUIPC_LD, CACHE_ALIGNED_STD, B_ALUI, or LDINDEXED.  The
    existing fusion-auipc-addi.c test indirectly validates the
    XINT fix since AUIPC_ADDI shares the same UNSPEC_AUIPC check
    code path.
    
    gcc/ChangeLog:
    
            * config/riscv/riscv-fusion.cc (riscv_macro_fusion_pair_p):
            Fix XINT to access SET_SRC (prev_set) in AUIPC_LD case.
            Fix base register comparison from != to == in
            CACHE_ALIGNED_STD case.  Remove redundant CONST_INT_P
            check in B_ALUI sub+smax case.  Remove duplicate REG_P
            check in LDINDEXED case.  Fix typo in comment.  Fix dump
            output name for CACHE_ALIGNED_STD.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/fusion-auipc-ld.c: New test.
            * gcc.target/riscv/fusion-b-alui.c: New test.
            * gcc.target/riscv/fusion-cache-aligned-std.c: New test.
            * gcc.target/riscv/fusion-ldindexed.c: New test.

Diff:
---
 gcc/config/riscv/riscv-fusion.cc                    | 10 ++++------
 gcc/testsuite/gcc.target/riscv/fusion-auipc-ld.c    | 16 ++++++++++++++++
 gcc/testsuite/gcc.target/riscv/fusion-b-alui.c      | 13 +++++++++++++
 .../gcc.target/riscv/fusion-cache-aligned-std.c     | 21 +++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/fusion-ldindexed.c   | 13 +++++++++++++
 5 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/gcc/config/riscv/riscv-fusion.cc b/gcc/config/riscv/riscv-fusion.cc
index 5bce3eda0a6c..990eab405a64 100644
--- a/gcc/config/riscv/riscv-fusion.cc
+++ b/gcc/config/riscv/riscv-fusion.cc
@@ -226,7 +226,6 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
       if (MEM_P (SET_SRC (curr_set))
          && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
          && REG_P (XEXP (SET_SRC (curr_set), 0))
-         && REG_P (XEXP (SET_SRC (curr_set), 0))
          && REGNO (XEXP (SET_SRC (curr_set), 0)) == prev_dest_regno
          && GET_CODE (SET_SRC (prev_set)) == PLUS
          && REG_P (XEXP (SET_SRC (prev_set), 0))
@@ -524,7 +523,7 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
                              (mem:DI (plus:DI (reg:DI rD) (const_int IMM12)))) 
*/
 
       if (GET_CODE (SET_SRC (prev_set)) == UNSPEC
-         && XINT (prev_set, 1) == UNSPEC_AUIPC
+         && XINT (SET_SRC (prev_set), 1) == UNSPEC_AUIPC
          && MEM_P (SET_SRC (curr_set))
          && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
          && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS)
@@ -560,8 +559,8 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
             bases are the same register.  */
          if (base_prev != NULL_RTX && base_curr != NULL_RTX
              && REG_P (base_prev) && REG_P (base_curr)
-             && REGNO (base_prev) != REGNO (base_curr)
-             /* The alignment of hte base pointer is more useful than the
+             && REGNO (base_prev) == REGNO (base_curr)
+             /* The alignment of the base pointer is more useful than the
                 alignment of the memory reference for determining if we're
                 on opposite sides of a cache line.  */
              && REGNO_POINTER_ALIGN (ORIGINAL_REGNO (base_prev)) >= 128)
@@ -582,7 +581,7 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
                  && (INTVAL (offset_prev) + 8 == INTVAL (offset_curr)))
                {
                  if (dump_file)
-                   fprintf (dump_file, "RISCV_FUSE_ALIGNED_STD\n");
+                   fprintf (dump_file, "RISCV_FUSE_CACHE_ALIGNED_STD\n");
                  return true;
                }
            }
@@ -720,7 +719,6 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
       if (GET_CODE (SET_SRC (prev_set)) == MINUS
          && (XEXP (SET_SRC (prev_set), 0)
              == CONST0_RTX (GET_MODE (SET_SRC (prev_set))))
-         && CONST_INT_P (XEXP (SET_SRC (prev_set), 0))
          && GET_CODE (SET_SRC (curr_set)) == SMAX
          && REG_P (SET_DEST (prev_set))
          && REG_P (SET_DEST (curr_set))
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-auipc-ld.c 
b/gcc/testsuite/gcc.target/riscv/fusion-auipc-ld.c
new file mode 100644
index 000000000000..e3a24e495e11
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-auipc-ld.c
@@ -0,0 +1,16 @@
+/* Verify RISCV_FUSE_AUIPC_LD correctly matches auipc+ld pairs.
+   This exercises the fix for XINT accessing SET_SRC (prev_set)
+   instead of prev_set directly.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" "-Os" "-Oz" "-flto" } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -mtune=sifive-p600-series 
-mcmodel=medany -mexplicit-relocs -fno-section-anchors -fdump-rtl-sched1" } */
+/* No upstream mtune currently enables RISCV_FUSE_AUIPC_LD.  */
+/* { dg-final { scan-rtl-dump "RISCV_FUSE_AUIPC_LD" "sched1" { xfail *-*-* } } 
} */
+
+extern long x;
+
+long
+load_global (void)
+{
+  return x;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-b-alui.c 
b/gcc/testsuite/gcc.target/riscv/fusion-b-alui.c
new file mode 100644
index 000000000000..3ae029571639
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-b-alui.c
@@ -0,0 +1,13 @@
+/* Verify RISCV_FUSE_B_ALUI correctly matches sub+smax (abs) pattern.
+   This exercises the removal of the redundant CONST_INT_P check.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" "-Os" "-Oz" "-flto" } } */
+/* { dg-options "-march=rv64gc_zbb -mabi=lp64d -mtune=sifive-p600-series 
-fdump-rtl-sched1" } */
+/* No upstream mtune currently enables RISCV_FUSE_B_ALUI.  */
+/* { dg-final { scan-rtl-dump "RISCV_FUSE_B_ALUI" "sched1" { xfail *-*-* } } } 
*/
+
+long
+abs_val (long x)
+{
+  return x < 0 ? -x : x;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-cache-aligned-std.c 
b/gcc/testsuite/gcc.target/riscv/fusion-cache-aligned-std.c
new file mode 100644
index 000000000000..5484e0c05758
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-cache-aligned-std.c
@@ -0,0 +1,21 @@
+/* Verify RISCV_FUSE_CACHE_ALIGNED_STD correctly matches consecutive
+   stores to the same cache line.  This exercises the fix for base
+   register comparison (changed from != to ==).  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" "-Os" "-Oz" "-flto" } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -mtune=sifive-p600-series 
-fdump-rtl-sched1" } */
+/* No upstream mtune currently enables RISCV_FUSE_CACHE_ALIGNED_STD.  */
+/* { dg-final { scan-rtl-dump "RISCV_FUSE_CACHE_ALIGNED_STD" "sched1" { xfail 
*-*-* } } } */
+
+struct pair
+{
+  long a;
+  long b;
+} __attribute__ ((aligned (16)));
+
+void
+store_pair (struct pair *p, long x, long y)
+{
+  p->a = x;
+  p->b = y;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/fusion-ldindexed.c 
b/gcc/testsuite/gcc.target/riscv/fusion-ldindexed.c
new file mode 100644
index 000000000000..7687edeec157
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/fusion-ldindexed.c
@@ -0,0 +1,13 @@
+/* Verify RISCV_FUSE_LDINDEXED correctly matches add+ld pairs.
+   This exercises the removal of the duplicate REG_P check.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" "-Os" "-Oz" "-flto" } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -mtune=sifive-p600-series 
-fdump-rtl-sched1" } */
+/* No upstream mtune currently enables RISCV_FUSE_LDINDEXED.  */
+/* { dg-final { scan-rtl-dump "RISCV_FUSE_LDINDEXED" "sched1" { xfail *-*-* } 
} } */
+
+long
+load_indexed (long *base, long idx)
+{
+  return base[idx];
+}

Reply via email to