https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127809
Bug ID: 127809
Summary: [MIPS/SPARC] DEBUG_INSN stops delete_related_insns
before a BARRIER
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: yqtian668 at gmail dot com
Target Milestone: ---
Host: x86_64-pc-linux-gnu
Target: mips-elf and sparc-elf
Build: x86_64-pc-linux-gnu
Created attachment 65797
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65797&action=edit
patch
This was found while investigating PR rtl-optimization/127808. While checking
those sites, I found a separate instance in jump.cc::delete_related_insns.
This reproduces with GCC trunk at revision
a02e2004cb707155d5b9b0a82dd428ded0ee2f6f. It also affects the existing GCC test
gcc.dg/builtin-unreachable-1.c on mips-elf at -Os when compiled with -g
-fno-var-tracking -fcompare-debug.
Small sparc-elf reproducer:
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;
}
Compile with:
sparc-elf-gcc -Os -g -fno-var-tracking -fcompare-debug -S source.c
Actual behavior:
The command reports a compare-debug failure. The -g output retains an
unreachable branch and delay-slot instruction after a deleted label, while -g0
removes them. The small reproducer is a code-size difference rather than wrong
code.
Root cause:
When delete_related_insns deletes a CODE_LABEL, it walks backward over deleted
instructions and notes to find a preceding BARRIER. The loop is currently:
while (prev && (prev->deleted () || NOTE_P (prev)))
prev = PREV_INSN (prev);
A DEBUG_INSN stops this walk, so the BARRIER is found with -g0 but hidden with
-g. Including DEBUG_INSN_P (prev) in the skipped nodes makes the result
independent of debug information.
The debug instruction position is produced by GCC itself: cleanup_barriers can
move a BARRIER in front of debug markers in a block containing an address-taken
label and __builtin_unreachable ().
Testing of the candidate fix:
* A targeted gcc.target/sparc test fails before the fix and passes after it.
* The existing gcc.dg/builtin-unreachable-1.c is the natural mips-elf trigger
found in the GCC testsuite.
* A complete sparc-elf check-gcc comparison has no new unexpected results.
* An x86_64-pc-linux-gnu native bootstrap and complete make -k check, with and
without the patch at the revision above, have identical test outcomes after
normalizing build paths.
Relationship to the relax_delay_slots issue PR rtl-optimization/127808:
This change relies on a BARRIER before the label correctly proving that no path
falls through. The related relax_delay_slots bug can violate that assumption
under -g, so its fix should be applied before or together with this one.