Skip to content

Commit cb1dca6

Browse files
committed
[Sparc] Add support for TLS in sparc.
llvm-svn: 191164
1 parent 7b1cdb9 commit cb1dca6

File tree

8 files changed

+311
-10
lines changed

8 files changed

+311
-10
lines changed

llvm/lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,27 @@ enum TOF {
5353

5454
// Extract bits 41-32 of an address.
5555
// Assembler: %hm(addr)
56-
MO_HM
56+
MO_HM,
57+
58+
// TargetFlags for Thread Local Storage.
59+
MO_TLS_GD_HI22,
60+
MO_TLS_GD_LO10,
61+
MO_TLS_GD_ADD,
62+
MO_TLS_GD_CALL,
63+
MO_TLS_LDM_HI22,
64+
MO_TLS_LDM_LO10,
65+
MO_TLS_LDM_ADD,
66+
MO_TLS_LDM_CALL,
67+
MO_TLS_LDO_HIX22,
68+
MO_TLS_LDO_LOX10,
69+
MO_TLS_LDO_ADD,
70+
MO_TLS_IE_HI22,
71+
MO_TLS_IE_LO10,
72+
MO_TLS_IE_LD,
73+
MO_TLS_IE_LDX,
74+
MO_TLS_IE_ADD,
75+
MO_TLS_LE_HIX22,
76+
MO_TLS_LE_LOX10
5777
};
5878

5979
} // end namespace SPII

llvm/lib/Target/Sparc/SparcAsmPrinter.cpp

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,37 @@ void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
105105
assert(TF == SPII::MO_NO_FLAG &&
106106
"Cannot handle target flags on call address");
107107
else if (MI->getOpcode() == SP::SETHIi)
108-
assert((TF == SPII::MO_HI || TF == SPII::MO_H44 || TF == SPII::MO_HH) &&
108+
assert((TF == SPII::MO_HI || TF == SPII::MO_H44 || TF == SPII::MO_HH
109+
|| TF == SPII::MO_TLS_GD_HI22
110+
|| TF == SPII::MO_TLS_LDM_HI22
111+
|| TF == SPII::MO_TLS_LDO_HIX22
112+
|| TF == SPII::MO_TLS_IE_HI22
113+
|| TF == SPII::MO_TLS_LE_HIX22) &&
109114
"Invalid target flags for address operand on sethi");
115+
else if (MI->getOpcode() == SP::TLS_CALL)
116+
assert((TF == SPII::MO_NO_FLAG
117+
|| TF == SPII::MO_TLS_GD_CALL
118+
|| TF == SPII::MO_TLS_LDM_CALL) &&
119+
"Cannot handle target flags on tls call address");
120+
else if (MI->getOpcode() == SP::TLS_ADDrr)
121+
assert((TF == SPII::MO_TLS_GD_ADD || TF == SPII::MO_TLS_LDM_ADD
122+
|| TF == SPII::MO_TLS_LDO_ADD || TF == SPII::MO_TLS_IE_ADD) &&
123+
"Cannot handle target flags on add for TLS");
124+
else if (MI->getOpcode() == SP::TLS_LDrr)
125+
assert(TF == SPII::MO_TLS_IE_LD &&
126+
"Cannot handle target flags on ld for TLS");
127+
else if (MI->getOpcode() == SP::TLS_LDXrr)
128+
assert(TF == SPII::MO_TLS_IE_LDX &&
129+
"Cannot handle target flags on ldx for TLS");
130+
else if (MI->getOpcode() == SP::XORri)
131+
assert((TF == SPII::MO_TLS_LDO_LOX10 || TF == SPII::MO_TLS_LE_LOX10) &&
132+
"Cannot handle target flags on xor for TLS");
110133
else
111-
assert((TF == SPII::MO_LO || TF == SPII::MO_M44 || TF == SPII::MO_L44 ||
112-
TF == SPII::MO_HM) &&
134+
assert((TF == SPII::MO_LO || TF == SPII::MO_M44 || TF == SPII::MO_L44
135+
|| TF == SPII::MO_HM
136+
|| TF == SPII::MO_TLS_GD_LO10
137+
|| TF == SPII::MO_TLS_LDM_LO10
138+
|| TF == SPII::MO_TLS_IE_LO10 ) &&
113139
"Invalid target flags for small address operand");
114140
}
115141
#endif
@@ -128,6 +154,24 @@ void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
128154
case SPII::MO_L44: O << "%l44("; break;
129155
case SPII::MO_HH: O << "%hh("; break;
130156
case SPII::MO_HM: O << "%hm("; break;
157+
case SPII::MO_TLS_GD_HI22: O << "%tgd_hi22("; break;
158+
case SPII::MO_TLS_GD_LO10: O << "%tgd_lo10("; break;
159+
case SPII::MO_TLS_GD_ADD: O << "%tgd_add("; break;
160+
case SPII::MO_TLS_GD_CALL: O << "%tgd_call("; break;
161+
case SPII::MO_TLS_LDM_HI22: O << "%tldm_hi22("; break;
162+
case SPII::MO_TLS_LDM_LO10: O << "%tldm_lo10("; break;
163+
case SPII::MO_TLS_LDM_ADD: O << "%tldm_add("; break;
164+
case SPII::MO_TLS_LDM_CALL: O << "%tldm_call("; break;
165+
case SPII::MO_TLS_LDO_HIX22: O << "%tldo_hix22("; break;
166+
case SPII::MO_TLS_LDO_LOX10: O << "%tldo_lox10("; break;
167+
case SPII::MO_TLS_LDO_ADD: O << "%tldo_add("; break;
168+
case SPII::MO_TLS_IE_HI22: O << "%tie_hi22("; break;
169+
case SPII::MO_TLS_IE_LO10: O << "%tie_lo10("; break;
170+
case SPII::MO_TLS_IE_LD: O << "%tie_ld("; break;
171+
case SPII::MO_TLS_IE_LDX: O << "%tie_ldx("; break;
172+
case SPII::MO_TLS_IE_ADD: O << "%tie_add("; break;
173+
case SPII::MO_TLS_LE_HIX22: O << "%tle_hix22("; break;
174+
case SPII::MO_TLS_LE_LOX10: O << "%tle_lox10("; break;
131175
}
132176

