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

            Bug ID: 127423
           Summary: [RISC-V] -fcompare-debug failure in
                    noce_get_alt_condition when a DEBUG_INSN overlaps
                    if_info->x
           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: ---

Created attachment 65602
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65602&action=edit
source input to trigger this bug

GCC trunk fails its `-fcompare-debug` check for the attached standalone C
testcase when targeting RISC-V with Zbb enabled.

Tested revision:

```text
891246665b51b4fc662f08f706f1c7523b8800c4
```

Command:

```sh
riscv64-unknown-linux-gnu-gcc -std=gnu11 -O2 \
  -fno-tree-forwprop \
  -fdisable-tree-phiopt1 -fdisable-tree-phiopt2 \
  -fdisable-tree-phiopt3 -fdisable-tree-phiopt4 \
  -march=rv64gc_zbb -mabi=lp64d -ffunction-sections \
  -fcompare-debug -S source.c
```

Actual result:

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

The testcase is header-free and does not require a target sysroot.  The pass
control options preserve the small source shape until RTL if-conversion; they
are accepted GCC options and the failure is deterministic.

Without debug information, the relevant ordinary instructions are:

```asm
slt     a5,a0,a1
min     a0,a0,a1
ret
```

With debug information, GCC instead emits:

```asm
slt     a5,a0,a1
bne     a5,zero,.L2
mv      a0,a1
ret
```

The first ordinary RTL difference occurs in the second RTL if-conversion pass
(`ce2`).  `noce_get_alt_condition` verifies that `if_info->x` is not mentioned
in `(cond_earliest, jump]` using this raw scan:

```c++
for (insn = if_info->jump; insn != *earliest; insn = PREV_INSN (insn))
  if (INSN_P (insn)
      && reg_overlap_mentioned_p (if_info->x, PATTERN (insn)))
    return NULL;
```

`INSN_P` includes `DEBUG_INSN`.  In the debug compilation, a source-only local
becomes a `VAR_LOCATION` that mentions the same pseudo as `if_info->x`.  That
non-executable debug payload therefore triggers the overlap veto and prevents
`noce_try_minmax`, even though the ordinary projection of the interval has no
overlapping use.

As a causal check, changing only the membership test to
`NONDEBUG_INSN_P (insn)` makes `-fcompare-debug` pass and restores the same
ordinary min/max transformation in both modes.  I have a tested candidate
patch and regression test prepared; the regression test fails on unmodified
trunk and passes after the change.

This is related to, but distinct from, PR debug/100852.  That issue changed
neighbor lookups in `noce_get_alt_condition` to
`prev_nonnote_nondebug_insn`; the interval scan above still uses `INSN_P` and
is not covered by that fix.  Bugzilla searches for `noce_get_alt_condition`,
`noce_try_minmax`, RISC-V `-fcompare-debug`, and the relevant debug payload did
not find an existing report for this scan.

Expected result: debug-only payloads should not affect the ordinary lifetime
check or change whether RTL if-conversion forms the min operation.

Reply via email to