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.