mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 12:50:00 +00:00
Implement initial-exec TLS for PPC32.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197824 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9413345f40
commit
ed4678820b
@ -301,6 +301,7 @@ MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(MCSymbol *Sym) {
|
||||
///
|
||||
void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
MCInst TmpInst;
|
||||
bool isPPC64 = Subtarget.isPPC64();
|
||||
|
||||
// Lower multi-instruction pseudo operations.
|
||||
switch (MI->getOpcode()) {
|
||||
@ -494,12 +495,13 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
.addExpr(SymGotTprel));
|
||||
return;
|
||||
}
|
||||
case PPC::LDgotTprelL: {
|
||||
case PPC::LDgotTprelL:
|
||||
case PPC::LDgotTprelL32: {
|
||||
// Transform %Xd = LDgotTprelL <ga:@sym>, %Xs
|
||||
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
|
||||
|
||||
// Change the opcode to LD.
|
||||
TmpInst.setOpcode(PPC::LD);
|
||||
TmpInst.setOpcode(isPPC64 ? PPC::LD : PPC::LWZ);
|
||||
const MachineOperand &MO = MI->getOperand(1);
|
||||
const GlobalValue *GValue = MO.getGlobal();
|
||||
MCSymbol *MOSymbol = getSymbol(GValue);
|
||||
@ -510,6 +512,24 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
OutStreamer.EmitInstruction(TmpInst);
|
||||
return;
|
||||
}
|
||||
|
||||
case PPC::PPC32GOT: {
|
||||
MCSymbol *GOTSymbol = OutContext.GetOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
|
||||
const MCExpr *SymGotTlsL =
|
||||
MCSymbolRefExpr::Create(GOTSymbol, MCSymbolRefExpr::VK_PPC_LO,
|
||||
OutContext);
|
||||
const MCExpr *SymGotTlsHA =
|
||||
MCSymbolRefExpr::Create(GOTSymbol, MCSymbolRefExpr::VK_PPC_HA,
|
||||
OutContext);
|
||||
OutStreamer.EmitInstruction(MCInstBuilder(PPC::LI)
|
||||
.addReg(MI->getOperand(0).getReg())
|
||||
.addExpr(SymGotTlsL));
|
||||
OutStreamer.EmitInstruction(MCInstBuilder(PPC::ADDIS)
|
||||
.addReg(MI->getOperand(0).getReg())
|
||||
.addReg(MI->getOperand(0).getReg())
|
||||
.addExpr(SymGotTlsHA));
|
||||
return;
|
||||
}
|
||||
case PPC::ADDIStlsgdHA: {
|
||||
// Transform: %Xd = ADDIStlsgdHA %X2, <ga:@sym>
|
||||
// Into: %Xd = ADDIS8 %X2, sym@got@tlsgd@ha
|
||||
|
@ -670,6 +670,7 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case PPCISD::ADDIS_TOC_HA: return "PPCISD::ADDIS_TOC_HA";
|
||||
case PPCISD::LD_TOC_L: return "PPCISD::LD_TOC_L";
|
||||
case PPCISD::ADDI_TOC_L: return "PPCISD::ADDI_TOC_L";
|
||||
case PPCISD::PPC32_GOT: return "PPCISD::PPC32_GOT";
|
||||
case PPCISD::ADDIS_GOT_TPREL_HA: return "PPCISD::ADDIS_GOT_TPREL_HA";
|
||||
case PPCISD::LD_GOT_TPREL_L: return "PPCISD::LD_GOT_TPREL_L";
|
||||
case PPCISD::ADD_TLS: return "PPCISD::ADD_TLS";
|
||||
@ -1431,18 +1432,19 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,
|
||||
return DAG.getNode(PPCISD::Lo, dl, PtrVT, TGALo, Hi);
|
||||
}
|
||||
|
||||
if (!is64bit)
|
||||
llvm_unreachable("only local-exec is currently supported for ppc32");
|
||||
|
||||
if (Model == TLSModel::InitialExec) {
|
||||
SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, 0);
|
||||
SDValue TGATLS = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0,
|
||||
PPCII::MO_TLS);
|
||||
SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
|
||||
SDValue TPOffsetHi = DAG.getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl,
|
||||
PtrVT, GOTReg, TGA);
|
||||
SDValue GOTPtr;
|
||||
if (is64bit) {
|
||||
SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
|
||||
GOTPtr = DAG.getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl,
|
||||
PtrVT, GOTReg, TGA);
|
||||
} else
|
||||
GOTPtr = DAG.getNode(PPCISD::PPC32_GOT, dl, PtrVT);
|
||||
SDValue TPOffset = DAG.getNode(PPCISD::LD_GOT_TPREL_L, dl,
|
||||
PtrVT, TGA, TPOffsetHi);
|
||||
PtrVT, TGA, GOTPtr);
|
||||
return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TPOffset, TGATLS);
|
||||
}
|
||||
|
||||
|
@ -177,6 +177,8 @@ namespace llvm {
|
||||
CR6SET,
|
||||
CR6UNSET,
|
||||
|
||||
PPC32_GOT,
|
||||
|
||||
/// G8RC = ADDIS_GOT_TPREL_HA %X2, Symbol - Used by the initial-exec
|
||||
/// TLS model, produces an ADDIS8 instruction that adds the GOT
|
||||
/// base to sym\@got\@tprel\@ha.
|
||||
|
@ -39,10 +39,6 @@ def s17imm64 : Operand<i64> {
|
||||
def tocentry : Operand<iPTR> {
|
||||
let MIOperandInfo = (ops i64imm:$imm);
|
||||
}
|
||||
def PPCTLSRegOperand : AsmOperandClass {
|
||||
let Name = "TLSReg"; let PredicateMethod = "isTLSReg";
|
||||
let RenderMethod = "addTLSRegOperands";
|
||||
}
|
||||
def tlsreg : Operand<i64> {
|
||||
let EncoderMethod = "getTLSRegEncoding";
|
||||
let ParserMatchClass = PPCTLSRegOperand;
|
||||
|
@ -99,6 +99,8 @@ def PPCtoc_entry: SDNode<"PPCISD::TOC_ENTRY", SDTIntBinOp, [SDNPMayLoad]>;
|
||||
def PPCvmaddfp : SDNode<"PPCISD::VMADDFP", SDTFPTernaryOp, []>;
|
||||
def PPCvnmsubfp : SDNode<"PPCISD::VNMSUBFP", SDTFPTernaryOp, []>;
|
||||
|
||||
def PPCppc32GOT : SDNode<"PPCISD::PPC32_GOT", SDTIntLeaf, []>;
|
||||
|
||||
def PPCaddisGotTprelHA : SDNode<"PPCISD::ADDIS_GOT_TPREL_HA", SDTIntBinOp>;
|
||||
def PPCldGotTprelL : SDNode<"PPCISD::LD_GOT_TPREL_L", SDTIntBinOp,
|
||||
[SDNPMayLoad]>;
|
||||
@ -564,6 +566,14 @@ def memrix : Operand<iPTR> { // memri where the imm is 4-aligned.
|
||||
def memr : Operand<iPTR> {
|
||||
let MIOperandInfo = (ops ptr_rc:$ptrreg);
|
||||
}
|
||||
def PPCTLSRegOperand : AsmOperandClass {
|
||||
let Name = "TLSReg"; let PredicateMethod = "isTLSReg";
|
||||
let RenderMethod = "addTLSRegOperands";
|
||||
}
|
||||
def tlsreg32 : Operand<i32> {
|
||||
let EncoderMethod = "getTLSRegEncoding";
|
||||
let ParserMatchClass = PPCTLSRegOperand;
|
||||
}
|
||||
|
||||
// PowerPC Predicate operand.
|
||||
def pred : Operand<OtherVT> {
|
||||
@ -1994,6 +2004,10 @@ let PPC970_Unit = 1, neverHasSideEffects = 1 in { // FXU Operations.
|
||||
defm ADD4 : XOForm_1r<31, 266, 0, (outs gprc:$rT), (ins gprc:$rA, gprc:$rB),
|
||||
"add", "$rT, $rA, $rB", IIC_IntSimple,
|
||||
[(set i32:$rT, (add i32:$rA, i32:$rB))]>;
|
||||
let isCodeGenOnly = 1 in
|
||||
def ADD4TLS : XOForm_1<31, 266, 0, (outs gprc:$rT), (ins gprc:$rA, tlsreg32:$rB),
|
||||
"add $rT, $rA, $rB", IIC_IntSimple,
|
||||
[(set i32:$rT, (add i32:$rA, tglobaltlsaddr:$rB))]>;
|
||||
defm ADDC : XOForm_1rc<31, 10, 0, (outs gprc:$rT), (ins gprc:$rA, gprc:$rB),
|
||||
"addc", "$rT, $rA, $rB", IIC_IntGeneral,
|
||||
[(set i32:$rT, (addc i32:$rA, i32:$rB))]>,
|
||||
@ -2259,6 +2273,17 @@ def : Pat<(add i32:$in, (PPChi tjumptable:$g, 0)),
|
||||
def : Pat<(add i32:$in, (PPChi tblockaddress:$g, 0)),
|
||||
(ADDIS $in, tblockaddress:$g)>;
|
||||
|
||||
// Support for thread-local storage.
|
||||
def PPC32GOT: Pseudo<(outs gprc:$rD), (ins), "#PPC32GOT",
|
||||
[(set i32:$rD, (PPCppc32GOT))]>;
|
||||
|
||||
def LDgotTprelL32: Pseudo<(outs gprc:$rD), (ins s16imm:$disp, gprc_nor0:$reg),
|
||||
"#LDgotTprelL32",
|
||||
[(set i32:$rD,
|
||||
(PPCldGotTprelL tglobaltlsaddr:$disp, i32:$reg))]>;
|
||||
def : Pat<(PPCaddTls i32:$in, tglobaltlsaddr:$g),
|
||||
(ADD4TLS $in, tglobaltlsaddr:$g)>;
|
||||
|
||||
// Standard shifts. These are represented separately from the real shifts above
|
||||
// so that we can distinguish between shifts that allow 5-bit and 6-bit shift
|
||||
// amounts.
|
||||
|
@ -1,5 +1,6 @@
|
||||
; RUN: llc -O0 < %s -march=ppc64 -mcpu=ppc64 | FileCheck -check-prefix=OPT0 %s
|
||||
; RUN: llc -O1 < %s -march=ppc64 -mcpu=ppc64 | FileCheck -check-prefix=OPT1 %s
|
||||
; RUN: llc -O0 < %s -march=ppc32 -mcpu=ppc | FileCheck -check-prefix=OPT0-PPC32 %s
|
||||
|
||||
target triple = "powerpc64-unknown-linux-gnu"
|
||||
|
||||
@ -38,3 +39,8 @@ entry:
|
||||
; OPT1: ld [[REG2:[0-9]+]], a2@got@tprel@l([[REG1]])
|
||||
; OPT1: add {{[0-9]+}}, [[REG2]], a2@tls
|
||||
|
||||
;OPT0-PPC32-LABEL: main2:
|
||||
;OPT0-PPC32: li [[REG1:[0-9]+]], _GLOBAL_OFFSET_TABLE_@l
|
||||
;OPT0-PPC32: addis [[REG1]], [[REG1]], _GLOBAL_OFFSET_TABLE_@ha
|
||||
;OPT0-PPC32: lwz [[REG2:[0-9]+]], a2@got@tprel@l([[REG1]])
|
||||
;OPT0-PPC32: add 3, [[REG2]], a2@tls
|
||||
|
Loading…
Reference in New Issue
Block a user