https://gcc.gnu.org/g:3518a4892d0dd65ca841b82519832147d626ca2e

commit r17-5185-g3518a4892d0dd65ca841b82519832147d626ca2e
Author: Jin Ma <[email protected]>
Date:   Tue Oct 13 14:03:49 2026 +0800

    sched: Avoid creating fusion groups during selective scheduling
    
    Selective scheduling builds its instruction expressions after the
    initial Haifa dependency analysis.  Reanalyzing instructions later can
    set SCHED_GROUP_P without updating VINSN_UNIQUE_P or the group links.
    This can make sel_rank_for_schedule violate comparator antisymmetry
    and trigger an ICE with checking enabled.
    
    Only create macro-fusion groups during Haifa dependency analysis,
    including the initial Haifa emulation used by selective scheduling.
    Add RTL regressions using the existing XiangShan zero-extension
    fusion rules.  Check that initial grouping still runs and that
    scheduling does not create a new group for initially separated shifts.
    A loop variant reproduces the comparator ICE during software pipelining.
    
    The regression tests were generated with LLM assistance.
    
    gcc/ChangeLog:
    
            * sched-deps.cc (sched_analyze_insn): Restrict macro-fusion grouping
            to Haifa dependency analysis.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/sched-fusion-selective.c: New test.
            * gcc.target/riscv/sched-fusion-selective-ice.c: Likewise.
    
    Signed-off-by: Jin Ma <[email protected]>

Diff:
---
 gcc/sched-deps.cc                                  |  1 +
 .../gcc.target/riscv/sched-fusion-selective-ice.c  | 60 ++++++++++++++++++++++
 .../gcc.target/riscv/sched-fusion-selective.c      | 42 +++++++++++++++
 3 files changed, 103 insertions(+)

diff --git a/gcc/sched-deps.cc b/gcc/sched-deps.cc
index 24b76a3ad891..d1e69af1e816 100644
--- a/gcc/sched-deps.cc
+++ b/gcc/sched-deps.cc
@@ -2944,6 +2944,7 @@ sched_analyze_insn (class deps_desc *deps, rtx x, 
rtx_insn *insn)
 
   /* Group compare and branch insns for macro-fusion.  */
   if (!deps->readonly
+      && (!sel_sched_p () || sched_emulate_haifa_p)
       && targetm.sched.macro_fusion_p
       && targetm.sched.macro_fusion_p ())
     sched_macro_fuse_insns (insn);
diff --git a/gcc/testsuite/gcc.target/riscv/sched-fusion-selective-ice.c 
b/gcc/testsuite/gcc.target/riscv/sched-fusion-selective-ice.c
new file mode 100644
index 000000000000..bc5f8e863201
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sched-fusion-selective-ice.c
@@ -0,0 +1,60 @@
+/* Verify that macro fusion does not cause an ICE in selective scheduling.  */
+
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */
+/* { dg-options "-O2 -fselective-scheduling2 -fsel-sched-pipelining" } */
+/* { dg-additional-options "-march=rv64gc -mabi=lp64d" } */
+/* { dg-additional-options "-mtune=xiangshan-nanhu -fchecking=2" } */
+
+long __RTL (startwith ("sched2"))
+sched_fusion_selective_ice (void)
+{
+(function "sched_fusion_selective_ice"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cnote 2 NOTE_INSN_FUNCTION_BEG)
+      (edge-to 3 (flags "FALLTHRU"))
+    )
+    (block 3
+      (edge-from 2 (flags "FALLTHRU"))
+      (edge-from 3)
+      (clabel 3 2)
+      (cnote 4 [bb 3] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 5 (set (reg:DI a2)
+                    (ashift:DI (reg:DI a2) (const_int 48))))
+      (cinsn 6 (set (reg:DI a1)
+                    (mult:DI (reg:DI a1) (reg:DI a4))))
+      (cinsn 7 (set (reg:DI a2)
+                    (lshiftrt:DI (reg:DI a2) (const_int 48))))
+      (cinsn 8 (set (reg:DI a0)
+                    (ashift:DI (reg:DI a0) (const_int 32))))
+      (cinsn 9 (set (reg:DI a0)
+                    (lshiftrt:DI (reg:DI a0) (const_int 32))))
+      (cinsn 10 (set (reg:DI a0)
+                     (plus:DI (reg:DI a0) (reg:DI a1))))
+      (cinsn 11 (set (reg:DI a0)
+                     (plus:DI (reg:DI a0) (reg:DI a2))))
+      (cinsn 12 (set (reg:DI a3)
+                     (plus:DI (reg:DI a3) (reg:DI a0))))
+      (cjump_insn 13 (set (pc)
+                         (if_then_else (ne (reg:DI a3) (const_int 0))
+                                       (label_ref 3) (pc))))
+      (edge-to 3)
+      (edge-to 4 (flags "FALLTHRU"))
+    )
+    (block 4
+      (edge-from 3 (flags "FALLTHRU"))
+      (cnote 14 [bb 4] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 15 (use (reg:DI a0)))
+      (cjump_insn 16 (simple_return))
+      (edge-to exit)
+    )
+    (cbarrier 17)
+  )
+  (crtl
+    (return_rtx (reg/i:DI a0))
+  )
+)
+}
diff --git a/gcc/testsuite/gcc.target/riscv/sched-fusion-selective.c 
b/gcc/testsuite/gcc.target/riscv/sched-fusion-selective.c
new file mode 100644
index 000000000000..39368bc817e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sched-fusion-selective.c
@@ -0,0 +1,42 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */
+/* { dg-options "-O2 -fselective-scheduling2 -fdump-rtl-sched2" } */
+/* { dg-additional-options "-march=rv64gc -mabi=lp64d" } */
+/* { dg-additional-options "-mtune=xiangshan-nanhu -fchecking=2" } */
+/* { dg-final { scan-rtl-dump "RISCV_FUSE_ZEXTW" "sched2" } } */
+/* { dg-final { scan-rtl-dump-not "RISCV_FUSE_ZEXTH" "sched2" } } */
+
+long __RTL (startwith ("sched2"))
+sched_fusion_selective (void)
+{
+(function "sched_fusion_selective"
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cnote 2 NOTE_INSN_FUNCTION_BEG)
+      (cinsn 5 (set (reg:DI a2)
+                    (ashift:DI (reg:DI a2) (const_int 48))))
+      (cinsn 6 (set (reg:DI a1)
+                    (mult:DI (reg:DI a1) (reg:DI a4))))
+      (cinsn 7 (set (reg:DI a2)
+                    (lshiftrt:DI (reg:DI a2) (const_int 48))))
+      (cinsn 8 (set (reg:DI a0)
+                    (ashift:DI (reg:DI a0) (const_int 32))))
+      (cinsn 9 (set (reg:DI a0)
+                    (lshiftrt:DI (reg:DI a0) (const_int 32))))
+      (cinsn 10 (set (reg:DI a0)
+                     (plus:DI (reg:DI a0) (reg:DI a1))))
+      (cinsn 11 (set (reg:DI a0)
+                     (plus:DI (reg:DI a0) (reg:DI a2))))
+      (cinsn 15 (use (reg:DI a0)))
+      (cjump_insn 16 (simple_return))
+      (edge-to exit)
+    )
+    (cbarrier 17)
+  )
+  (crtl
+    (return_rtx (reg/i:DI a0))
+  )
+)
+}

Reply via email to