Index: clang/docs/ClangCommandLineReference.rst =================================================================== --- clang/docs/ClangCommandLineReference.rst +++ clang/docs/ClangCommandLineReference.rst @@ -2292,6 +2292,14 @@ AARCH64 ------- +.. option:: -ffixed-x16 + +Reserve the x16 register (AArch64 only) + +.. option:: -ffixed-x17 + +Reserve the x17 register (AArch64 only) + .. option:: -ffixed-x18 Reserve the x18 register (AArch64 only) Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1959,6 +1959,10 @@ def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">, Group, HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">; +def ffixed_x16 : Flag<["-"], "ffixed-x16">, Group, + HelpText<"Reserve the x16 register (AArch64 only)">; +def ffixed_x17 : Flag<["-"], "ffixed-x17">, Group, + HelpText<"Reserve the x17 register (AArch64 only)">; def ffixed_x18 : Flag<["-"], "ffixed-x18">, Group, HelpText<"Reserve the x18 register (AArch64 only)">; Index: clang/lib/Driver/ToolChains/Arch/AArch64.cpp =================================================================== --- clang/lib/Driver/ToolChains/Arch/AArch64.cpp +++ clang/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -195,6 +195,12 @@ if (A->getOption().matches(options::OPT_mno_unaligned_access)) Features.push_back("+strict-align"); + if (Args.hasArg(options::OPT_ffixed_x16)) + Features.push_back("+reserve-x16"); + + if (Args.hasArg(options::OPT_ffixed_x17)) + Features.push_back("+reserve-x17"); + if (Args.hasArg(options::OPT_ffixed_x18)) Features.push_back("+reserve-x18"); Index: clang/test/Driver/aarch64-fixed-x16.c =================================================================== --- /dev/null +++ clang/test/Driver/aarch64-fixed-x16.c @@ -0,0 +1,4 @@ +// RUN: %clang -target aarch64-none-gnu -ffixed-x16 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X16 < %t %s + +// CHECK-FIXED-X16: "-target-feature" "+reserve-x16" Index: clang/test/Driver/aarch64-fixed-x17.c =================================================================== --- /dev/null +++ clang/test/Driver/aarch64-fixed-x17.c @@ -0,0 +1,4 @@ +// RUN: %clang -target aarch64-none-gnu -ffixed-x17 -### %s 2> %t +// RUN: FileCheck --check-prefix=CHECK-FIXED-X17 < %t %s + +// CHECK-FIXED-X17: "-target-feature" "+reserve-x17" Index: llvm/lib/Target/AArch64/AArch64.td =================================================================== --- llvm/lib/Target/AArch64/AArch64.td +++ llvm/lib/Target/AArch64/AArch64.td @@ -72,6 +72,14 @@ "Disallow all unaligned memory " "access">; +def FeatureReserveX16 : SubtargetFeature<"reserve-x16", "ReserveX16", "true", + "Reserve X16, making it unavailable " + "as a GPR">; + +def FeatureReserveX17 : SubtargetFeature<"reserve-x17", "ReserveX17", "true", + "Reserve X17, making it unavailable " + "as a GPR">; + def FeatureReserveX18 : SubtargetFeature<"reserve-x18", "ReserveX18", "true", "Reserve X18, making it unavailable " "as a GPR">; Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -4851,11 +4851,19 @@ SelectionDAG &DAG) const { unsigned Reg = StringSwitch(RegName) .Case("sp", AArch64::SP) + .Case("x16", AArch64::X16) + .Case("w16", AArch64::W16) + .Case("x17", AArch64::X17) + .Case("w17", AArch64::W17) .Case("x18", AArch64::X18) .Case("w18", AArch64::W18) .Default(0); - if ((Reg == AArch64::X18 || Reg == AArch64::W18) && - !Subtarget->isX18Reserved()) + if (((Reg == AArch64::X16 || Reg == AArch64::W16) && + !Subtarget->isX16Reserved()) || + ((Reg == AArch64::X17 || Reg == AArch64::W17) && + !Subtarget->isX17Reserved()) || + ((Reg == AArch64::X18 || Reg == AArch64::W18) && + !Subtarget->isX18Reserved())) Reg = 0; if (Reg) return Reg; Index: llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -134,6 +134,12 @@ if (TFI->hasFP(MF) || TT.isOSDarwin()) markSuperRegs(Reserved, AArch64::W29); + if (MF.getSubtarget().isX16Reserved()) + markSuperRegs(Reserved, AArch64::W16); // Platform register + + if (MF.getSubtarget().isX17Reserved()) + markSuperRegs(Reserved, AArch64::W17); // Platform register + if (MF.getSubtarget().isX18Reserved()) markSuperRegs(Reserved, AArch64::W18); // Platform register @@ -156,6 +162,12 @@ case AArch64::WSP: case AArch64::WZR: return true; + case AArch64::X16: + case AArch64::W16: + return MF.getSubtarget().isX16Reserved(); + case AArch64::X17: + case AArch64::W17: + return MF.getSubtarget().isX17Reserved(); case AArch64::X18: case AArch64::W18: return MF.getSubtarget().isX18Reserved(); @@ -430,6 +442,10 @@ case AArch64::GPR64commonRegClassID: return 32 - 1 // XZR/SP - (TFI->hasFP(MF) || TT.isOSDarwin()) // FP + - MF.getSubtarget() + .isX16Reserved() // X16 reserved as platform register + - MF.getSubtarget() + .isX17Reserved() // X17 reserved as platform register - MF.getSubtarget() .isX18Reserved() // X18 reserved as platform register - hasBasePointer(MF); // X19 Index: llvm/lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- llvm/lib/Target/AArch64/AArch64Subtarget.h +++ llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -128,6 +128,12 @@ unsigned MaxJumpTableSize = 0; unsigned WideningBaseCost = 0; + // ReserveX16 - X16 is not available as a general purpose register. + bool ReserveX16 = false; + + // ReserveX17 - X17 is not available as a general purpose register. + bool ReserveX17 = false; + // ReserveX18 - X18 is not available as a general purpose register. bool ReserveX18; @@ -215,6 +221,8 @@ return MinVectorRegisterBitWidth; } + bool isX16Reserved() const { return ReserveX16; } + bool isX17Reserved() const { return ReserveX17; } bool isX18Reserved() const { return ReserveX18; } bool hasFPARMv8() const { return HasFPARMv8; } bool hasNEON() const { return HasNEON; } Index: llvm/test/CodeGen/AArch64/arm64-platform-reg.ll =================================================================== --- llvm/test/CodeGen/AArch64/arm64-platform-reg.ll +++ llvm/test/CodeGen/AArch64/arm64-platform-reg.ll @@ -1,8 +1,11 @@ -; RUN: llc -mtriple=arm64-apple-ios -mattr=+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE-X18 -; RUN: llc -mtriple=arm64-freebsd-gnu -mattr=+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE-X18 +; RUN: llc -mtriple=aarch64-fuchsia -mattr=+reserve-x16 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X16 +; RUN: llc -mtriple=aarch64-fuchsia -mattr=+reserve-x17 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X17 +; RUN: llc -mtriple=arm64-apple-ios -mattr=+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 +; RUN: llc -mtriple=arm64-freebsd-gnu -mattr=+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 +; RUN: llc -mtriple=aarch64-fuchsia -mattr=+reserve-x16,+reserve-x17,+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X16 --check-prefix=CHECK-RESERVE-X17 --check-prefix=CHECK-RESERVE-X18 ; RUN: llc -mtriple=arm64-linux-gnu -o - %s | FileCheck %s -; RUN: llc -mtriple=aarch64-fuchsia -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE-X18 -; RUN: llc -mtriple=aarch64-windows -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE-X18 +; 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 ; 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. @@ -19,11 +22,15 @@ ; CHECK: ldr x18 ; CHECK: str x18 -; CHECK-RESERVE-X18-NOT: ldr fp +; CHECK-RESERVE-NOT: ldr fp +; CHECK-RESERVE-X16-NOT: ldr x16 +; CHECK-RESERVE-X17-NOT: ldr x17 ; CHECK-RESERVE-X18-NOT: ldr x18 -; CHECK-RESERVE-X18: Spill -; CHECK-RESERVE-X18-NOT: ldr fp +; CHECK-RESERVE: Spill +; CHECK-RESERVE-NOT: ldr fp +; CHECK-RESERVE-X16-NOT: ldr x16 +; CHECK-RESERVE-X17-NOT: ldr x17 ; CHECK-RESERVE-X18-NOT: ldr x18 -; CHECK-RESERVE-X18: ret +; CHECK-RESERVE: ret ret void }