https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127796

            Bug ID: 127796
           Summary: [SPARC] DEBUG_INSN between consecutive labels makes -g
                    redirect jumps differently
           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: sparc-unknown-elf
             Build: x86_64-pc-linux-gnu

GCC's existing `gcc.c-torture/compile/pr110705-1.c` test produces different
post-delay-slot-scheduling output with `-g` and `-g0` on SPARC when variable
tracking is disabled. This reproduces on GCC trunk at revision
`54e232d0d4752b419ed775bdad50d83798fa899d` with GCC 17.0.0 20261009. The
affected `skip_consecutive_labels` implementation remains unchanged on master
revision `59e5dcee5375614cf1cc58e97dcc04f63bc9b519`.

## Reproducer

Using a `sparc-elf` compiler built from that revision:

```
$ sparc-elf-gcc -O1 -w -fno-var-tracking -fcompare-debug -S \
    gcc/testsuite/gcc.c-torture/compile/pr110705-1.c
cc1: error: ...: '-fcompare-debug' failure (length)
```

The same source also reproduces when copied unchanged out of the testsuite.

## Actual behavior

The `-g` and `-g0` assemblies have different branch targets and label counts.
After label names are erased, their executable instructions are identical, so
this report is about debug information changing delay-slot reorganization, not
about a known runtime miscompilation.

The first differing pass is `dbr`. Before that pass, the relevant instruction
streams differ only by a debug marker between two labels. With `-g0`,
`relax_delay_slots` redirects the jump to the last label in the group and the
first label is deleted. With `-g`, the debug marker hides the later label, so
the jump keeps the first label.

## Cause

`skip_consecutive_labels` in `gcc/reorg.cc` stops at every `INSN_P`:

```c
for (insn = label;
     insn != 0 && !INSN_P (insn) && !BARRIER_P (insn);
     insn = NEXT_INSN (insn))
```

`INSN_P` is true for a `DEBUG_INSN`, even though a debug instruction should not
be an executable boundary when choosing among consecutive labels.

The reproducer is SPARC because that target exercises this path, but
`skip_consecutive_labels` is part of GCC's generic delay-slot reorganization
code rather than the SPARC backend.

This is related to PR rtl-optimization/127725, but that report covers different
sites in `optimize_skip`, `get_label_before`, and `fill_slots_from_thread`. It
does not cover `skip_consecutive_labels`. A Bugzilla duplicate search was
refreshed on 2026-10-10 and found no report for this site.

## Proposed fix

Changing the condition to `!NONDEBUG_INSN_P (insn)` makes both builds choose
the same label. A patch and a focused `gcc.target/sparc` `-fcompare-debug` test
are prepared. The test fails before the change and passes after it.

The patch passes `contrib/check_GNU_style.sh` and `git diff --check`. A native
x86_64 build containing this fix and three sibling delay-slot fixes completed
bootstrap and the full testsuite. After normalizing the build-directory path
embedded in one module test name, all 541,492 baseline and combined-patch
test-result records were identical.

Reply via email to