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.
  • [Bug rtl-optimization/127809] N... yqtian668 at gmail dot com via Gcc-bugs

Reply via email to