mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 04:33:05 +00:00
[Sparc] Add support for TLS in sparc.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191164 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7d7db75a55
commit
7d052f272d
@ -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
|
||||
|
@ -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()) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)>;
|
||||
|
@ -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";
|
||||
}
|
||||
@ -806,6 +819,34 @@ let Defs = [FCC] in {
|
||||
Requires<[HasHardQuad]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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)>;
|
||||
|
73
test/CodeGen/SPARC/tls.ll
Normal file
73
test/CodeGen/SPARC/tls.ll
Normal file
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user