diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h @@ -35,6 +35,7 @@ } 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; @@ -88,6 +89,7 @@ /// 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; diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -309,7 +309,7 @@ } 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. @@ -355,14 +355,32 @@ 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().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); }); } diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -110,6 +110,9 @@ // 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; @@ -196,7 +199,13 @@ } 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]; } diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp --- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp @@ -56,6 +56,15 @@ "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 +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; @@ -265,6 +274,7 @@ unsigned MaxSVEVectorSizeInBitsOverride) : AArch64GenSubtargetInfo(TT, CPU, TuneCPU, FS), ReserveXRegister(AArch64::GPR64commonRegClass.getNumRegs()), + ReserveXRegisterForRA(AArch64::GPR64commonRegClass.getNumRegs()), CustomCallSavedXRegs(AArch64::GPR64commonRegClass.getNumRegs()), IsLittle(LittleEndian), MinSVEVectorSizeInBits(MinSVEVectorSizeInBitsOverride), @@ -287,6 +297,14 @@ *static_cast(&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 { diff --git a/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll b/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll --- a/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll +++ b/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll @@ -13,6 +13,7 @@ ; 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 @@ -20,6 +21,9 @@ ; 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 @@ -69,6 +73,7 @@ ; 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 \ @@ -78,6 +83,7 @@ ; 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 \ @@ -85,7 +91,10 @@ ; 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 \ @@ -113,6 +122,8 @@ ; 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, @@ -127,7 +138,10 @@ ; 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 @@ -154,7 +168,10 @@ ; 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