133177
switch (MO.getType()) {

llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ bool SparcDAGToDAGISel::SelectADDRri(SDValue Addr,
8080
return true;
8181
}
8282
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
83-
Addr.getOpcode() == ISD::TargetGlobalAddress)
83+
Addr.getOpcode() == ISD::TargetGlobalAddress ||
84+
Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
8485
return false; // direct calls.
8586

8687
if (Addr.getOpcode() == ISD::ADD) {
@@ -117,7 +118,8 @@ bool SparcDAGToDAGISel::SelectADDRri(SDValue Addr,
117118
bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) {
118119
if (Addr.getOpcode() == ISD::FrameIndex) return false;
119120
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
120-
Addr.getOpcode() == ISD::TargetGlobalAddress)
121+
Addr.getOpcode() == ISD::TargetGlobalAddress ||
122+
Addr.getOpcode() == ISD::TargetGlobalTLSAddress)
121123
return false; // direct calls.
122124

123125
if (Addr.getOpcode() == ISD::ADD) {

llvm/lib/Target/Sparc/SparcISelLowering.cpp

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,9 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
15441544
case SPISD::RET_FLAG: return "SPISD::RET_FLAG";
15451545
case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG";
15461546
case SPISD::FLUSHW: return "SPISD::FLUSHW";
1547+
case SPISD::TLS_ADD: return "SPISD::TLS_ADD";
1548+
case SPISD::TLS_LD: return "SPISD::TLS_LD";
1549+
case SPISD::TLS_CALL: return "SPISD::TLS_CALL";
15471550
}
15481551
}
15491552

