Skip to content

Commit 40dafea

Browse files
committed
[AArch64] Stop manually reserved registers from 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.
1 parent 4e81ee4 commit 40dafea

File tree

3 files changed

+25
-0
lines changed

3 files changed

+25
-0
lines changed

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3619,6 +3619,12 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF,
36193619
if (Reg == BasePointerReg)
36203620
SavedRegs.set(Reg);
36213621

3622+
// Don't save manually reserved registers set through -ffixed-reg.
3623+
if (RegInfo->isUserReservedReg(MF, Reg)) {
3624+
SavedRegs.reset(Reg);
3625+
continue;
3626+
}
3627+
36223628
bool RegUsed = SavedRegs.test(Reg);
36233629
unsigned PairedReg = AArch64::NoRegister;
36243630
const bool RegIsGPR64 = AArch64::GPR64RegClass.contains(Reg);

llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,18 @@ AArch64RegisterInfo::getStrictlyReservedRegs(const MachineFunction &MF) const {
518518
return Reserved;
519519
}
520520

521+
BitVector
522+
AArch64RegisterInfo::getUserReservedRegs(const MachineFunction &MF) const {
523+
BitVector Reserved(getNumRegs());
524+
for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
525+
// ReserveXRegister is set for registers manually reserved
526+
// through -ffixed-reg.
527+
if (MF.getSubtarget<AArch64Subtarget>().isXRegisterReserved(i))
528+
markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i));
529+
}
530+
return Reserved;
531+
}
532+
521533
BitVector
522534
AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
523535
BitVector Reserved(getNumRegs());
@@ -551,6 +563,11 @@ bool AArch64RegisterInfo::isReservedReg(const MachineFunction &MF,
551563
return getReservedRegs(MF)[Reg];
552564
}
553565

566+
bool AArch64RegisterInfo::isUserReservedReg(const MachineFunction &MF,
567+
MCRegister Reg) const {
568+
return getUserReservedRegs(MF)[Reg];
569+
}
570+
554571
bool AArch64RegisterInfo::isStrictlyReservedReg(const MachineFunction &MF,
555572
MCRegister Reg) const {
556573
return getStrictlyReservedRegs(MF)[Reg];

llvm/lib/Target/AArch64/AArch64RegisterInfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class AArch64RegisterInfo final : public AArch64GenRegisterInfo {
3535
}
3636

3737
bool isReservedReg(const MachineFunction &MF, MCRegister Reg) const;
38+
bool isUserReservedReg(const MachineFunction &MF, MCRegister Reg) const;
3839
bool isStrictlyReservedReg(const MachineFunction &MF, MCRegister Reg) const;
3940
bool isAnyArgRegReserved(const MachineFunction &MF) const;
4041
void emitReservedArgRegCallError(const MachineFunction &MF) const;
@@ -93,6 +94,7 @@ class AArch64RegisterInfo final : public AArch64GenRegisterInfo {
9394
const uint32_t *getWindowsStackProbePreservedMask() const;
9495

9596
BitVector getStrictlyReservedRegs(const MachineFunction &MF) const;
97+
BitVector getUserReservedRegs(const MachineFunction &MF) const;
9698
BitVector getReservedRegs(const MachineFunction &MF) const override;
9799
std::optional<std::string>
98100
explainReservedReg(const MachineFunction &MF,

0 commit comments

Comments
 (0)