[llvm] [AArch64] Fix reserved registers being saved in prolog/epilog (PR #138448)
via llvm-commits
llvm-commits at lists.llvm.org
Sun May 4 03:50:31 PDT 2025
https://github.com/yasuna-oribe created https://github.com/llvm/llvm-project/pull/138448
GCC's man page is clear on how -ffixed-reg must behave:
```
Treat the register named reg as a fixed register; generated
code should never refer to it (except perhaps as a stack pointer,
frame pointer or in some other fixed role).
```
This implies prolog/epilog code also must not save/restore explicitly fixed registers, even when it is callee-saved. Some projects rely on this (GCC's) behavior.
For example,
```
void f() {
register uint64_t x28 asm("x28") = 0xee;
asm volatile("" : "+r"(x28)); // avoid mov being eliminated
}
```
should not touch x28 outside of `mov w28,#0xee`.
For riscv64, clang behaves the same as GCC, so I am inclined to believe this is indeed a bug.
Fixes #111379.
>From 400525f01121116789ac364abefdc37ce9709a6c Mon Sep 17 00:00:00 2001
From: oribe yasuna <or at dmc.chat>
Date: Sun, 4 May 2025 10:35:35 +0000
Subject: [PATCH] [AArch64] Fix reserved registers being saved in prolog/epilog
GCC's man page is clear on how -ffixed-reg must behave:
```
Treat the register named reg as a fixed register; generated
code should never refer to it (except perhaps as a stack pointer,
frame pointer or in some other fixed role).
```
This implies prolog/epilog code also must not save/restore explicitly
fixed registers, even when it is callee-saved. Some projects rely on
this (GCC's) behavior.
For example,
```
void f() {
register uint64_t x28 asm("x28") = 0xee;
asm volatile("" : "+r"(x28)); // avoid mov being eliminated
}
```
should not touch x28 outside of `mov w28,#0xee`.
For riscv64 clang behaves the same as GCC.
Fixes #111379.
---
llvm/lib/Target/AArch64/AArch64FrameLowering.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
index 78ac57e3e92a6..2d72f8757d7c0 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -3619,6 +3619,13 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF,
if (Reg == BasePointerReg)
SavedRegs.set(Reg);
+ // Don't save fixed registers specified with -ffixed-reg.
+ if (AArch64::GPR64RegClass.contains(Reg) &&
+ RegInfo->isReservedReg(MF, Reg)) {
+ SavedRegs.reset(Reg);
+ continue;
+ }
+
bool RegUsed = SavedRegs.test(Reg);
unsigned PairedReg = AArch64::NoRegister;
const bool RegIsGPR64 = AArch64::GPR64RegClass.contains(Reg);
More information about the llvm-commits
mailing list