Index: lib/Target/PowerPC/PPCAsmPrinter.cpp =================================================================== --- lib/Target/PowerPC/PPCAsmPrinter.cpp +++ lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -669,30 +669,29 @@ MO.isBlockAddress()) && "Invalid operand for ADDIStocHA!"); MCSymbol *MOSymbol = nullptr; - bool IsExternal = false; - bool IsNonLocalFunction = false; - bool IsCommon = false; - bool IsAvailExt = false; + bool GlobalToc = false; if (MO.isGlobal()) { const GlobalValue *GV = MO.getGlobal(); MOSymbol = getSymbol(GV); - IsExternal = GV->isDeclaration(); - IsCommon = GV->hasCommonLinkage(); - IsNonLocalFunction = GV->getType()->getElementType()->isFunctionTy() && - !GV->isStrongDefinitionForLinker(); - IsAvailExt = GV->hasAvailableExternallyLinkage(); - } else if (MO.isCPI()) + // ADDIStocHA is already a PIC style access, if a direct access was what + // was wanted, the generator wouldn't have used ADDIStocHA. Force PIC for + // the classifier. + unsigned char gv_flags = Subtarget->classifyGlobalReference(GV, true); + GlobalToc = ((gv_flags & PPCII::MO_NLP_FLAG) || + (gv_flags & PPCII::MO_NLP_HIDDEN_FLAG)); + } else if (MO.isCPI()) { MOSymbol = GetCPISymbol(MO.getIndex()); - else if (MO.isJTI()) + } else if (MO.isJTI()) { MOSymbol = GetJTISymbol(MO.getIndex()); - else if (MO.isBlockAddress()) + } else if (MO.isBlockAddress()) { MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress()); + } - if (IsExternal || IsNonLocalFunction || IsCommon || IsAvailExt || - MO.isJTI() || MO.isBlockAddress() || - TM.getCodeModel() == CodeModel::Large) + if (GlobalToc || MO.isJTI() || MO.isBlockAddress() || + TM.getCodeModel() == CodeModel::Large) { MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); + } const MCExpr *Exp = MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_HA, @@ -727,13 +726,18 @@ MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); } else if (MO.isGlobal()) { - const GlobalValue *GValue = MO.getGlobal(); - MOSymbol = getSymbol(GValue); - if (GValue->getType()->getElementType()->isFunctionTy() || - GValue->isDeclaration() || GValue->hasCommonLinkage() || - GValue->hasAvailableExternallyLinkage() || - TM.getCodeModel() == CodeModel::Large) - MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); + const GlobalValue *GV = MO.getGlobal(); + MOSymbol = getSymbol(GV); + DEBUG( + // LDtocL is already a PIC style access, if a direct access was what + // was wanted, the generator wouldn't have used ADDIStocHA. Force PIC for + // the classifier. + unsigned char gv_flags = Subtarget->classifyGlobalReference(GV, true); + assert(((gv_flags & PPCII::MO_NLP_FLAG) || + (gv_flags & PPCII::MO_NLP_HIDDEN_FLAG)) && + "LDtocL used on symbol that could be accessed directly is " + "invalid. Must match ADDIStocHA.")); + MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); } const MCExpr *Exp = @@ -754,21 +758,22 @@ const MachineOperand &MO = MI->getOperand(2); assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL"); MCSymbol *MOSymbol = nullptr; - bool IsExternal = false; - bool IsNonLocalFunction = false; if (MO.isGlobal()) { const GlobalValue *GV = MO.getGlobal(); + DEBUG( + // ADDItocL is already a PIC style access, if a direct access was what + // was wanted, the generator wouldn't have used ADDIStocHA. Force PIC for + // the classifier. + unsigned char gv_flags = Subtarget->classifyGlobalReference(GV, true); + assert ( + !(gv_flags & PPCII::MO_NLP_FLAG) && + !(gv_flags & PPCII::MO_NLP_HIDDEN_FLAG) && + "Interposable definitions must use indirect access.")); MOSymbol = getSymbol(GV); - IsExternal = GV->isDeclaration(); - IsNonLocalFunction = GV->getType()->getElementType()->isFunctionTy() && - !GV->isStrongDefinitionForLinker(); - } else if (MO.isCPI()) + } else if (MO.isCPI()) { MOSymbol = GetCPISymbol(MO.getIndex()); - - if (IsNonLocalFunction || IsExternal || - TM.getCodeModel() == CodeModel::Large) - MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); + } const MCExpr *Exp = MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_LO, Index: lib/Target/PowerPC/PPCFastISel.cpp =================================================================== --- lib/Target/PowerPC/PPCFastISel.cpp +++ lib/Target/PowerPC/PPCFastISel.cpp @@ -1972,19 +1972,18 @@ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::ADDIStocHA), HighPartReg).addReg(PPC::X2).addGlobalAddress(GV); - // If/when switches are implemented, jump tables should be handled - // on the "if" path here. - if (CModel == CodeModel::Large || - (GV->getType()->getElementType()->isFunctionTy() && - !GV->isStrongDefinitionForLinker()) || - GV->isDeclaration() || GV->hasCommonLinkage() || - GV->hasAvailableExternallyLinkage()) + // For ELFv2 ABI, we could generate non-PIC accesses, but we don't. + // Since we're forcing PIC, let the classifier know. + unsigned char gv_flags = PPCSubTarget->classifyGlobalReference(GV, true); + if ((gv_flags & PPCII::MO_NLP_FLAG) || + (gv_flags & PPCII::MO_NLP_HIDDEN_FLAG)) { BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::LDtocL), DestReg).addGlobalAddress(GV).addReg(HighPartReg); - else + } else { // Otherwise generate the ADDItocL. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(PPC::ADDItocL), DestReg).addReg(HighPartReg).addGlobalAddress(GV); + } } return DestReg; Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -2902,9 +2902,7 @@ break; // The first source operand is a TargetGlobalAddress or a TargetJumpTable. - // If it is an externally defined symbol, a symbol with common linkage, - // a non-local function address, or a jump table address, or if we are - // generating code for large code model, we generate: + // If it must be toc-referenced according to PPCSubTarget, we generate: // LDtocL(, ADDIStocHA(%X2, )) // Otherwise we generate: // ADDItocL(ADDIStocHA(%X2, ), ) @@ -2919,13 +2917,16 @@ MVT::i64, GA, SDValue(Tmp, 0))); if (GlobalAddressSDNode *G = dyn_cast(GA)) { - const GlobalValue *GValue = G->getGlobal(); - if ((GValue->getType()->getElementType()->isFunctionTy() && - !GValue->isStrongDefinitionForLinker()) || - GValue->isDeclaration() || GValue->hasCommonLinkage() || - GValue->hasAvailableExternallyLinkage()) + const GlobalValue *GV = G->getGlobal(); + // TOC_ENTRY should only be created when PIC access is required. A direct + // access can be generated otherwise. Force PIC when classifying to avoid + // an incosistency. + unsigned char gv_flags = PPCSubTarget->classifyGlobalReference(GV, true); + if ((gv_flags & PPCII::MO_NLP_FLAG) || + (gv_flags & PPCII::MO_NLP_HIDDEN_FLAG)) { return transferMemOperands(N, CurDAG->getMachineNode(PPC::LDtocL, dl, MVT::i64, GA, SDValue(Tmp, 0))); + } } return CurDAG->getMachineNode(PPC::ADDItocL, dl, MVT::i64, Index: lib/Target/PowerPC/PPCSubtarget.h =================================================================== --- lib/Target/PowerPC/PPCSubtarget.h +++ lib/Target/PowerPC/PPCSubtarget.h @@ -269,6 +269,10 @@ bool isSVR4ABI() const { return !isDarwinABI(); } bool isELFv2ABI() const; + /// isPIC - True if the relocation model, the abi, or the code model require + /// PIC accesses. + bool isPIC() const; + bool enableEarlyIfConversion() const override { return hasISEL(); } // Scheduling customization. @@ -285,6 +289,11 @@ bool useAA() const override; bool enableSubRegLiveness() const override; + + /// ClassifyGlobalReference - Classify a global variable reference for the + /// current subtarget accourding to how we should reference it. + unsigned char classifyGlobalReference(const GlobalValue *GV) const; + unsigned char classifyGlobalReference(const GlobalValue *GV, bool forcePIC) const; }; } // End llvm namespace Index: lib/Target/PowerPC/PPCSubtarget.cpp =================================================================== --- lib/Target/PowerPC/PPCSubtarget.cpp +++ lib/Target/PowerPC/PPCSubtarget.cpp @@ -210,5 +210,51 @@ return UseSubRegLiveness; } +unsigned char PPCSubtarget::classifyGlobalReference( + const GlobalValue *GV) const { + return classifyGlobalReference(GV, false); +} + +unsigned char PPCSubtarget::classifyGlobalReference( + const GlobalValue *GV, bool forcePIC) const { + // If PIC is not required, use a direct reference. + if (!isPIC() && !forcePIC) + return PPCII::MO_NO_FLAG; + + // Large code model always uses the TOC even for local symbols. + if (TM.getCodeModel() == CodeModel::Large) + return PPCII::MO_PIC_FLAG | PPCII::MO_NLP_FLAG; + + unsigned char flags = PPCII::MO_PIC_FLAG; + + // Only if the relocation mode is PIC do we have to worry about + // interposition. In all other cases we can use a slightly looser standard to + // decide how to access the symbol. + if (TM.getRelocationModel() == Reloc::PIC_) { + if (!GV->hasLocalLinkage()) { + if (GV->hasHiddenVisibility()) { + flags |= PPCII::MO_NLP_HIDDEN_FLAG; + return flags; + } + flags |= PPCII::MO_NLP_FLAG; + return flags; + } + return flags; + } + + if (GV->isStrongDefinitionForLinker()) + return flags; + return flags | PPCII::MO_NLP_FLAG; +} + bool PPCSubtarget::isELFv2ABI() const { return TM.isELFv2ABI(); } bool PPCSubtarget::isPPC64() const { return TM.isPPC64(); } +bool PPCSubtarget::isPIC() const { + if (TM.getRelocationModel() == Reloc::PIC_) + return true; + if (TM.getCodeModel() == CodeModel::Large) + return true; + if (isSVR4ABI() && isPPC64() && !isELFv2ABI()) + return true; + return false; +} Index: test/CodeGen/PowerPC/fast-isel-load-store.ll =================================================================== --- test/CodeGen/PowerPC/fast-isel-load-store.ll +++ test/CodeGen/PowerPC/fast-isel-load-store.ll @@ -195,6 +195,7 @@ ; ELF64: t17 %1 = add nsw i64 %v, 1 store i64 %1, i64* getelementptr inbounds ([8192 x i64], [8192 x i64]* @i, i32 0, i64 5000), align 8 +;; The common linkage requires a TOC indirection, hence the ld ; ELF64: addis ; ELF64: ld ; ELF64: addi