Skip to content

Commit

Permalink
[AArch64] Support reserving x20 register
Browse files Browse the repository at this point in the history
Register x20 is a callee-saved register which may be used for other
purposes in certain contexts, for example to hold special variables
within the kernel. This change adds support for reserving this register
both to frontend and backend to make this register usable for these
purposes.

Differential Revision: https://reviews.llvm.org/D46552

llvm-svn: 334531
  • Loading branch information
petrhosek committed Jun 12, 2018
1 parent 6d0d812 commit 7250908
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 13 deletions.
4 changes: 4 additions & 0 deletions clang/docs/ClangCommandLineReference.rst
Expand Up @@ -2296,6 +2296,10 @@ AARCH64

Reserve the x18 register (AArch64 only)

.. option:: -ffixed-x20

Reserve the x20 register (AArch64 only)

.. option:: -mfix-cortex-a53-835769, -mno-fix-cortex-a53-835769

Workaround Cortex-A53 erratum 835769 (AArch64 only)
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -2004,6 +2004,8 @@ def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">,
HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">;
def ffixed_x18 : Flag<["-"], "ffixed-x18">, Group<m_aarch64_Features_Group>,
HelpText<"Reserve the x18 register (AArch64 only)">;
def ffixed_x20 : Flag<["-"], "ffixed-x20">, Group<m_aarch64_Features_Group>,
HelpText<"Reserve the x20 register (AArch64 only)">;

def msimd128 : Flag<["-"], "msimd128">, Group<m_wasm_Features_Group>;
def mno_simd128 : Flag<["-"], "mno-simd128">, Group<m_wasm_Features_Group>;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/AArch64.cpp
Expand Up @@ -198,6 +198,9 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
if (Args.hasArg(options::OPT_ffixed_x18))
Features.push_back("+reserve-x18");

if (Args.hasArg(options::OPT_ffixed_x20))
Features.push_back("+reserve-x20");

if (Args.hasArg(options::OPT_mno_neg_immediates))
Features.push_back("+no-neg-immediates");
}
4 changes: 4 additions & 0 deletions clang/test/Driver/aarch64-fixed-x20.c
@@ -0,0 +1,4 @@
// RUN: %clang -target aarch64-none-gnu -ffixed-x20 -### %s 2> %t
// RUN: FileCheck --check-prefix=CHECK-FIXED-X20 < %t %s

// CHECK-FIXED-X20: "-target-feature" "+reserve-x20"
4 changes: 4 additions & 0 deletions llvm/lib/Target/AArch64/AArch64.td
Expand Up @@ -76,6 +76,10 @@ 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">;

def FeatureUseAA : SubtargetFeature<"use-aa", "UseAA", "true",
"Use alias analysis during codegen">;

Expand Down
8 changes: 6 additions & 2 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Expand Up @@ -4930,9 +4930,13 @@ unsigned AArch64TargetLowering::getRegisterByName(const char* RegName, EVT VT,
.Case("sp", AArch64::SP)
.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::X18 || Reg == AArch64::W18) &&
!Subtarget->isX18Reserved()) ||
((Reg == AArch64::X20 || Reg == AArch64::W20) &&
!Subtarget->isX20Reserved()))
Reg = 0;
if (Reg)
return Reg;
Expand Down
14 changes: 11 additions & 3 deletions llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
Expand Up @@ -137,6 +137,9 @@ AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
if (MF.getSubtarget<AArch64Subtarget>().isX18Reserved())
markSuperRegs(Reserved, AArch64::W18); // Platform register

if (MF.getSubtarget<AArch64Subtarget>().isX20Reserved())
markSuperRegs(Reserved, AArch64::W20); // Platform register

if (hasBasePointer(MF))
markSuperRegs(Reserved, AArch64::W19);

Expand All @@ -159,12 +162,15 @@ bool AArch64RegisterInfo::isReservedReg(const MachineFunction &MF,
case AArch64::X18:
case AArch64::W18:
return MF.getSubtarget<AArch64Subtarget>().isX18Reserved();
case AArch64::X19:
case AArch64::W19:
return hasBasePointer(MF);
case AArch64::X20:
case AArch64::W20:
return MF.getSubtarget<AArch64Subtarget>().isX20Reserved();
case AArch64::FP:
case AArch64::W29:
return TFI->hasFP(MF) || TT.isOSDarwin();
case AArch64::W19:
case AArch64::X19:
return hasBasePointer(MF);
}

return false;
Expand Down Expand Up @@ -432,6 +438,8 @@ unsigned AArch64RegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
- (TFI->hasFP(MF) || TT.isOSDarwin()) // FP
- MF.getSubtarget<AArch64Subtarget>()
.isX18Reserved() // X18 reserved as platform register
- MF.getSubtarget<AArch64Subtarget>()
.isX20Reserved() // X20 reserved as platform register
- hasBasePointer(MF); // X19
case AArch64::FPR8RegClassID:
case AArch64::FPR16RegClassID:
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/AArch64/AArch64Subtarget.h
Expand Up @@ -131,6 +131,9 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
// 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;

bool IsLittle;

/// TargetTriple - What processor and OS we're targeting.
Expand Down Expand Up @@ -216,6 +219,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
}

bool isX18Reserved() const { return ReserveX18; }
bool isX20Reserved() const { return ReserveX20; }
bool hasFPARMv8() const { return HasFPARMv8; }
bool hasNEON() const { return HasNEON; }
bool hasCrypto() const { return HasCrypto; }
Expand Down
20 changes: 12 additions & 8 deletions llvm/test/CodeGen/AArch64/arm64-platform-reg.ll
@@ -1,8 +1,10 @@
; 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=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-x20 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X20
; RUN: llc -mtriple=aarch64-fuchsia -mattr=+reserve-x18,+reserve-x20 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 --check-prefix=CHECK-RESERVE-X20
; 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.
Expand All @@ -19,11 +21,13 @@ define void @keep_live() {
; CHECK: ldr x18
; CHECK: str x18

; CHECK-RESERVE-X18-NOT: ldr fp
; CHECK-RESERVE-NOT: ldr fp
; CHECK-RESERVE-X18-NOT: ldr x18
; CHECK-RESERVE-X18: Spill
; CHECK-RESERVE-X18-NOT: ldr fp
; CHECK-RESERVE-X20-NOT: ldr x20
; CHECK-RESERVE: Spill
; CHECK-RESERVE-NOT: ldr fp
; CHECK-RESERVE-X18-NOT: ldr x18
; CHECK-RESERVE-X18: ret
; CHECK-RESERVE-X20-NOT: ldr x20
; CHECK-RESERVE: ret
ret void
}

0 comments on commit 7250908

Please sign in to comment.