@@ -1699,6 +1702,103 @@ SDValue SparcTargetLowering::LowerBlockAddress(SDValue Op,
16991702
return makeAddress(Op, DAG);
17001703
}
17011704

1705+
SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op,
1706+
SelectionDAG &DAG) const {
1707+
1708+
GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
1709+
SDLoc DL(GA);
1710+
const GlobalValue *GV = GA->getGlobal();
1711+
EVT PtrVT = getPointerTy();
1712+
1713+
TLSModel::Model model = getTargetMachine().getTLSModel(GV);
1714+
1715+
if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) {
1716+
unsigned HiTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_HI22
1717+
: SPII::MO_TLS_LDM_HI22);
1718+
unsigned LoTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_LO10
1719+
: SPII::MO_TLS_LDM_LO10);
1720+
unsigned addTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_ADD
1721+
: SPII::MO_TLS_LDM_ADD);
1722+
unsigned callTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_CALL
1723+
: SPII::MO_TLS_LDM_CALL);
1724+
1725+
SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG);
1726+
SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
1727+
SDValue Argument = DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Base, HiLo,
1728+
withTargetFlags(Op, addTF, DAG));
1729+
1730+
SDValue Chain = DAG.getEntryNode();
1731+
SDValue InFlag;
1732+
1733+
Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(1, true), DL);
1734+
Chain = DAG.getCopyToReg(Chain, DL, SP::O0, Argument, InFlag);
1735+
InFlag = Chain.getValue(1);
1736+
SDValue Callee = DAG.getTargetExternalSymbol("__tls_get_addr", PtrVT);
1737+
SDValue Symbol = withTargetFlags(Op, callTF, DAG);
1738+
1739+
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1740+
SmallVector<SDValue, 4> Ops;
1741+
Ops.push_back(Chain);
1742+
Ops.push_back(Callee);
1743+
Ops.push_back(Symbol);
1744+
Ops.push_back(DAG.getRegister(SP::O0, PtrVT));
1745+
const uint32_t *Mask = getTargetMachine()
1746+
.getRegisterInfo()->getCallPreservedMask(CallingConv::C);
1747+
assert(Mask && "Missing call preserved mask for calling convention");
1748+
Ops.push_back(DAG.getRegisterMask(Mask));
1749+
Ops.push_back(InFlag);
1750+
Chain = DAG.getNode(SPISD::TLS_CALL, DL, NodeTys, &Ops[0], Ops.size());
1751+
InFlag = Chain.getValue(1);
1752+
Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(1, true),
1753+
DAG.getIntPtrConstant(0, true), InFlag, DL);
1754+
InFlag = Chain.getValue(1);
1755+
SDValue Ret = DAG.getCopyFromReg(Chain, DL, SP::O0, PtrVT, InFlag);
1756+
1757+
if (model != TLSModel::LocalDynamic)
1758+
return Ret;
1759+
1760+
SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
1761+
withTargetFlags(Op, SPII::MO_TLS_LDO_HIX22, DAG));
1762+
SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
1763+
withTargetFlags(Op, SPII::MO_TLS_LDO_LOX10, DAG));
1764+
HiLo = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
1765+
return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Ret, HiLo,
1766+
withTargetFlags(Op, SPII::MO_TLS_LDO_ADD, DAG));
1767+
}
1768+
1769+
if (model == TLSModel::InitialExec) {
1770+
unsigned ldTF = ((PtrVT == MVT::i64)? SPII::MO_TLS_IE_LDX
1771+
: SPII::MO_TLS_IE_LD);
1772+
1773+
SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
1774+
1775+
// GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
1776+
// function has calls.
1777+
MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
1778+
MFI->setHasCalls(true);
1779+
1780+
SDValue TGA = makeHiLoPair(Op,
1781+
SPII::MO_TLS_IE_HI22, SPII::MO_TLS_IE_LO10, DAG);
1782+
SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base, TGA);
1783+
SDValue Offset = DAG.getNode(SPISD::TLS_LD,
1784+
DL, PtrVT, Ptr,
1785+
withTargetFlags(Op, ldTF, DAG));
1786+
return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT,
1787+
DAG.getRegister(SP::G7, PtrVT), Offset,
1788+
withTargetFlags(Op, SPII::MO_TLS_IE_ADD, DAG));
1789+
}
1790+
1791+
assert(model == TLSModel::LocalExec);
1792+
SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
1793+
withTargetFlags(Op, SPII::MO_TLS_LE_HIX22, DAG));
1794+
SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
1795+
withTargetFlags(Op, SPII::MO_TLS_LE_LOX10, DAG));
1796+
SDValue Offset = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
1797+
1798+
return DAG.getNode(ISD::ADD, DL, PtrVT,
1799+
DAG.getRegister(SP::G7, PtrVT), Offset);
1800+
}
1801+
17021802
SDValue
17031803
SparcTargetLowering::LowerF128_LibCallArg(SDValue Chain, ArgListTy &Args,
17041804
SDValue Arg, SDLoc DL,
@@ -2333,8 +2433,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
23332433

23342434
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this);
23352435
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
2336-
case ISD::GlobalTLSAddress:
2337-
llvm_unreachable("TLS not implemented for Sparc.");
2436+
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
23382437
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
23392438
case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
23402439
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);

