Index: llvm/lib/Target/AArch64/AArch64.td =================================================================== --- llvm/lib/Target/AArch64/AArch64.td +++ llvm/lib/Target/AArch64/AArch64.td @@ -384,6 +384,14 @@ include "AArch64SystemOperands.td" +//===----------------------------------------------------------------------===// +// Access to privileged registers +//===----------------------------------------------------------------------===// + +foreach i = 1-3 in +def FeatureUseEL#i#ForTP : SubtargetFeature<"tpidr-el"#i, "UseEL"#i#"ForTP", + "true", "Permit use of TPIDR_EL"#i#" for the TLS base">; + //===----------------------------------------------------------------------===// // AArch64 Processors supported. // Index: llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -505,6 +505,12 @@ if (MF->getTarget().getTargetTriple().isOSFuchsia() && MF->getTarget().getCodeModel() == CodeModel::Kernel) SysReg = AArch64SysReg::TPIDR_EL1; + else if (MF->getSubtarget().useEL3ForTP()) + SysReg = AArch64SysReg::TPIDR_EL3; + else if (MF->getSubtarget().useEL2ForTP()) + SysReg = AArch64SysReg::TPIDR_EL2; + else if (MF->getSubtarget().useEL1ForTP()) + SysReg = AArch64SysReg::TPIDR_EL1; BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MRS), DstReg) .addImm(SysReg); MI.eraseFromParent(); Index: llvm/lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- llvm/lib/Target/AArch64/AArch64Subtarget.h +++ llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -173,6 +173,9 @@ bool DisableLatencySchedHeuristic = false; bool UseRSqrt = false; bool Force32BitJumpTables = false; + bool UseEL1ForTP = false; + bool UseEL2ForTP = false; + bool UseEL3ForTP = false; uint8_t MaxInterleaveFactor = 2; uint8_t VectorInsertExtractBaseCost = 3; uint16_t CacheLineSize = 0; @@ -324,6 +327,10 @@ hasFuseCCSelect() || hasFuseLiterals(); } + bool useEL1ForTP() const { return UseEL1ForTP; } + bool useEL2ForTP() const { return UseEL2ForTP; } + bool useEL3ForTP() const { return UseEL3ForTP; } + bool useRSqrt() const { return UseRSqrt; } bool force32BitJumpTables() const { return Force32BitJumpTables; } unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; } Index: llvm/test/CodeGen/AArch64/arm64-builtins-linux.ll =================================================================== --- llvm/test/CodeGen/AArch64/arm64-builtins-linux.ll +++ llvm/test/CodeGen/AArch64/arm64-builtins-linux.ll @@ -1,6 +1,9 @@ ; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s ; RUN: llc < %s -mtriple=aarch64-fuchsia | FileCheck %s ; RUN: llc < %s -mtriple=aarch64-fuchsia -code-model=kernel | FileCheck --check-prefix=FUCHSIA-KERNEL %s +; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+tpidr-el1 | FileCheck --check-prefix=USEEL1 %s +; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+tpidr-el2 | FileCheck --check-prefix=USEEL2 %s +; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+tpidr-el3 | FileCheck --check-prefix=USEEL3 %s ; Function Attrs: nounwind readnone declare i8* @llvm.thread.pointer() #1 @@ -10,6 +13,12 @@ ; CHECK: mrs {{x[0-9]+}}, TPIDR_EL0 ; FUCHSIA-KERNEL: thread_pointer: ; FUCHSIA-KERNEL: mrs {{x[0-9]+}}, TPIDR_EL1 +; USEEL1: thread_pointer: +; USEEL1: mrs {{x[0-9]+}}, TPIDR_EL1 +; USEEL2: thread_pointer: +; USEEL2: mrs {{x[0-9]+}}, TPIDR_EL2 +; USEEL3: thread_pointer: +; USEEL3: mrs {{x[0-9]+}}, TPIDR_EL3 %1 = tail call i8* @llvm.thread.pointer() ret i8* %1 }