https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128341
Bug ID: 128341
Summary: [AArch64] Trailing debug insns change SME mode-switch
insertion point
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: compare-debug-failure
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: aarch64-unknown-linux-gnu
Build: x86_64-pc-linux-gnu
Adding debug information changes where GCC inserts the SME lazy-save setup in a
basic block. On current trunk, -g0 places the add/msr that sets TPIDR2_EL0
before a store, while -g places the same setup after the store. GCC's own
-fcompare-debug check fails.
I reproduced this with GCC 17.0.0 20261031 (experimental), revision
f1114bb0f3ec67f2fb6bee88f22e148c3d7dedf4, targeting aarch64-unknown-linux-gnu.
Reproducer:
#include <arm_sme.h>
void ext (void);
void ext2 (void) __arm_inout ("za");
int g, h;
__arm_inout ("za") void
f2 (int x)
{
ext2 ();
if (x)
{
int y = x * 3;
g = y;
int z = y + h;
h = z;
int w = z * 5;
(void) w;
}
ext ();
ext2 ();
}
Command:
aarch64-linux-gnu-gcc -O1 -march=armv9-a+sme -ffreestanding \
-g -fcompare-debug -S source.c
Actual result:
cc1: error: source.c: '-fcompare-debug' failure
The relevant ordinary instructions differ as follows:
-g0:
add x2, x29, 32
msr tpidr2_el0, x2
str w0, [x1, 4]
-g:
str w0, [x1, 4]
add x0, x29, 32
msr tpidr2_el0, x0
Expected result:
Debug information should not change where mode switching inserts the TPIDR2
lazy-save setup. The -g and -g0 compilations should make the same
code-generation decision.
Cause analysis:
In optimize_mode_switching, a basic block with no mode requirement gets a
seginfo anchored at BB_END (bb). AArch64 LOCAL_SME_STATE back-propagation
later gives this seginfo the successor's lazy-save mode, and the mode-set
instructions are emitted before the saved anchor.
Without debug information, BB_END is the store to h, so the TPIDR2 setup is
emitted before the store. With -g, BB_END is a trailing DEBUG_INSN, so the
setup is emitted after the store instead.
A small candidate fix walks backward across only trailing DEBUG_INSNs when
choosing this anchor. It deliberately does not skip notes, so their existing
placement semantics are preserved.
Verification of the candidate fix on the revision above:
* The focused DejaGNU test fails on the unmodified compiler and passes with the
fix.
* -fcompare-debug passes with the fix.
* Comparing the complete AArch64 SME cross testsuite before and after the
change shows only the new regression test changing from FAIL to PASS; all
pre-existing results are unchanged.
* contrib/check_GNU_style.sh and git diff --check pass.
A full native bootstrap and regression test has not yet been run.
The test case was found by a non-AI automated testing tool. AI assisted with
the analysis and development of the candidate fix.