https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127422
Bug ID: 127422
Summary: [AArch64] -fcompare-debug failure in combine when a
DEBUG_INSN retains a volatile MEM -
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 65601
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65601&action=edit
Standalone AArch64 C testcase
GCC trunk fails its -fcompare-debug check for the attached standalone C
testcase when targeting AArch64.
Tested revision:
2c3724c84c139c70c034816cc37f5dfb7f256815
Command:
aarch64-linux-gnu-gcc -std=gnu11 -w -O2 -mno-track-speculation \
-fcompare-debug -S repro.c
Actual result:
xgcc: error: repro.c: '-fcompare-debug' failure (length)
The testcase is header-free and does not require Csmith or a target sysroot.
The ordinary RTL is identical between the two profiles through ext_dce and
first differs in combine. The relevant sequence contains two volatile loads.
After Combine folds the second load into its consumer and deletes the ordinary
load, the no-debug profile can retry and combine the first load.
With variable tracking enabled, propagate_for_debug retains the deleted second
load's volatile MEM in a DEBUG_INSN. can_combine_p then scans the open interval
using raw INSN_P membership:
for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p))
if (INSN_P (p) && p != succ && p != succ2
&& is_volatile_p (PATTERN (p)))
return false;
Because INSN_P includes DEBUG_INSN, the non-executing debug value is treated
as another volatile access and blocks the retry. At that point the debug
instruction is the only volatile reference in the interval; there is no
ordinary volatile instruction there.
As a causal check, changing only this membership test from INSN_P to
NONDEBUG_INSN_P has the following results:
- the debug retry changes from rejected to allowed;
- -fcompare-debug changes from failure to success;
- the no-debug output is unchanged; and
- the debug output becomes identical to that no-debug output.
Expected result: debug-only instructions must not act as operational volatile
accesses or change the generated ordinary code.