diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp index 7d8afbf9915b..eec993a4b9e6 100644 --- a/llvm/lib/MC/XCOFFObjectWriter.cpp +++ b/llvm/lib/MC/XCOFFObjectWriter.cpp @@ -649,6 +649,13 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm, uint64_t &FixedValue) { auto getIndex = [this](const MCSymbol *Sym, const MCSectionXCOFF *ContainingCsect) { + // AIX TLS local-dynamic mode hack + if (Sym->getName().equals("_Renamed..5f24__TLSML[UA]")) { + for (auto Iter : SymbolIndexMap) + if (Iter.first->getName().equals("_Renamed..5f24__TLSML[TC]")) + return Iter.second; + llvm_unreachable("_Renamed..5f24__TLSML[TC] not found!"); + } // If we could not find the symbol directly in SymbolIndexMap, this symbol // could either be a temporary symbol or an undefined symbol. In this case, // we would need to have the relocation reference its csect instead. diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index 00dda306a584..a38e2b5802d8 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -241,10 +241,12 @@ public: Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM || Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE || Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE || - Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD || - Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML) + Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD) OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@" << MCSymbolRefExpr::getVariantKindName(Kind) << '\n'; + else if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML) + OS << "\t.tc " << TCSym->getName() << "," << TCSym->getName() << "@" + << MCSymbolRefExpr::getVariantKindName(Kind) << '\n'; else OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << '\n'; diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index b301cf675b12..1e3b1a9eb86a 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -777,10 +777,10 @@ getTOCEntryTypeForMO(const MachineOperand &MO) { // On AIX, TLS-local-dynamic requires that the symbol for the module handle must // have the name "_$TLSML". This symbol is used as one TOC symbol reference // itself with an ML relocation type, thus it has "[TC]" attached to its name. -static inline bool isSpecialAIXSymbolTLSML(const MachineOperand &MO, - const bool IsAIX) { - return IsAIX && MO.isSymbol() && - (std::strcmp(MO.getSymbolName(), "_$TLSML[TC]") == 0); +static inline bool isSpecialTLSMLForAIX(const MachineOperand &MO, + const bool IsAIX) { + return IsAIX && MO.isGlobal() && + (MO.getGlobal()->getName().equals("_$TLSML")); } /// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to @@ -873,7 +873,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { if (MO.getTargetFlags() & PPCII::MO_TLSGD_FLAG) return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD; if (MO.getTargetFlags() & PPCII::MO_TLSLD_FLAG) { - if (isSpecialAIXSymbolTLSML(MO, IsAIX)) + if (isSpecialTLSMLForAIX(MO, IsAIX)) // FIXME: Due to the size limit of MachineOperand::SubReg_TargetFlags, // hacked this flag which should have been named MO_TLSLDM_FLAG: on AIX // the ML relocation type is only valid for a reference to a TOC symbol @@ -1001,8 +1001,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(PPC::LWZ); const MachineOperand &MO = MI->getOperand(1); - assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() || - isSpecialAIXSymbolTLSML(MO, IsAIX)) && + assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && "Invalid operand for LWZtoc."); // Map the operand to its corresponding MCSymbol. @@ -1091,8 +1090,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(PPC::LD); const MachineOperand &MO = MI->getOperand(1); - assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() || - isSpecialAIXSymbolTLSML(MO, IsAIX)) && + assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && "Invalid operand!"); // Map the operand to its corresponding MCSymbol. @@ -1130,8 +1128,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(PPC::ADDIS); const MachineOperand &MO = MI->getOperand(2); - assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() || - isSpecialAIXSymbolTLSML(MO, IsAIX)) && + assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && "Invalid operand for ADDIStocHA."); // Map the machine operand to its corresponding MCSymbol. @@ -1164,8 +1161,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(PPC::LWZ); const MachineOperand &MO = MI->getOperand(1); - assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() || - isSpecialAIXSymbolTLSML(MO, IsAIX)) && + assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && "Invalid operand for LWZtocL."); // Map the machine operand to its corresponding MCSymbol. @@ -1197,8 +1193,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(PPC::ADDIS8); const MachineOperand &MO = MI->getOperand(2); - assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() || - isSpecialAIXSymbolTLSML(MO, IsAIX)) && + assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && "Invalid operand for ADDIStocHA8!"); const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this); @@ -1208,8 +1203,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { const bool GlobalToc = MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal()); if (GlobalToc || MO.isJTI() || MO.isBlockAddress() || - (MO.isCPI() && TM.getCodeModel() == CodeModel::Large) || - isSpecialAIXSymbolTLSML(MO, IsAIX)) + (MO.isCPI() && TM.getCodeModel() == CodeModel::Large)) MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); VK = IsAIX ? MCSymbolRefExpr::VK_PPC_U : MCSymbolRefExpr::VK_PPC_TOC_HA; @@ -1238,8 +1232,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(PPC::LD); const MachineOperand &MO = MI->getOperand(1); - assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() || - isSpecialAIXSymbolTLSML(MO, IsAIX)) && + assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && "Invalid operand for LDtocL!"); LLVM_DEBUG(assert( diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 433b9792d1fe..349d8793ba23 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -3423,11 +3423,20 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op, // there should be no symbol-table entry referring to the module-handle). // Instead we will create reference to __TLSML[TC]@ml in PPCTLSDynamicCall // when processing the TLSLD_AIX pseudo node. - SDValue ModuleHandle = DAG.getNode(PPCISD::TLSLD_AIX, dl, PtrVT); SDValue VariableOffsetTGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TLSLD_FLAG); + + Module *M = DAG.getMachineFunction().getFunction().getParent(); + GlobalVariable *TLSGV = + dyn_cast_or_null(M->getOrInsertGlobal( + StringRef("_$TLSML"), PointerType::getUnqual(*DAG.getContext()))); + assert(TLSGV && "Not able to create GV for _$TLSML."); + SDValue ModuleHandleTGA = + DAG.getTargetGlobalAddress(TLSGV, dl, PtrVT, 0, PPCII::MO_TLSLD_FLAG); + SDValue ModuleHandle = getTOCEntry(DAG, dl, ModuleHandleTGA); + SDValue MHOffset = DAG.getNode(PPCISD::TLSLD_AIX, dl, PtrVT, ModuleHandle); SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA); - return DAG.getNode(ISD::ADD, dl, PtrVT, ModuleHandle, VariableOffset); + return DAG.getNode(ISD::ADD, dl, PtrVT, MHOffset, VariableOffset); } // If Local- or Initial-exec or Local-dynamic is not possible or specified, diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td index 0f11c8c4867d..263b564e94c4 100644 --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -1630,8 +1630,8 @@ def TLSGDAIX8 : [(set i64:$rD, (PPCTlsgdAIX i64:$offset, i64:$handle))]>; // This pseudo is expanded to load module-handle in X3, and the call to GETtlsMOD64AIX. -def TLSLDAIX8 : PPCEmitTimePseudo<(outs g8rc:$rD), (ins), - "#TLSLDAIX8", [(set i64:$rD, (PPCTlsldAIX))]>; +def TLSLDAIX8 : PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc:$handle), + "#TLSLDAIX8", [(set i64:$rD, (PPCTlsldAIX i64:$handle))]>; // Combined op for ADDItlsldL and GETtlsADDR, late expanded. X3 and LR8 // are true defines, while the rest of the Defs are clobbers. let hasExtraSrcRegAllocReq = 1, hasExtraDefRegAllocReq = 1, diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index b2adf2fb1814..9102da206c17 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -220,7 +220,7 @@ def PPCaddiTlsgdLAddr : SDNode<"PPCISD::ADDI_TLSGD_L_ADDR", SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>, SDTCisInt<0> ]>>; def PPCTlsgdAIX : SDNode<"PPCISD::TLSGD_AIX", SDTIntBinOp>; -def PPCTlsldAIX : SDNode<"PPCISD::TLSLD_AIX", SDTIntLeaf>; +def PPCTlsldAIX : SDNode<"PPCISD::TLSLD_AIX", SDTIntUnaryOp>; def PPCaddisTlsldHA : SDNode<"PPCISD::ADDIS_TLSLD_HA", SDTIntBinOp>; def PPCaddiTlsldL : SDNode<"PPCISD::ADDI_TLSLD_L", SDTIntBinOp>; def PPCgetTlsldAddr : SDNode<"PPCISD::GET_TLSLD_ADDR", SDTIntBinOp>; @@ -3289,8 +3289,8 @@ def TLSGDAIX : PPCEmitTimePseudo<(outs gprc:$rD), (ins gprc:$offset, gprc:$handl [(set i32:$rD, (PPCTlsgdAIX i32:$offset, i32:$handle))]>; // This pseudo is expanded to load module-handle in R3, and the call to GETtlsMOD32AIX. -def TLSLDAIX : PPCEmitTimePseudo<(outs gprc:$rD), (ins), - "#TLSLDAIX", [(set i32:$rD, (PPCTlsldAIX))]>; +def TLSLDAIX : PPCEmitTimePseudo<(outs gprc:$rD), (ins gprc:$handle), + "#TLSLDAIX", [(set i32:$rD, (PPCTlsldAIX i32:$handle))]>; // LR is a true define, while the rest of the Defs are clobbers. R3 is // explicitly defined when this op is created, so not mentioned here. let hasExtraSrcRegAllocReq = 1, hasExtraDefRegAllocReq = 1, diff --git a/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp b/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp index 71825dca77bc..5c2d2ab844d1 100644 --- a/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp +++ b/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp @@ -53,9 +53,6 @@ protected: bool IsPCREL = false; MachineFunction *MF = MBB.getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); - const TargetRegisterClass *GPRNoZero = - Is64Bit ? &PPC::G8RC_and_G8RC_NOX0RegClass - : &PPC::GPRC_and_GPRC_NOR0RegClass; for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end(); I != IE;) { @@ -189,58 +186,73 @@ protected: break; if (UseIter != MBB.end()) { + // FIXME update comment: look for two LDTocOp // Get the instruction that defines the other used register // operand of UseIter. The match pattern is that: UseIter has // exactly one used-operand defined by LDTocOp // (LDtocL/LDtoc/LWZtocL/LWZtoc). - MachineInstr *LoadOffsetToc = nullptr; - int MatchCount = 0; + std::set LoadFromTocs; for (MachineOperand &MO : UseIter->operands()) { if (MO.isReg() && MO.isUse()) { if (RegInfo.hasOneDef(MO.getReg())) { - if (RegInfo.getOneDef(MO.getReg()) - ->getParent() - ->getOpcode() == LDTocOp) { - LoadOffsetToc = - RegInfo.getOneDef(MO.getReg())->getParent(); - ++MatchCount; + MachineInstr *Temp = + RegInfo.getOneDef(MO.getReg())->getParent(); + if (Temp->getOpcode() == LDTocOp) + LoadFromTocs.insert( + RegInfo.getOneDef(MO.getReg())->getParent()); + else if (Temp == &MI) { + if (RegInfo.hasOneDef(MI.getOperand(1).getReg())) { + Temp = RegInfo.getOneDef(MI.getOperand(1).getReg()) + ->getParent(); + if (Temp->getOpcode() == LDTocOp) + LoadFromTocs.insert(Temp); + } } } else { // FIXME: analyze this scenario if there is one. - MatchCount = 0; + LoadFromTocs.clear(); break; } } } - // Get the iterator. - if (MatchCount == 1 && LoadOffsetToc) { - Anchor = MBB.begin(); - for (MachineBasicBlock::iterator AE = MBB.end(); Anchor != AE; - ++Anchor) - if (&*Anchor == LoadOffsetToc) - break; - - if (Anchor == MBB.end()) - Anchor = I; + // If there are two LoadFromToc, check their operands and swap + // instructions if necessary, and then get the anchor point. + if (LoadFromTocs.size() == 2) { + SmallVector IterVec; + for (MachineBasicBlock::iterator AI = MBB.begin(), + AE = MBB.end(); + AI != AE; ++AI) + if (LoadFromTocs.count(&*AI)) + IterVec.push_back(AI); + assert(IterVec.size() == 2 && "FIXME."); + if (IterVec[0]->getOperand(1).isGlobal() && + IterVec[0]->getOperand(1).getGlobal()->getName().equals( + "_$TLSML")) { + Anchor = IterVec[1]; + } else if (IterVec[1]->getOperand(1).isGlobal() && + IterVec[1] + ->getOperand(1) + .getGlobal() + ->getName() + .equals("_$TLSML")) { + MachineInstr *Temp = &*IterVec[0]; + IterVec[1]->moveBefore(&*IterVec[0]); + for (MachineBasicBlock::iterator AI = MBB.begin(), + AE = MBB.end(); + AI != AE; ++AI) + if (&*AI == Temp) { + Anchor = AI; + break; + } + } } } } - // Generate instructions to load module-handle. - Register ModuleHandleHReg; - if (IsLargeModel) { - ModuleHandleHReg = RegInfo.createVirtualRegister(GPRNoZero); - BuildMI(MBB, Anchor, DL, - TII->get(Is64Bit ? PPC::ADDIStocHA8 : PPC::ADDIStocHA), - ModuleHandleHReg) - .addReg(Subtarget.getTOCPointerRegister()) - .addExternalSymbol("_$TLSML[TC]", PPCII::MO_TLSLD_FLAG); - } - BuildMI(MBB, Anchor, DL, TII->get(LDTocOp), GPR3) - .addExternalSymbol("_$TLSML[TC]", PPCII::MO_TLSLD_FLAG) - .addReg(IsLargeModel - ? ModuleHandleHReg - : Register(Subtarget.getTOCPointerRegister())); + // The module-handle is copied in r3. The copy is followed by + // GETtlsMOD32AIX/GETtlsMOD64AIX. + BuildMI(MBB, Anchor, DL, TII->get(TargetOpcode::COPY), GPR3) + .addReg(MI.getOperand(1).getReg()); // The call to .__tls_get_mod. BuildMI(MBB, Anchor, DL, TII->get(Opc2), GPR3).addReg(GPR3); } else if (!IsTLSTPRelMI) {