diff options
| -rw-r--r-- | llvm/lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h | 22 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcAsmPrinter.cpp | 50 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcISelLowering.cpp | 103 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcISelLowering.h | 9 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcInstr64Bit.td | 9 | ||||
| -rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrInfo.td | 49 | ||||
| -rw-r--r-- | llvm/test/CodeGen/SPARC/tls.ll | 73 | 
8 files changed, 311 insertions, 10 deletions
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h index aac0e8d74a8..f3caeaa0c23 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h @@ -53,7 +53,27 @@ enum TOF {    // Extract bits 41-32 of an address.    // Assembler: %hm(addr) -  MO_HM +  MO_HM, + +  // TargetFlags for Thread Local Storage. +  MO_TLS_GD_HI22, +  MO_TLS_GD_LO10, +  MO_TLS_GD_ADD, +  MO_TLS_GD_CALL, +  MO_TLS_LDM_HI22, +  MO_TLS_LDM_LO10, +  MO_TLS_LDM_ADD, +  MO_TLS_LDM_CALL, +  MO_TLS_LDO_HIX22, +  MO_TLS_LDO_LOX10, +  MO_TLS_LDO_ADD, +  MO_TLS_IE_HI22, +  MO_TLS_IE_LO10, +  MO_TLS_IE_LD, +  MO_TLS_IE_LDX, +  MO_TLS_IE_ADD, +  MO_TLS_LE_HIX22, +  MO_TLS_LE_LOX10  };  } // end namespace SPII diff --git a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp index b695dd8747d..d561093a3ec 100644 --- a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -105,11 +105,37 @@ void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,        assert(TF == SPII::MO_NO_FLAG &&               "Cannot handle target flags on call address");      else if (MI->getOpcode() == SP::SETHIi) -      assert((TF == SPII::MO_HI || TF == SPII::MO_H44 || TF == SPII::MO_HH) && +      assert((TF == SPII::MO_HI || TF == SPII::MO_H44 || TF == SPII::MO_HH +              || TF == SPII::MO_TLS_GD_HI22 +              || TF == SPII::MO_TLS_LDM_HI22 +              || TF == SPII::MO_TLS_LDO_HIX22 +              || TF == SPII::MO_TLS_IE_HI22 +              || TF == SPII::MO_TLS_LE_HIX22) &&               "Invalid target flags for address operand on sethi"); +    else if (MI->getOpcode() == SP::TLS_CALL) +      assert((TF == SPII::MO_NO_FLAG +              || TF == SPII::MO_TLS_GD_CALL +              || TF == SPII::MO_TLS_LDM_CALL) && +             "Cannot handle target flags on tls call address"); +    else if (MI->getOpcode() == SP::TLS_ADDrr) +      assert((TF == SPII::MO_TLS_GD_ADD || TF == SPII::MO_TLS_LDM_ADD +              || TF == SPII::MO_TLS_LDO_ADD || TF == SPII::MO_TLS_IE_ADD) && +             "Cannot handle target flags on add for TLS"); +    else if (MI->getOpcode() == SP::TLS_LDrr) +      assert(TF == SPII::MO_TLS_IE_LD && +             "Cannot handle target flags on ld for TLS"); +    else if (MI->getOpcode() == SP::TLS_LDXrr) +      assert(TF == SPII::MO_TLS_IE_LDX && +             "Cannot handle target flags on ldx for TLS"); +    else if (MI->getOpcode() == SP::XORri) +      assert((TF == SPII::MO_TLS_LDO_LOX10 || TF == SPII::MO_TLS_LE_LOX10) && +             "Cannot handle target flags on xor for TLS");      else -      assert((TF == SPII::MO_LO || TF == SPII::MO_M44 || TF == SPII::MO_L44 || -              TF == SPII::MO_HM) && +      assert((TF == SPII::MO_LO || TF == SPII::MO_M44 || TF == SPII::MO_L44 +              || TF == SPII::MO_HM +              || TF == SPII::MO_TLS_GD_LO10 +              || TF == SPII::MO_TLS_LDM_LO10 +              || TF == SPII::MO_TLS_IE_LO10 ) &&               "Invalid target flags for small address operand");    }  #endif @@ -128,6 +154,24 @@ void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,    case SPII::MO_L44: O << "%l44("; break;    case SPII::MO_HH:  O << "%hh(";  break;    case SPII::MO_HM:  O << "%hm(";  break; +  case SPII::MO_TLS_GD_HI22:   O << "%tgd_hi22(";   break; +  case SPII::MO_TLS_GD_LO10:   O << "%tgd_lo10(";   break; +  case SPII::MO_TLS_GD_ADD:    O << "%tgd_add(";    break; +  case SPII::MO_TLS_GD_CALL:   O << "%tgd_call(";   break; +  case SPII::MO_TLS_LDM_HI22:  O << "%tldm_hi22(";  break; +  case SPII::MO_TLS_LDM_LO10:  O << "%tldm_lo10(";  break; +  case SPII::MO_TLS_LDM_ADD:   O << "%tldm_add(";   break; +  case SPII::MO_TLS_LDM_CALL:  O << "%tldm_call(";  break; +  case SPII::MO_TLS_LDO_HIX22: O << "%tldo_hix22("; break; +  case SPII::MO_TLS_LDO_LOX10: O << "%tldo_lox10("; break; +  case SPII::MO_TLS_LDO_ADD:   O << "%tldo_add(";   break; +  case SPII::MO_TLS_IE_HI22:   O << "%tie_hi22(";   break; +  case SPII::MO_TLS_IE_LO10:   O << "%tie_lo10(";   break; +  case SPII::MO_TLS_IE_LD:     O << "%tie_ld(";     break; +  case SPII::MO_TLS_IE_LDX:    O << "%tie_ldx(";    break; +  case SPII::MO_TLS_IE_ADD:    O << "%tie_add(";    break; +  case SPII::MO_TLS_LE_HIX22:  O << "%tle_hix22(";  break; +  case SPII::MO_TLS_LE_LOX10:  O << "%tle_lox10(";   break;    }    switch (MO.getType()) { diff --git a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp index db62151c843..e17a187241c 100644 --- a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -80,7 +80,8 @@ bool SparcDAGToDAGISel::SelectADDRri(SDValue Addr,      return true;    }    if (Addr.getOpcode() == ISD::TargetExternalSymbol || -      Addr.getOpcode() == ISD::TargetGlobalAddress) +      Addr.getOpcode() == ISD::TargetGlobalAddress || +      Addr.getOpcode() == ISD::TargetGlobalTLSAddress)      return false;  // direct calls.    if (Addr.getOpcode() == ISD::ADD) { @@ -117,7 +118,8 @@ bool SparcDAGToDAGISel::SelectADDRri(SDValue Addr,  bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) {    if (Addr.getOpcode() == ISD::FrameIndex) return false;    if (Addr.getOpcode() == ISD::TargetExternalSymbol || -      Addr.getOpcode() == ISD::TargetGlobalAddress) +      Addr.getOpcode() == ISD::TargetGlobalAddress || +      Addr.getOpcode() == ISD::TargetGlobalTLSAddress)      return false;  // direct calls.    if (Addr.getOpcode() == ISD::ADD) { diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index eb9896c1f56..86bac7e3d88 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -1544,6 +1544,9 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {    case SPISD::RET_FLAG:   return "SPISD::RET_FLAG";    case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG";    case SPISD::FLUSHW:     return "SPISD::FLUSHW"; +  case SPISD::TLS_ADD:    return "SPISD::TLS_ADD"; +  case SPISD::TLS_LD:     return "SPISD::TLS_LD"; +  case SPISD::TLS_CALL:   return "SPISD::TLS_CALL";    }  } @@ -1699,6 +1702,103 @@ SDValue SparcTargetLowering::LowerBlockAddress(SDValue Op,    return makeAddress(Op, DAG);  } +SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op, +                                                   SelectionDAG &DAG) const { + +  GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op); +  SDLoc DL(GA); +  const GlobalValue *GV = GA->getGlobal(); +  EVT PtrVT = getPointerTy(); + +  TLSModel::Model model = getTargetMachine().getTLSModel(GV); + +  if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { +    unsigned HiTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_HI22 +                     : SPII::MO_TLS_LDM_HI22); +    unsigned LoTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_LO10 +                     : SPII::MO_TLS_LDM_LO10); +    unsigned addTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_ADD +                      : SPII::MO_TLS_LDM_ADD); +    unsigned callTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_CALL +                       : SPII::MO_TLS_LDM_CALL); + +    SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG); +    SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT); +    SDValue Argument = DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Base, HiLo, +                               withTargetFlags(Op, addTF, DAG)); + +    SDValue Chain = DAG.getEntryNode(); +    SDValue InFlag; + +    Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(1, true), DL); +    Chain = DAG.getCopyToReg(Chain, DL, SP::O0, Argument, InFlag); +    InFlag = Chain.getValue(1); +    SDValue Callee = DAG.getTargetExternalSymbol("__tls_get_addr", PtrVT); +    SDValue Symbol = withTargetFlags(Op, callTF, DAG); + +    SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); +    SmallVector<SDValue, 4> Ops; +    Ops.push_back(Chain); +    Ops.push_back(Callee); +    Ops.push_back(Symbol); +    Ops.push_back(DAG.getRegister(SP::O0, PtrVT)); +    const uint32_t *Mask = getTargetMachine() +      .getRegisterInfo()->getCallPreservedMask(CallingConv::C); +    assert(Mask && "Missing call preserved mask for calling convention"); +    Ops.push_back(DAG.getRegisterMask(Mask)); +    Ops.push_back(InFlag); +    Chain = DAG.getNode(SPISD::TLS_CALL, DL, NodeTys, &Ops[0], Ops.size()); +    InFlag = Chain.getValue(1); +    Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(1, true), +                               DAG.getIntPtrConstant(0, true), InFlag, DL); +    InFlag = Chain.getValue(1); +    SDValue Ret = DAG.getCopyFromReg(Chain, DL, SP::O0, PtrVT, InFlag); + +    if (model != TLSModel::LocalDynamic) +      return Ret; + +    SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT, +                             withTargetFlags(Op, SPII::MO_TLS_LDO_HIX22, DAG)); +    SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT, +                             withTargetFlags(Op, SPII::MO_TLS_LDO_LOX10, DAG)); +    HiLo =  DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo); +    return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Ret, HiLo, +                       withTargetFlags(Op, SPII::MO_TLS_LDO_ADD, DAG)); +  } + +  if (model == TLSModel::InitialExec) { +    unsigned ldTF     = ((PtrVT == MVT::i64)? SPII::MO_TLS_IE_LDX +                         : SPII::MO_TLS_IE_LD); + +    SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT); + +    // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this +    // function has calls. +    MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); +    MFI->setHasCalls(true); + +    SDValue TGA = makeHiLoPair(Op, +                               SPII::MO_TLS_IE_HI22, SPII::MO_TLS_IE_LO10, DAG); +    SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base, TGA); +    SDValue Offset = DAG.getNode(SPISD::TLS_LD, +                                 DL, PtrVT, Ptr, +                                 withTargetFlags(Op, ldTF, DAG)); +    return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, +                       DAG.getRegister(SP::G7, PtrVT), Offset, +                       withTargetFlags(Op, SPII::MO_TLS_IE_ADD, DAG)); +  } + +  assert(model == TLSModel::LocalExec); +  SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT, +                           withTargetFlags(Op, SPII::MO_TLS_LE_HIX22, DAG)); +  SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT, +                           withTargetFlags(Op, SPII::MO_TLS_LE_LOX10, DAG)); +  SDValue Offset =  DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo); + +  return DAG.getNode(ISD::ADD, DL, PtrVT, +                     DAG.getRegister(SP::G7, PtrVT), Offset); +} +  SDValue  SparcTargetLowering::LowerF128_LibCallArg(SDValue Chain, ArgListTy &Args,                                            SDValue Arg, SDLoc DL, @@ -2333,8 +2433,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {    case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG, *this);    case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG); -  case ISD::GlobalTLSAddress: -    llvm_unreachable("TLS not implemented for Sparc."); +  case ISD::GlobalTLSAddress:   return LowerGlobalTLSAddress(Op, DAG);    case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG);    case ISD::BlockAddress:       return LowerBlockAddress(Op, DAG);    case ISD::ConstantPool:       return LowerConstantPool(Op, DAG); diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h index 64c688d6816..57ef0995e71 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.h +++ b/llvm/lib/Target/Sparc/SparcISelLowering.h @@ -40,8 +40,12 @@ namespace llvm {        CALL,        // A call instruction.        RET_FLAG,    // Return with a flag operand. -      GLOBAL_BASE_REG, // Global base reg for PIC -      FLUSHW       // FLUSH register windows to stack +      GLOBAL_BASE_REG, // Global base reg for PIC. +      FLUSHW,      // FLUSH register windows to stack. + +      TLS_ADD,     // For Thread Local Storage (TLS). +      TLS_LD, +      TLS_CALL      };    } @@ -119,6 +123,7 @@ namespace llvm {                             SDLoc DL, SelectionDAG &DAG) const;      SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; +    SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;      SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;      SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td index 47658eec225..212bd1cb7bf 100644 --- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td +++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td @@ -162,6 +162,9 @@ def : Pat<(subc i64:$a, i64:$b), (SUBCCrr $a, $b)>;  def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>; +def : Pat<(tlsadd i64:$a, i64:$b, tglobaltlsaddr:$sym), +          (TLS_ADDrr $a, $b, $sym)>; +  // Register-immediate instructions.  def : Pat<(and i64:$a, (i64 simm13:$b)), (ANDri $a, (as_i32imm $b))>; @@ -237,6 +240,12 @@ def LDXri  : F3_2<3, 0b001011,                    (outs I64Regs:$dst), (ins MEMri:$addr),                    "ldx [$addr], $dst",                    [(set i64:$dst, (load ADDRri:$addr))]>; +let mayLoad = 1 in +  def TLS_LDXrr : F3_1<3, 0b001011, +                       (outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym), +                       "ldx [$addr], $dst, $sym", +                       [(set i64:$dst, +                           (tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>;  // Extending loads to i64.  def : Pat<(i64 (zextloadi1 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>; diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index 695be338edb..7dc17cc5016 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -85,6 +85,8 @@ def MEMri : Operand<iPTR> {    let MIOperandInfo = (ops ptr_rc, i32imm);  } +def TLSSym : Operand<iPTR>; +  // Branch targets have OtherVT type.  def brtarget : Operand<OtherVT>;  def calltarget : Operand<i32>; @@ -106,6 +108,11 @@ SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>;  def SDTSPITOF :  SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, f32>]>; +def SDTSPtlsadd : +SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisPtrTy<2>]>; +def SDTSPtlsld : +SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>; +  def SPcmpicc : SDNode<"SPISD::CMPICC", SDTSPcmpicc, [SDNPOutGlue]>;  def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>;  def SPbricc : SDNode<"SPISD::BRICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; @@ -144,6 +151,12 @@ def retflag       : SDNode<"SPISD::RET_FLAG", SDT_SPRet,  def flushw        : SDNode<"SPISD::FLUSHW", SDTNone,                             [SDNPHasChain, SDNPSideEffect, SDNPMayStore]>; +def tlsadd        : SDNode<"SPISD::TLS_ADD", SDTSPtlsadd>; +def tlsld         : SDNode<"SPISD::TLS_LD",  SDTSPtlsld>; +def tlscall       : SDNode<"SPISD::TLS_CALL", SDT_SPCall, +                            [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, +                             SDNPVariadic]>; +  def getPCX        : Operand<i32> {    let PrintMethod = "printGetPCX";  } @@ -807,6 +820,34 @@ let Defs = [FCC] in {  }  //===----------------------------------------------------------------------===// +// Instructions for Thread Local Storage(TLS). +//===----------------------------------------------------------------------===// + +def TLS_ADDrr : F3_1<2, 0b000000, +                    (outs IntRegs:$rd), +                    (ins IntRegs:$rs1, IntRegs:$rs2, TLSSym:$sym), +                    "add $rs1, $rs2, $rd, $sym", +                    [(set i32:$rd, +                        (tlsadd i32:$rs1, i32:$rs2, tglobaltlsaddr:$sym))]>; + +let mayLoad = 1 in +  def TLS_LDrr : F3_1<3, 0b000000, +                      (outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym), +                      "ld [$addr], $dst, $sym", +                      [(set i32:$dst, +                          (tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>; + +let Uses = [O6], isCall = 1 in +  def TLS_CALL : InstSP<(outs), +                        (ins calltarget:$disp, TLSSym:$sym, variable_ops), +                        "call $disp, $sym\n\tnop", +                        [(tlscall texternalsym:$disp, tglobaltlsaddr:$sym)]> { +  bits<30> disp; +  let op = 1; +  let Inst{29-0} = disp; +} + +//===----------------------------------------------------------------------===//  // V9 Instructions  //===----------------------------------------------------------------------===// @@ -915,6 +956,14 @@ def : Pat<(SPlo tglobaladdr:$in), (ORri (i32 G0), tglobaladdr:$in)>;  def : Pat<(SPhi tconstpool:$in), (SETHIi tconstpool:$in)>;  def : Pat<(SPlo tconstpool:$in), (ORri (i32 G0), tconstpool:$in)>; +// GlobalTLS addresses +def : Pat<(SPhi tglobaltlsaddr:$in), (SETHIi tglobaltlsaddr:$in)>; +def : Pat<(SPlo tglobaltlsaddr:$in), (ORri (i32 G0), tglobaltlsaddr:$in)>; +def : Pat<(add (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)), +          (ADDri (SETHIi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>; +def : Pat<(xor (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)), +          (XORri (SETHIi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>; +  // Blockaddress  def : Pat<(SPhi tblockaddress:$in), (SETHIi tblockaddress:$in)>;  def : Pat<(SPlo tblockaddress:$in), (ORri (i32 G0), tblockaddress:$in)>; diff --git a/llvm/test/CodeGen/SPARC/tls.ll b/llvm/test/CodeGen/SPARC/tls.ll new file mode 100644 index 00000000000..660ddff0fae --- /dev/null +++ b/llvm/test/CodeGen/SPARC/tls.ll @@ -0,0 +1,73 @@ +; RUN: llc <%s -march=sparc   -relocation-model=static | FileCheck %s --check-prefix=v8abs +; RUN: llc <%s -march=sparcv9 -relocation-model=static | FileCheck %s --check-prefix=v9abs +; RUN: llc <%s -march=sparc   -relocation-model=pic    | FileCheck %s --check-prefix=pic +; RUN: llc <%s -march=sparcv9 -relocation-model=pic    | FileCheck %s --check-prefix=pic + + +@local_symbol = internal thread_local global i32 0 +@extern_symbol = external thread_local global i32 + +; v8abs-LABEL:  test_tls_local +; v8abs:        sethi  %tle_hix22(local_symbol), [[R0:%[goli][0-7]]] +; v8abs:        xor    [[R0]], %tle_lox10(local_symbol), [[R1:%[goli][0-7]]] +; v8abs:        ld     [%g7+[[R1]]] + +; v9abs-LABEL:  test_tls_local +; v9abs:        sethi  %tle_hix22(local_symbol), [[R0:%[goli][0-7]]] +; v9abs:        xor    [[R0]], %tle_lox10(local_symbol), [[R1:%[goli][0-7]]] +; v9abs:        ld     [%g7+[[R1]]] + +; pic-LABEL:  test_tls_local +; pic:        or     {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]] +; pic:        add    [[PC]], %o7, [[GOTBASE:%[goli][0-7]]] +; pic-DAG:    sethi  %tldm_hi22(local_symbol), [[R0:%[goli][0-7]]] +; pic-DAG:    add    [[R0]], %tldm_lo10(local_symbol), [[R1:%[goli][0-7]]] +; pic-DAG:    add    [[GOTBASE]], [[R1]], %o0, %tldm_add(local_symbol) +; pic-DAG:    call   __tls_get_addr, %tldm_call(local_symbol) +; pic-DAG:    sethi  %tldo_hix22(local_symbol), [[R2:%[goli][0-7]]] +; pic-DAG:    xor    [[R2]], %tldo_lox10(local_symbol), [[R3:%[goli][0-7]]] +; pic:        add    %o0, [[R3]], {{.+}}, %tldo_add(local_symbol) + +define i32 @test_tls_local() { +entry: +  %0 = load i32* @local_symbol, align 4 +  %1 = add i32 %0, 1 +  store i32 %1, i32* @local_symbol, align 4 +  ret i32 %1 +} + + +; v8abs-LABEL:  test_tls_extern +; v8abs:        or     {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]] +; v8abs:        add    [[PC]], %o7, %[[GOTBASE:[goli][0-7]]] +; v8abs:        sethi  %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]] +; v8abs:        add    [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]] +; v8abs:        ld     [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ld(extern_symbol) +; v8abs:        add    %g7, [[R3]], %[[R4:[goli][0-7]]], %tie_add(extern_symbol) +; v8abs:        ld     [%[[R4]]] + +; v9abs-LABEL:  test_tls_extern +; v9abs:        or     {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]] +; v9abs:        add    [[PC]], %o7, %[[GOTBASE:[goli][0-7]]] +; v9abs:        sethi  %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]] +; v9abs:        add    [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]] +; v9abs:        ldx    [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ldx(extern_symbol) +; v9abs:        add    %g7, [[R3]], %[[R4:[goli][0-7]]], %tie_add(extern_symbol) +; v9abs:        ld     [%[[R4]]] + +; pic-LABEL:  test_tls_extern +; pic:        or     {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]] +; pic:        add    [[PC]], %o7, [[GOTBASE:%[goli][0-7]]] +; pic:        sethi  %tgd_hi22(extern_symbol), [[R0:%[goli][0-7]]] +; pic:        add    [[R0]], %tgd_lo10(extern_symbol), [[R1:%[goli][0-7]]] +; pic:        add    [[GOTBASE]], [[R1]], %o0, %tgd_add(extern_symbol) +; pic:        call   __tls_get_addr, %tgd_call(extern_symbol) +; pic-NEXT:   nop + +define i32 @test_tls_extern() { +entry: +  %0 = load i32* @extern_symbol, align 4 +  %1 = add i32 %0, 1 +  store i32 %1, i32* @extern_symbol, align 4 +  ret i32 %1 +}  | 

