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]; +}
