Index: lib/Target/AArch64/AArch64.td =================================================================== --- lib/Target/AArch64/AArch64.td +++ lib/Target/AArch64/AArch64.td @@ -240,6 +240,13 @@ def FeatureMTE : SubtargetFeature<"mte", "HasMTE", "true", "Enable Memory Tagging Extension" >; +foreach i = 1-3 in + def FeatureUseEL#i : SubtargetFeature<"use-el"#i, "UseEL"#i, "true", + "Generate access to EL"#i#" registers">; + +def FeatureUseSPForTP : SubtargetFeature<"use-sp-for-tp", "UseSPForTP", "true", + "Use SP_EL[1|2] instead of TPIDR_EL[1|2] for TLS">; + //===----------------------------------------------------------------------===// // Architectures. // Index: lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp =================================================================== --- lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -928,6 +928,22 @@ if (MF->getTarget().getTargetTriple().isOSFuchsia() && MF->getTarget().getCodeModel() == CodeModel::Kernel) SysReg = AArch64SysReg::TPIDR_EL1; + const auto &ST = MF->getSubtarget(); + if (ST.hasFeature(AArch64::FeatureUseSPForTP)) { + if (ST.hasFeature(AArch64::FeatureUseEL2)) + SysReg = AArch64SysReg::SP_EL2; + else if (ST.hasFeature(AArch64::FeatureUseEL1)) + SysReg = AArch64SysReg::SP_EL1; + else + report_fatal_error("SP can only be used for TP in EL1 or EL2"); + } else { + if (ST.hasFeature(AArch64::FeatureUseEL3)) + SysReg = AArch64SysReg::TPIDR_EL3; + else if (ST.hasFeature(AArch64::FeatureUseEL2)) + SysReg = AArch64SysReg::TPIDR_EL2; + else if (ST.hasFeature(AArch64::FeatureUseEL1)) + SysReg = AArch64SysReg::TPIDR_EL1; + } BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MRS), DstReg) .addImm(SysReg); MI.eraseFromParent(); Index: lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- lib/Target/AArch64/AArch64Subtarget.h +++ lib/Target/AArch64/AArch64Subtarget.h @@ -144,6 +144,10 @@ bool DisableLatencySchedHeuristic = false; bool UseRSqrt = false; bool Force32BitJumpTables = false; + bool UseEL1 = false; + bool UseEL2 = false; + bool UseEL3 = false; + bool UseSPForTP = false; uint8_t MaxInterleaveFactor = 2; uint8_t VectorInsertExtractBaseCost = 3; uint16_t CacheLineSize = 0; @@ -293,6 +297,11 @@ hasFuseAES() || hasFuseCCSelect() || hasFuseLiterals(); } + bool useEL1() const { return UseEL1; } + bool useEL2() const { return UseEL2; } + bool useEL3() const { return UseEL3; } + bool useSPForTP() const { return UseSPForTP; } + bool useRSqrt() const { return UseRSqrt; } bool force32BitJumpTables() const { return Force32BitJumpTables; } unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; } Index: test/CodeGen/AArch64/arm64-builtins-linux.ll =================================================================== --- test/CodeGen/AArch64/arm64-builtins-linux.ll +++ test/CodeGen/AArch64/arm64-builtins-linux.ll @@ -1,6 +1,11 @@ ; 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=+use-el1 | FileCheck --check-prefix=USEEL1 %s +; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+use-el2 | FileCheck --check-prefix=USEEL2 %s +; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+use-el3 | FileCheck --check-prefix=USEEL3 %s +; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+use-el1,+use-sp-for-tp | FileCheck --check-prefix=USEEL1-USESPFORTP %s +; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+use-el2,+use-sp-for-tp | FileCheck --check-prefix=USEEL2-USESPFORTP %s ; Function Attrs: nounwind readnone declare i8* @llvm.thread.pointer() #1 @@ -10,6 +15,16 @@ ; 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 +; USEEL1-USESPFORTP: thread_pointer: +; USEEL1-USESPFORTP: mrs {{x[0-9]+}}, SP_EL1 +; USEEL2-USESPFORTP: thread_pointer: +; USEEL2-USESPFORTP: mrs {{x[0-9]+}}, SP_EL2 %1 = tail call i8* @llvm.thread.pointer() ret i8* %1 }