Index: lib/Target/AArch64/AArch64.td =================================================================== --- lib/Target/AArch64/AArch64.td +++ lib/Target/AArch64/AArch64.td @@ -72,13 +72,10 @@ "Disallow all unaligned memory " "access">; -def FeatureReserveX18 : SubtargetFeature<"reserve-x18", "ReserveX18", "true", - "Reserve X18, making it unavailable " - "as a GPR">; - -def FeatureReserveX20 : SubtargetFeature<"reserve-x20", "ReserveX20", "true", - "Reserve X20, making it unavailable " - "as a GPR">; +foreach i = {1-7,18,20} in + def FeatureReserveX#i : SubtargetFeature<"reserve-x"#i, "ReserveXRegister["#i#"]", "true", + "Reserve X"#i#", making it unavailable " + "as a GPR">; def FeatureUseAA : SubtargetFeature<"use-aa", "UseAA", "true", "Use alias analysis during codegen">; Index: lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64FrameLowering.cpp +++ lib/Target/AArch64/AArch64FrameLowering.cpp @@ -1193,7 +1193,7 @@ // we also need to save lr in the shadow call stack. if ((RPI.Reg1 == AArch64::LR || RPI.Reg2 == AArch64::LR) && MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)) { - if (!MF.getSubtarget().isX18Reserved()) + if (!MF.getSubtarget().isXRegisterReserved(18)) report_fatal_error("Must reserve x18 to use shadow call stack"); NeedShadowCallStackProlog = true; } Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -4952,15 +4952,43 @@ SelectionDAG &DAG) const { unsigned Reg = StringSwitch(RegName) .Case("sp", AArch64::SP) + .Case("x1", AArch64::X1) + .Case("w1", AArch64::W1) + .Case("x2", AArch64::X2) + .Case("w2", AArch64::W2) + .Case("x3", AArch64::X3) + .Case("w3", AArch64::W3) + .Case("x4", AArch64::X4) + .Case("w4", AArch64::W4) + .Case("x5", AArch64::X5) + .Case("w5", AArch64::W5) + .Case("x6", AArch64::X6) + .Case("w6", AArch64::W6) + .Case("x7", AArch64::X7) + .Case("w7", AArch64::W7) .Case("x18", AArch64::X18) .Case("w18", AArch64::W18) .Case("x20", AArch64::X20) .Case("w20", AArch64::W20) .Default(0); - if (((Reg == AArch64::X18 || Reg == AArch64::W18) && - !Subtarget->isX18Reserved()) || + if (((Reg == AArch64::X1 || Reg == AArch64::W1) && + !Subtarget->isXRegisterReserved(1)) || + ((Reg == AArch64::X2 || Reg == AArch64::W2) && + !Subtarget->isXRegisterReserved(2)) || + ((Reg == AArch64::X3 || Reg == AArch64::W3) && + !Subtarget->isXRegisterReserved(3)) || + ((Reg == AArch64::X4 || Reg == AArch64::W4) && + !Subtarget->isXRegisterReserved(4)) || + ((Reg == AArch64::X5 || Reg == AArch64::W5) && + !Subtarget->isXRegisterReserved(5)) || + ((Reg == AArch64::X6 || Reg == AArch64::W6) && + !Subtarget->isXRegisterReserved(6)) || + ((Reg == AArch64::X7 || Reg == AArch64::W7) && + !Subtarget->isXRegisterReserved(7)) || + ((Reg == AArch64::X18 || Reg == AArch64::W18) && + !Subtarget->isXRegisterReserved(18)) || ((Reg == AArch64::X20 || Reg == AArch64::W20) && - !Subtarget->isX20Reserved())) + !Subtarget->isXRegisterReserved(20))) Reg = 0; if (Reg) return Reg; Index: lib/Target/AArch64/AArch64RegisterInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64RegisterInfo.cpp +++ lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -134,11 +134,10 @@ if (TFI->hasFP(MF) || TT.isOSDarwin()) markSuperRegs(Reserved, AArch64::W29); - if (MF.getSubtarget().isX18Reserved()) - markSuperRegs(Reserved, AArch64::W18); // Platform register - - if (MF.getSubtarget().isX20Reserved()) - markSuperRegs(Reserved, AArch64::W20); // Platform register + for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) { + if (MF.getSubtarget().isXRegisterReserved(i)) + markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i)); + } if (hasBasePointer(MF)) markSuperRegs(Reserved, AArch64::W19); @@ -149,31 +148,7 @@ bool AArch64RegisterInfo::isReservedReg(const MachineFunction &MF, unsigned Reg) const { - const AArch64FrameLowering *TFI = getFrameLowering(MF); - - switch (Reg) { - default: - break; - case AArch64::SP: - case AArch64::XZR: - case AArch64::WSP: - case AArch64::WZR: - return true; - case AArch64::X18: - case AArch64::W18: - return MF.getSubtarget().isX18Reserved(); - case AArch64::X19: - case AArch64::W19: - return hasBasePointer(MF); - case AArch64::X20: - case AArch64::W20: - return MF.getSubtarget().isX20Reserved(); - case AArch64::FP: - case AArch64::W29: - return TFI->hasFP(MF) || TT.isOSDarwin(); - } - - return false; + return getReservedRegs(MF)[Reg]; } bool AArch64RegisterInfo::isConstantPhysReg(unsigned PhysReg) const { @@ -434,13 +409,16 @@ case AArch64::GPR64RegClassID: case AArch64::GPR32commonRegClassID: case AArch64::GPR64commonRegClassID: + { + int numReserved = 0; + for (size_t i = 0; i < AArch64::GPR64commonRegClass.getNumRegs(); ++i) { + if (MF.getSubtarget().isXRegisterReserved(i)) ++numReserved; + } return 32 - 1 // XZR/SP - (TFI->hasFP(MF) || TT.isOSDarwin()) // FP - - MF.getSubtarget() - .isX18Reserved() // X18 reserved as platform register - - MF.getSubtarget() - .isX20Reserved() // X20 reserved as platform register + - numReserved - hasBasePointer(MF); // X19 + } case AArch64::FPR8RegClassID: case AArch64::FPR16RegClassID: case AArch64::FPR32RegClassID: Index: lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- lib/Target/AArch64/AArch64Subtarget.h +++ lib/Target/AArch64/AArch64Subtarget.h @@ -131,8 +131,8 @@ // ReserveX18 - X18 is not available as a general purpose register. bool ReserveX18; - // ReserveX20 - X20 is not available as a general purpose register. - bool ReserveX20 = false; + // ReserveXRegister[i] - X#i is not available as a general purpose register. + bool ReserveXRegister[31]; bool IsLittle; @@ -218,8 +218,7 @@ return MinVectorRegisterBitWidth; } - bool isX18Reserved() const { return ReserveX18; } - bool isX20Reserved() const { return ReserveX20; } + bool isXRegisterReserved(size_t i) const { return ReserveXRegister[i]; } bool hasFPARMv8() const { return HasFPARMv8; } bool hasNEON() const { return HasNEON; } bool hasCrypto() const { return HasCrypto; } Index: lib/Target/AArch64/AArch64Subtarget.cpp =================================================================== --- lib/Target/AArch64/AArch64Subtarget.cpp +++ lib/Target/AArch64/AArch64Subtarget.cpp @@ -156,6 +156,7 @@ TargetTriple(TT), FrameLowering(), InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(), TLInfo(TM, *this) { + ReserveXRegister[18] |= ReserveX18; CallLoweringInfo.reset(new AArch64CallLowering(*getTargetLowering())); Legalizer.reset(new AArch64LegalizerInfo(*this)); Index: test/CodeGen/AArch64/arm64-platform-reg.ll =================================================================== --- test/CodeGen/AArch64/arm64-platform-reg.ll +++ test/CodeGen/AArch64/arm64-platform-reg.ll @@ -6,6 +6,14 @@ ; RUN: llc -mtriple=aarch64-fuchsia -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 ; RUN: llc -mtriple=aarch64-windows -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 +; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x1 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X1 +; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x2 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X2 +; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x3 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X3 +; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x4 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X4 +; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x5 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X5 +; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x6 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X6 +; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x7 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X7 + ; x18 is reserved as a platform register on Darwin but not on other ; systems. Create loads of register pressure and make sure this is respected. @@ -22,10 +30,24 @@ ; CHECK: str x18 ; CHECK-RESERVE-NOT: ldr fp +; CHECK-RESERVE-X1-NOT: ldr x1, +; CHECK-RESERVE-X2-NOT: ldr x2, +; CHECK-RESERVE-X3-NOT: ldr x3, +; CHECK-RESERVE-X4-NOT: ldr x4, +; CHECK-RESERVE-X5-NOT: ldr x5, +; CHECK-RESERVE-X6-NOT: ldr x6, +; CHECK-RESERVE-X7-NOT: ldr x7, ; CHECK-RESERVE-X18-NOT: ldr x18 ; CHECK-RESERVE-X20-NOT: ldr x20 ; CHECK-RESERVE: Spill ; CHECK-RESERVE-NOT: ldr fp +; CHECK-RESERVE-X1-NOT: ldr x1, +; CHECK-RESERVE-X2-NOT: ldr x2, +; CHECK-RESERVE-X3-NOT: ldr x3, +; CHECK-RESERVE-X4-NOT: ldr x4, +; CHECK-RESERVE-X5-NOT: ldr x5, +; CHECK-RESERVE-X6-NOT: ldr x6, +; CHECK-RESERVE-X7-NOT: ldr x7, ; CHECK-RESERVE-X18-NOT: ldr x18 ; CHECK-RESERVE-X20-NOT: ldr x20 ; CHECK-RESERVE: ret