skip_consecutive_labels walks across labels and notes until it reaches an
INSN_P.  A DEBUG_INSN satisfies INSN_P, so a debug marker between two
labels can hide the later label.  This makes branch redirection depend on
whether debug information is present and causes an -fcompare-debug
failure.

This issue was already tracked as PR127796.  Jeff Law also suggested
auditing this site while reviewing the PR127808 patch.  This patch uses
NONDEBUG_INSN_P as the stopping condition and adds a focused SPARC
regression test derived from gcc.c-torture/compile/pr110705-1.c.

Tested at GCC revision ca33fb40100211b9ed8c2e686b46cb9025791930:

* The new test fails without the patch with an -fcompare-debug length
  mismatch and passes with the patch.
* A complete sparc-elf sparc.exp comparison has no regressions; the only
  difference is the new test changing from absent to PASS.
* Native x86_64-pc-linux-gnu bootstrap and full regression testing
  completed for the baseline and the exact patch.  Both produced 530002
  PASS, 9 FAIL, 1 XPASS, 4292 XFAIL, and 7556 UNSUPPORTED results, with
  identical unexpected-result sets.
* contrib/check_GNU_style.sh and git diff --check pass.

Assisted-by: OpenAI Codex 5.6 Sol, co-reviewed by Claude and Yongqiang Tian.

        PR rtl-optimization/127796

gcc/ChangeLog:

        * reorg.cc (skip_consecutive_labels): Ignore debug instructions
        when scanning consecutive labels.

gcc/testsuite/ChangeLog:

        * gcc.target/sparc/reorg-skip-labels-debug.c: New test.

Signed-off-by: Yongqiang Tian <[email protected]>
---
 gcc/reorg.cc                                  |  2 +-
 .../sparc/reorg-skip-labels-debug.c           | 41 +++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/sparc/reorg-skip-labels-debug.c

diff --git a/gcc/reorg.cc b/gcc/reorg.cc
index e5eaa303c..8a865fa9e 100644
--- a/gcc/reorg.cc
+++ b/gcc/reorg.cc
@@ -138,7 +138,7 @@ skip_consecutive_labels (rtx label_or_return)
 
      So we explicitly disallow looking through BARRIERS here.  */
   for (insn = label;
-       insn != 0 && !INSN_P (insn) && !BARRIER_P (insn);
+       insn != 0 && !NONDEBUG_INSN_P (insn) && !BARRIER_P (insn);
        insn = NEXT_INSN (insn))
     if (LABEL_P (insn))
       label = insn;
diff --git a/gcc/testsuite/gcc.target/sparc/reorg-skip-labels-debug.c 
b/gcc/testsuite/gcc.target/sparc/reorg-skip-labels-debug.c
new file mode 100644
index 000000000..930b81cb4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/reorg-skip-labels-debug.c
@@ -0,0 +1,41 @@
+/* PR rtl-optimization/127796 */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-var-tracking -fcompare-debug" } */
+
+/* Keep debug markers as DEBUG_INSNs through delay-slot reorg.  */
+
+/* Taken from gcc.c-torture/compile/pr110705-1.c.  */
+
+struct a {
+  long b;
+};
+union d {
+  struct a b;
+  int e;
+} v;
+long c;
+int f;
+
+static void
+g (union d h, long i)
+{
+  while (1)
+    switch (c)
+    case 4:
+      if (h.e)
+       c = 4;
+}
+
+void
+j (union d *h)
+{
+  if (f)
+    g (*h, h->b.b);
+}
+
+void
+k ()
+{
+  union d *h = &v;
+  j (h);
+}
-- 
2.34.1

Reply via email to