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<ReadTPMode> 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