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

            Bug ID: 127687
           Summary: -fcompare-debug failure when GIMPLE_DEBUG splits
                    forwprop VEC_PERM sequence blending
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: yqtian668 at gmail dot com
  Target Milestone: ---

Created attachment 65731
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65731&action=edit
input

GCC fails its `-fcompare-debug` check for the attached existing GCC testcase
`gcc.dg/pr123672.c` at `-O2`.  Adding debug information also changes the final
x86-64 instruction sequence.

Tested revision:

```text
fc79df73ccd91f677c5990a3dadd83e2620404f9
gcc version 17.0.0 20260826 (experimental) (GCC)
```

The build was configured with:

```text
--target=x86_64-pc-linux-gnu --disable-bootstrap --enable-languages=c
--disable-multilib --disable-nls --disable-werror --enable-checking=yes
```

Command:

```sh
xgcc -B/path/to/gcc -O2 -fcompare-debug -c pr123672.c -o pr123672.o
```

Actual result:

```text
xgcc: error: pr123672.c: '-fcompare-debug' failure (length)
```

Compiling the source separately with `-g0` and `-g` produces different
`.text` sections.  The full ordinary-instruction diff is attached as
`instructions-g0-vs-g.diff`.  In particular, the `-g0` compilation blends the
two vector-permute sequences and uses two `shufps` instructions, whereas the
`-g` compilation keeps the sequences separate and uses four `pshufd`
instructions.

The first ordinary compiler-state difference occurs in forwprop.  The
statement loop in `pass_forwprop::execute` accumulates simplifiable VEC_PERM
sequences and processes them as a list so that compatible pairs can be
blended.  It currently processes that list at every non-assignment statement:

```c++
if (!is_gimple_assign (stmt))
  {
    process_vec_perm_simplify_seq_list (&vec_perm_simplify_seq_list);
    gsi_next (&gsi);
    continue;
  }
```

A `GIMPLE_DEBUG` bind is not an assignment.  With `-g`, a debug bind between
the two compatible sequences therefore processes the first sequence before
the second one is available, preventing the pair from being blended.

As a causal check, I made a diagnostic change that skips `GIMPLE_DEBUG`
statements before the non-assignment check.  With only that change:

- `-fcompare-debug` passes;
- the patched `-g` and `-g0` `.text` sections are byte-identical; and
- the patched `-g0` `.text` is byte-identical to the unmodified `-g0` output.

The diagnostic change is attached to document the causal check; it is not
intended to prescribe the final patch or its regression test.

The same non-assignment flush is still present in GCC master revision
`2e70e94cef1d76dbb3202d64184a7a8329c92f4e` by source inspection.  The
execution results above are from the tested revision `fc79df73ccd9`.

This is distinct from PR tree-optimization/123672.  That issue is the
wrong-code problem for which this testcase was originally added; the problem
reported here is the debug-dependent boundary in the later sequence-blending
logic.

Expected result: a non-executable debug bind should not end a pending
VEC_PERM sequence or change the generated ordinary code.

Reply via email to