llvm/lib/Target/Sparc/SparcISelLowering.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,12 @@ namespace llvm {
4040

4141
CALL, // A call instruction.
4242
RET_FLAG, // Return with a flag operand.
43-
GLOBAL_BASE_REG, // Global base reg for PIC
44-
FLUSHW // FLUSH register windows to stack
43+
GLOBAL_BASE_REG, // Global base reg for PIC.
44+
FLUSHW, // FLUSH register windows to stack.
45+
46+
TLS_ADD, // For Thread Local Storage (TLS).
47+
TLS_LD,
48+
TLS_CALL
4549
};
4650
}
4751

@@ -119,6 +123,7 @@ namespace llvm {
119123
SDLoc DL, SelectionDAG &DAG) const;
120124

121125
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
126+
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
122127
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
123128
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
124129

llvm/lib/Target/Sparc/SparcInstr64Bit.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ def : Pat<(subc i64:$a, i64:$b), (SUBCCrr $a, $b)>;
162162

163163
def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>;
164164

165+
def : Pat<(tlsadd i64:$a, i64:$b, tglobaltlsaddr:$sym),
166+
(TLS_ADDrr $a, $b, $sym)>;
167+
165168
// Register-immediate instructions.
166169

167170
def : Pat<(and i64:$a, (i64 simm13:$b)), (ANDri $a, (as_i32imm $b))>;
@@ -237,6 +240,12 @@ def LDXri : F3_2<3, 0b001011,
237240
(outs I64Regs:$dst), (ins MEMri:$addr),
238241
"ldx [$addr], $dst",
239242
[(set i64:$dst, (load ADDRri:$addr))]>;
243+
let mayLoad = 1 in
244+
def TLS_LDXrr : F3_1<3, 0b001011,
245+
(outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
246+
"ldx [$addr], $dst, $sym",
247+
[(set i64:$dst,
248+
(tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>;
240249

241250
// Extending loads to i64.
242251
def : Pat<(i64 (zextloadi1 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>;

llvm/lib/Target/Sparc/SparcInstrInfo.td

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ def MEMri : Operand<iPTR> {
8585
let MIOperandInfo = (ops ptr_rc, i32imm);
8686
}
8787

88+
def TLSSym : Operand<iPTR>;
89+
8890
// Branch targets have OtherVT type.
8991
def brtarget : Operand<OtherVT>;
9092
def calltarget : Operand<i32>;
@@ -106,6 +108,11 @@ SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>;
106108
def SDTSPITOF :
107109
SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, f32>]>;
108110

111+
def SDTSPtlsadd :
112+
SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisPtrTy<2>]>;
113+
def SDTSPtlsld :
114+
SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
115+
109116
def SPcmpicc : SDNode<"SPISD::CMPICC", SDTSPcmpicc, [SDNPOutGlue]>;
110117
def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>;
111118
def SPbricc : SDNode<"SPISD::BRICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;
@@ -144,6 +151,12 @@ def retflag : SDNode<"SPISD::RET_FLAG", SDT_SPRet,
144151
def flushw : SDNode<"SPISD::FLUSHW", SDTNone,
145152
[SDNPHasChain, SDNPSideEffect, SDNPMayStore]>;
146153

154+
def tlsadd : SDNode<"SPISD::TLS_ADD", SDTSPtlsadd>;
155+
def tlsld : SDNode<"SPISD::TLS_LD", SDTSPtlsld>;
156+
def tlscall : SDNode<"SPISD::TLS_CALL", SDT_SPCall,
157+
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
158+
SDNPVariadic]>;
159+
147160
def getPCX : Operand<i32> {
148161
let PrintMethod = "printGetPCX";
149162
}
@@ -806,6 +819,34 @@ let Defs = [FCC] in {
806819
Requires<[HasHardQuad]>;
807820
}
808821

822+
//===----------------------------------------------------------------------===//
823+
// Instructions for Thread Local Storage(TLS).
824+
//===----------------------------------------------------------------------===//
825+
826+
def TLS_ADDrr : F3_1<2, 0b000000,
827+
(outs IntRegs:$rd),
828+
(ins IntRegs:$rs1, IntRegs:$rs2, TLSSym:$sym),
829+
"add $rs1, $rs2, $rd, $sym",
830+
[(set i32:$rd,
831+
(tlsadd i32:$rs1, i32:$rs2, tglobaltlsaddr:$sym))]>;
832+
833+
let mayLoad = 1 in
834+
def TLS_LDrr : F3_1<3, 0b000000,
835+
(outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
836+
"ld [$addr], $dst, $sym",
837+
[(set i32:$dst,
838+
(tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>;
839+
840+
let Uses = [O6], isCall = 1 in
841+
def TLS_CALL : InstSP<(outs),
842+
(ins calltarget:$disp, TLSSym:$sym, variable_ops),
843+
"call $disp, $sym\n\tnop",
844+
[(tlscall texternalsym:$disp, tglobaltlsaddr:$sym)]> {
845+
bits<30> disp;
846+
let op = 1;
847+
let Inst{29-0} = disp;
848+
}
849+
809850
//===----------------------------------------------------------------------===//
810851
// V9 Instructions
811852
//===----------------------------------------------------------------------===//
@@ -915,6 +956,14 @@ def : Pat<(SPlo tglobaladdr:$in), (ORri (i32 G0), tglobaladdr:$in)>;
915956
def : Pat<(SPhi tconstpool:$in), (SETHIi tconstpool:$in)>;
916957
def : Pat<(SPlo tconstpool:$in), (ORri (i32 G0), tconstpool:$in)>;
917958

959+
// GlobalTLS addresses
960+
def : Pat<(SPhi tglobaltlsaddr:$in), (SETHIi tglobaltlsaddr:$in)>;
961+
def : Pat<(SPlo tglobaltlsaddr:$in), (ORri (i32 G0), tglobaltlsaddr:$in)>;
962+
def : Pat<(add (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)),
963+
(ADDri (SETHIi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>;
964+
def : Pat<(xor (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)),
965+
(XORri (SETHIi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>;
966+
918967
// Blockaddress
919968
def : Pat<(SPhi tblockaddress:$in), (SETHIi tblockaddress:$in)>;
920969
def : Pat<(SPlo tblockaddress:$in), (ORri (i32 G0), tblockaddress:$in)>;

0 commit comments

Comments
 (0)