Index: lib/Target/ARM/ARMISelLowering.h =================================================================== --- lib/Target/ARM/ARMISelLowering.h +++ lib/Target/ARM/ARMISelLowering.h @@ -36,6 +36,11 @@ class ARMSubtarget; class InstrItineraryData; +enum ReadTPMode { + Soft, + Cp15 +}; + namespace ARMISD { // ARM Specific DAG Nodes Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -135,6 +135,13 @@ "arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128)); +static cl::opt ReadThreadPointer( + "mtp", cl::Hidden, cl::init(ReadTPMode::Soft), + cl::values(clEnumValN(ReadTPMode::Soft, "soft", + "Soft reading of thread pointer"), + clEnumValN(ReadTPMode::Cp15, "cp15", + "Read thread pointer from register")), + cl::desc("The way of reading thread pointer")); // The APCS parameter registers. static const MCPhysReg GPRArgRegs[] = { @@ -2916,7 +2923,21 @@ SDValue Chain = DAG.getEntryNode(); EVT PtrVT = getPointerTy(DAG.getDataLayout()); // Get the Thread Pointer - SDValue ThreadPointer = DAG.getNode(ARMISD::THREAD_POINTER, dl, PtrVT); + SDValue ThreadPointer; + // Get the Thread Pointer + if (ReadThreadPointer == ReadTPMode::Soft) + ThreadPointer = DAG.getNode(ARMISD::THREAD_POINTER, dl, PtrVT); + else if (ReadThreadPointer == ReadTPMode::Cp15) { + SDValue Ops[] = {Chain, + DAG.getConstant(Intrinsic::arm_mrc, dl, MVT::i32), + DAG.getConstant(15, dl, MVT::i32), + DAG.getConstant(0, dl, MVT::i32), + DAG.getConstant(13, dl, MVT::i32), + DAG.getConstant(0, dl, MVT::i32), + DAG.getConstant(3, dl, MVT::i32)}; + ThreadPointer = DAG.getNode(ISD::INTRINSIC_W_CHAIN, dl, + DAG.getVTList(MVT::i32, MVT::Other), Ops); + } if (model == TLSModel::InitialExec) { MachineFunction &MF = DAG.getMachineFunction(); Index: test/CodeGen/ARM/readtp.ll =================================================================== --- test/CodeGen/ARM/readtp.ll +++ test/CodeGen/ARM/readtp.ll @@ -0,0 +1,24 @@ +; RUN: llc -mtriple=armeb-linux-gnueabihf -O2 -mtp=cp15 %s -o - | FileCheck %s -check-prefix=CHECK-HARD +; RUN: llc -mtriple=armeb-linux-gnueabihf -O2 -mtp=soft %s -o - | FileCheck %s -check-prefix=CHECK-SOFT +; RUN: llc -mtriple=armeb-linux-gnueabihf -O2 %s -o - | FileCheck %s -check-prefix=CHECK-DEFAULT + + +; volatile __thread int counter; +; void foo(int argc, char** argh) { +; counter = 5; +; } + + +@counter = thread_local global i32 0, align 4 + +define void @foo() { +entry: + store volatile i32 5, i32* @counter, align 4 + ret void +} + + +; CHECK-LABEL: foo: +; CHECK-HARD: mrc p15, #0, {{r[0-9]+}}, {{c[0-9]+}}, {{c[0-9]+}}, #3 +; CHECK-SOFT: bl __aeabi_read_tp +; CHECK-DEFAULT: bl __aeabi_read_tp \ No newline at end of file