Index: include/llvm/IR/IntrinsicsSystemZ.td =================================================================== --- include/llvm/IR/IntrinsicsSystemZ.td +++ include/llvm/IR/IntrinsicsSystemZ.td @@ -11,6 +11,13 @@ // //===----------------------------------------------------------------------===// +let TargetPrefix = "s390" in { + +def int_s390_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">, + Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + +} + class SystemZUnaryConv : GCCBuiltin<"__builtin_s390_" ## name>, Intrinsic<[result], [arg], [IntrNoMem]>; Index: lib/Target/SystemZ/SystemZISelLowering.h =================================================================== --- lib/Target/SystemZ/SystemZISelLowering.h +++ lib/Target/SystemZ/SystemZISelLowering.h @@ -464,6 +464,7 @@ SDValue lowerTLSGetOffset(GlobalAddressSDNode *Node, SelectionDAG &DAG, unsigned Opcode, SDValue GOTOffset) const; + SDValue lowerThreadPointer(SDLoc &DL, SelectionDAG &DAG) const; SDValue lowerGlobalTLSAddress(GlobalAddressSDNode *Node, SelectionDAG &DAG) const; SDValue lowerBlockAddress(BlockAddressSDNode *Node, Index: lib/Target/SystemZ/SystemZISelLowering.cpp =================================================================== --- lib/Target/SystemZ/SystemZISelLowering.cpp +++ lib/Target/SystemZ/SystemZISelLowering.cpp @@ -2533,14 +2533,9 @@ return DAG.getCopyFromReg(Chain, DL, SystemZ::R2D, PtrVT, Glue); } -SDValue SystemZTargetLowering::lowerGlobalTLSAddress(GlobalAddressSDNode *Node, - SelectionDAG &DAG) const { - if (DAG.getTarget().Options.EmulatedTLS) - return LowerToTLSEmulatedModel(Node, DAG); - SDLoc DL(Node); - const GlobalValue *GV = Node->getGlobal(); +SDValue SystemZTargetLowering::lowerThreadPointer(SDLoc &DL, + SelectionDAG &DAG) const { EVT PtrVT = getPointerTy(DAG.getDataLayout()); - TLSModel::Model model = DAG.getTarget().getTLSModel(GV); // The high part of the thread pointer is in access register 0. SDValue TPHi = DAG.getNode(SystemZISD::EXTRACT_ACCESS, DL, MVT::i32, @@ -2555,7 +2550,19 @@ // Merge them into a single 64-bit address. SDValue TPHiShifted = DAG.getNode(ISD::SHL, DL, PtrVT, TPHi, DAG.getConstant(32, DL, PtrVT)); - SDValue TP = DAG.getNode(ISD::OR, DL, PtrVT, TPHiShifted, TPLo); + return DAG.getNode(ISD::OR, DL, PtrVT, TPHiShifted, TPLo); +} + +SDValue SystemZTargetLowering::lowerGlobalTLSAddress(GlobalAddressSDNode *Node, + SelectionDAG &DAG) const { + if (DAG.getTarget().Options.EmulatedTLS) + return LowerToTLSEmulatedModel(Node, DAG); + SDLoc DL(Node); + const GlobalValue *GV = Node->getGlobal(); + EVT PtrVT = getPointerTy(DAG.getDataLayout()); + TLSModel::Model model = DAG.getTarget().getTLSModel(GV); + + SDValue TP = lowerThreadPointer(DL, DAG); // Get the offset of GA from the thread pointer, based on the TLS model. SDValue Offset; @@ -3396,6 +3403,11 @@ unsigned Id = cast(Op.getOperand(0))->getZExtValue(); switch (Id) { + case Intrinsic::s390_thread_pointer: { + SDLoc DL(Op); + return lowerThreadPointer(DL, DAG); + } + case Intrinsic::s390_vpdi: return DAG.getNode(SystemZISD::PERMUTE_DWORDS, SDLoc(Op), Op.getValueType(), Op.getOperand(1), Op.getOperand(2), Op.getOperand(3)); Index: test/CodeGen/SystemZ/builtins.ll =================================================================== --- /dev/null +++ test/CodeGen/SystemZ/builtins.ll @@ -0,0 +1,14 @@ +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +; Function Attrs: nounwind readnone +declare i8* @llvm.s390.thread.pointer() #1 + +define i8* @thread_pointer() { +; CHECK: thread_pointer: +; CHECK: ear [[REG1:%r[0-5]]], %a0 +; CHECK: sllg %r2, [[REG1]], 32 +; CHECK: ear %r2, %a1 +; CHECK: br %r14 + %1 = tail call i8* @llvm.s390.thread.pointer() + ret i8* %1 +}