https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128010
Bug ID: 128010
Summary: aarch64 has no asm clobber syntax for the top bits of
sve z regs needed by syscalls
Product: gcc
Version: 16.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: nsz at gcc dot gnu.org
Target Milestone: ---
linux syscalls clobber the top bits of z0..z31 registers, but
preserve the bottom 128bits (q0..q31).
this cannot be expressed by inline assembly clobbers: using full
z0..z31 clobber would spill d8..d15 around syscalls (callee saved
fp regs in the c call abi, preserved by linux), the point of
inline syscalls is to minimize register spills and shuffling so
such spill is not acceptable.
ideally we would be able to say that "q9 is clobbered but d9 is not"
for any subreg that can be named. but for libc a "z above bit 128"
clobber is enough for now.
affects code that wants to do syscalls inline and compiled (or lto
linked) with -march=armv8-a+sve.
glibc is affected when built with sve. it was found in musl libc.
(p regs got clobbered by syscalls when building with clang+sve)
example that is unsafe without z reg clobber but spills d regs with:
static inline long sys1(long n, long a)
{
register long x8 __asm__("x8") = n;
register long x0 __asm__("x0") = a;
asm volatile ("svc 0" : "=r"(x0) : "r"(x8), "0"(x0) :
"z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7",
"z8", "z9", "z10", "z11", "z12", "z13", "z14", "z15",
"z16", "z17", "z18", "z19", "z20", "z21", "z22", "z23",
"z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7",
"p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",
"ffr", "memory");
return x0;
}
void foo(int *p)
{
int i;
for (i=0; i<512; i++) {
p[i] += 1234;
}
sys1(1, 2);
for (i=0; i<512; i++) {
p[i] += 1234;
}
}