}
BitVector
-AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
+AArch64RegisterInfo::getStrictlyReservedRegs(const MachineFunction &MF) const {
const AArch64FrameLowering *TFI = getFrameLowering(MF);
// FIXME: avoid re-calculating this every time.
return Reserved;
}
+BitVector
+AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
+ BitVector Reserved = getStrictlyReservedRegs(MF);
+
+ for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) {
+ if (MF.getSubtarget<AArch64Subtarget>().isXRegisterReservedForRA(i))
+ markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i));
+ }
+
+ assert(checkAllSuperRegsMarked(Reserved));
+ return Reserved;
+}
+
bool AArch64RegisterInfo::isReservedReg(const MachineFunction &MF,
MCRegister Reg) const {
return getReservedRegs(MF)[Reg];
}
+bool AArch64RegisterInfo::isStrictlyReservedReg(const MachineFunction &MF,
+ MCRegister Reg) const {
+ return getStrictlyReservedRegs(MF)[Reg];
+}
+
bool AArch64RegisterInfo::isAnyArgRegReserved(const MachineFunction &MF) const {
return llvm::any_of(*AArch64::GPR64argRegClass.MC, [this, &MF](MCPhysReg r) {
- return isReservedReg(MF, r);
+ return isStrictlyReservedReg(MF, r);
});
}
}
bool isReservedReg(const MachineFunction &MF, MCRegister Reg) const;
+ bool isStrictlyReservedReg(const MachineFunction &MF, MCRegister Reg) const;
bool isAnyArgRegReserved(const MachineFunction &MF) const;
void emitReservedArgRegCallError(const MachineFunction &MF) const;
/// Stack probing calls preserve different CSRs to the normal CC.
const uint32_t *getWindowsStackProbePreservedMask() const;
+ BitVector getStrictlyReservedRegs(const MachineFunction &MF) const;
BitVector getReservedRegs(const MachineFunction &MF) const override;
bool isAsmClobberable(const MachineFunction &MF,
MCRegister PhysReg) const override;
"aarch64-insert-extract-base-cost",
cl::desc("Base cost of vector insert/extract element"), cl::Hidden);
+// Reserve a list of X# registers, so they are unavailable for register
+// allocator, but can still be used as ABI requests, such as passing arguments
+// to function call.
+static cl::list<std::string>
+ReservedRegsForRA("reserve-regs-for-regalloc", cl::desc("Reserve physical "
+ "registers, so they can't be used by register allocator. "
+ "Should only be used for testing register allocator."),
+ cl::CommaSeparated, cl::Hidden);
+
unsigned AArch64Subtarget::getVectorInsertExtractBaseCost() const {
if (OverrideVectorInsertExtractBaseCost.getNumOccurrences() > 0)
return OverrideVectorInsertExtractBaseCost;
unsigned MaxSVEVectorSizeInBitsOverride)
: AArch64GenSubtargetInfo(TT, CPU, TuneCPU, FS),
ReserveXRegister(AArch64::GPR64commonRegClass.getNumRegs()),
+ ReserveXRegisterForRA(AArch64::GPR64commonRegClass.getNumRegs()),
CustomCallSavedXRegs(AArch64::GPR64commonRegClass.getNumRegs()),
IsLittle(LittleEndian),
MinSVEVectorSizeInBits(MinSVEVectorSizeInBitsOverride),
*static_cast<const AArch64TargetMachine *>(&TM), *this, *RBI));
RegBankInfo.reset(RBI);
+
+ auto TRI = getRegisterInfo();
+ StringSet<> ReservedRegNames;
+ ReservedRegNames.insert(ReservedRegsForRA.begin(), ReservedRegsForRA.end());
+ for (unsigned i = 0; i < 31; ++i) {
+ if (ReservedRegNames.count(TRI->getName(AArch64::X0 + i)))
+ ReserveXRegisterForRA.set(i);
+ }
}
const CallLowering *AArch64Subtarget::getCallLowering() const {
// ReserveXRegister[i] - X#i is not available as a general purpose register.
BitVector ReserveXRegister;
+ // ReserveXRegisterForRA[i] - X#i is not available for register allocator.
+ BitVector ReserveXRegisterForRA;
+
// CustomCallUsedXRegister[i] - X#i call saved.
BitVector CustomCallSavedXRegs;
}
bool isXRegisterReserved(size_t i) const { return ReserveXRegister[i]; }
- unsigned getNumXRegisterReserved() const { return ReserveXRegister.count(); }
+ bool isXRegisterReservedForRA(size_t i) const { return ReserveXRegisterForRA[i]; }
+ unsigned getNumXRegisterReserved() const {
+ BitVector AllReservedX(AArch64::GPR64commonRegClass.getNumRegs());
+ AllReservedX |= ReserveXRegister;
+ AllReservedX |= ReserveXRegisterForRA;
+ return AllReservedX.count();
+ }
bool isXRegCustomCalleeSaved(size_t i) const {
return CustomCallSavedXRegs[i];
}
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x5 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X5
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x6 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X6
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x7 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X7
+; RUN: llc -mtriple=arm64-linux-gnu -reserve-regs-for-regalloc=X8 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X8
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x9 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X9
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x10 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X10
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x11 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X11
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x13 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X13
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x14 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X14
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x15 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X15
+; RUN: llc -mtriple=arm64-linux-gnu -reserve-regs-for-regalloc=X16 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X16
+; RUN: llc -mtriple=arm64-linux-gnu -reserve-regs-for-regalloc=X17 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X17
+; RUN: llc -mtriple=arm64-linux-gnu -reserve-regs-for-regalloc=X19 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X19
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x20 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X20
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x21 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X21
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x22 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X22
; RUN: -mattr=+reserve-x27 \
; RUN: -mattr=+reserve-x28 \
; RUN: -mattr=+reserve-x30 \
+; RUN: -reserve-regs-for-regalloc=X8,X16,X17,X19 \
; RUN: -o - %s | FileCheck %s \
; RUN: --check-prefix=CHECK-RESERVE \
; RUN: --check-prefix=CHECK-RESERVE-X1 \
; RUN: --check-prefix=CHECK-RESERVE-X5 \
; RUN: --check-prefix=CHECK-RESERVE-X6 \
; RUN: --check-prefix=CHECK-RESERVE-X7 \
+; RUN: --check-prefix=CHECK-RESERVE-X8 \
; RUN: --check-prefix=CHECK-RESERVE-X9 \
; RUN: --check-prefix=CHECK-RESERVE-X10 \
; RUN: --check-prefix=CHECK-RESERVE-X11 \
; RUN: --check-prefix=CHECK-RESERVE-X13 \
; RUN: --check-prefix=CHECK-RESERVE-X14 \
; RUN: --check-prefix=CHECK-RESERVE-X15 \
+; RUN: --check-prefix=CHECK-RESERVE-X16 \
+; RUN: --check-prefix=CHECK-RESERVE-X17 \
; RUN: --check-prefix=CHECK-RESERVE-X18 \
+; RUN: --check-prefix=CHECK-RESERVE-X19 \
; RUN: --check-prefix=CHECK-RESERVE-X20 \
; RUN: --check-prefix=CHECK-RESERVE-X21 \
; RUN: --check-prefix=CHECK-RESERVE-X22 \
; CHECK: str x18
; CHECK-RESERVE-NOT: ldr fp
+; CHECK-RESERVE-X8-NOT: adrp x8
+; CHECK-RESERVE-X8-NOT: ldr x8
; CHECK-RESERVE-X1-NOT: ldr x1,
; CHECK-RESERVE-X2-NOT: ldr x2,
; CHECK-RESERVE-X3-NOT: ldr x3,
; CHECK-RESERVE-X13-NOT: ldr x13,
; CHECK-RESERVE-X14-NOT: ldr x14,
; CHECK-RESERVE-X15-NOT: ldr x15,
+; CHECK-RESERVE-X16-NOT: ldr x16
+; CHECK-RESERVE-X17-NOT: ldr x17
; CHECK-RESERVE-X18-NOT: ldr x18
+; CHECK-RESERVE-X19-NOT: ldr x19
; CHECK-RESERVE-X20-NOT: ldr x20
; CHECK-RESERVE-X21-NOT: ldr x21
; CHECK-RESERVE-X22-NOT: ldr x22
; CHECK-RESERVE-X13-NOT: ldr x13,
; CHECK-RESERVE-X14-NOT: ldr x14,
; CHECK-RESERVE-X15-NOT: ldr x15,
+; CHECK-RESERVE-X16-NOT: ldr x16
+; CHECK-RESERVE-X17-NOT: ldr x17
; CHECK-RESERVE-X18-NOT: ldr x18
+; CHECK-RESERVE-X19-NOT: ldr x19
; CHECK-RESERVE-X20-NOT: ldr x20
; CHECK-RESERVE-X21-NOT: ldr x21
; CHECK-RESERVE-X22-NOT: ldr x22