When delete_related_insns deletes a CODE_LABEL, it walks backward over
deleted instructions and notes to find a preceding BARRIER. A
DEBUG_INSN stops the walk, so unreachable code can be retained with -g
but deleted with -g0.
Skip debug insns in the walk. Add a SPARC regression test. GCC's
existing gcc.dg/builtin-unreachable-1.c is also a natural trigger on
mips-elf at -Os with -g -fno-var-tracking -fcompare-debug.
This was found during the PR127808 investigation prompted by Jeff's
PR127795 review. The patch is independently applicable, but is ordered
after patch 1 because delete_related_insns relies on a BARRIER correctly
proving that no path falls through.
Tested at GCC revision a02e2004cb707155d5b9b0a82dd428ded0ee2f6f:
* With patch 1 applied but without this patch, the new SPARC test fails;
with both patches it passes.
* The existing gcc.dg/builtin-unreachable-1.c fails on baseline mips-elf
at -Os with -g -fno-var-tracking -fcompare-debug and passes with this
fix.
* A complete sparc-elf `make -k -j8 check-gcc` comparison has no
regressions.
* Native x86_64-pc-linux-gnu bootstrap and complete `make -k -j24 check`
have the same normalized outcomes with and without the two-patch
series, as reported in patch 1.
* `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/127809
gcc/ChangeLog:
* jump.cc (delete_related_insns): Ignore debug insns when looking for
a BARRIER before a deleted label.
gcc/testsuite/ChangeLog:
* gcc.target/sparc/delete-related-insns-debug.c: New test.
Signed-off-by: Yongqiang Tian <[email protected]>
---
gcc/jump.cc | 2 +-
.../sparc/delete-related-insns-debug.c | 27 +++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/sparc/delete-related-insns-debug.c
diff --git a/gcc/jump.cc b/gcc/jump.cc
index 75158924c..973c776fe 100644
--- a/gcc/jump.cc
+++ b/gcc/jump.cc
@@ -1281,7 +1281,7 @@ delete_related_insns (rtx uncast_insn)
if (LABEL_NUSES (XEXP (note, 0)) == 0)
delete_related_insns (XEXP (note, 0));
- while (prev && (prev->deleted () || NOTE_P (prev)))
+ while (prev && (prev->deleted () || NOTE_P (prev) || DEBUG_INSN_P (prev)))
prev = PREV_INSN (prev);
/* If INSN was a label and a dispatch table follows it,
diff --git a/gcc/testsuite/gcc.target/sparc/delete-related-insns-debug.c
b/gcc/testsuite/gcc.target/sparc/delete-related-insns-debug.c
new file mode 100644
index 000000000..2e0da504c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/delete-related-insns-debug.c
@@ -0,0 +1,27 @@
+/* PR rtl-optimization/127809 */
+/* { dg-do compile } */
+/* { dg-require-effective-target label_values } */
+/* { dg-options "-Os -fno-var-tracking -fcompare-debug" } */
+
+/* When reorg deletes a label that follows a BARRIER and a block holding
+ only debug insns, the code after the label is unreachable and must be
+ deleted with -g as well as with -g0. */
+
+int h;
+
+void
+foo (int b, int c)
+{
+ int i = b * 3;
+ void *x = &&lab;
+l1:
+ if (b)
+ {
+ lab:
+ __builtin_unreachable ();
+ }
+ h = i;
+ if (c)
+ x = &&l1;
+ goto *x;
+}
--
2.34.1