diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -1177,6 +1177,7 @@ CCAssignFn *ccAssignFnForCall(CallingConv::ID CC, bool Return, bool IsVarArg) const; + bool callsShareTOCBase(const Function *Caller, const GlobalValue *GV) const; private: struct ReuseLoadInfo { SDValue Ptr; diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -4658,85 +4658,6 @@ static bool isFunctionGlobalAddress(SDValue Callee); -static bool callsShareTOCBase(const Function *Caller, SDValue Callee, - const TargetMachine &TM) { - // It does not make sense to call callsShareTOCBase() with a caller that - // is PC Relative since PC Relative callers do not have a TOC. -#ifndef NDEBUG - const PPCSubtarget *STICaller = &TM.getSubtarget(*Caller); - assert(!STICaller->isUsingPCRelativeCalls() && - "PC Relative callers do not have a TOC and cannot share a TOC Base"); -#endif - - // Callee is either a GlobalAddress or an ExternalSymbol. ExternalSymbols - // don't have enough information to determine if the caller and callee share - // the same TOC base, so we have to pessimistically assume they don't for - // correctness. - GlobalAddressSDNode *G = dyn_cast(Callee); - if (!G) - return false; - - const GlobalValue *GV = G->getGlobal(); - - // If the callee is preemptable, then the static linker will use a plt-stub - // which saves the toc to the stack, and needs a nop after the call - // instruction to convert to a toc-restore. - if (!TM.shouldAssumeDSOLocal(*Caller->getParent(), GV)) - return false; - - // Functions with PC Relative enabled may clobber the TOC in the same DSO. - // We may need a TOC restore in the situation where the caller requires a - // valid TOC but the callee is PC Relative and does not. - const Function *F = dyn_cast(GV); - const GlobalAlias *Alias = dyn_cast(GV); - - // If we have an Alias we can try to get the function from there. - if (Alias) { - const GlobalObject *GlobalObj = Alias->getAliaseeObject(); - F = dyn_cast(GlobalObj); - } - - // If we still have no valid function pointer we do not have enough - // information to determine if the callee uses PC Relative calls so we must - // assume that it does. - if (!F) - return false; - - // If the callee uses PC Relative we cannot guarantee that the callee won't - // clobber the TOC of the caller and so we must assume that the two - // functions do not share a TOC base. - const PPCSubtarget *STICallee = &TM.getSubtarget(*F); - if (STICallee->isUsingPCRelativeCalls()) - return false; - - // If the GV is not a strong definition then we need to assume it can be - // replaced by another function at link time. The function that replaces - // it may not share the same TOC as the caller since the callee may be - // replaced by a PC Relative version of the same function. - if (!GV->isStrongDefinitionForLinker()) - return false; - - // The medium and large code models are expected to provide a sufficiently - // large TOC to provide all data addressing needs of a module with a - // single TOC. - if (CodeModel::Medium == TM.getCodeModel() || - CodeModel::Large == TM.getCodeModel()) - return true; - - // Any explicitly-specified sections and section prefixes must also match. - // Also, if we're using -ffunction-sections, then each function is always in - // a different section (the same is true for COMDAT functions). - if (TM.getFunctionSections() || GV->hasComdat() || Caller->hasComdat() || - GV->getSection() != Caller->getSection()) - return false; - if (const auto *F = dyn_cast(GV)) { - if (F->getSectionPrefix() != Caller->getSectionPrefix()) - return false; - } - - return true; -} - static bool needStackSlotPassParameters(const PPCSubtarget &Subtarget, const SmallVectorImpl &Outs) { @@ -4880,8 +4801,16 @@ return false; // Check if we share the TOC base. - if (!Subtarget.isUsingPCRelativeCalls() && - !callsShareTOCBase(&Caller, Callee, getTargetMachine())) + // Make sure the callee is GlobalAddress. We don't have enough information for + // ExternalSymbol to determine if the caller and callee share the same TOC + // base. + bool ShareTOCBase = isa(Callee); + bool UsingPCRel = Subtarget.isUsingPCRelativeCalls(); + if (ShareTOCBase && !UsingPCRel) + ShareTOCBase = Subtarget.getTargetLowering()->callsShareTOCBase( + &Caller, cast(Callee)->getGlobal()); + + if (!UsingPCRel && !ShareTOCBase) return false; // TCO allows altering callee ABI, so we don't have to check further. @@ -5240,7 +5169,7 @@ } else if (Subtarget.isUsingPCRelativeCalls()) { assert(Subtarget.is64BitELFABI() && "PC Relative is only on ELF ABI."); RetOpc = PPCISD::CALL_NOTOC; - } else if (Subtarget.isAIXABI() || Subtarget.is64BitELFABI()) + } else if (Subtarget.isAIXABI() || Subtarget.is64BitELFABI()) { // The ABIs that maintain a TOC pointer accross calls need to have a nop // immediately following the call instruction if the caller and callee may // have different TOC bases. At link time if the linker determines the calls @@ -5249,8 +5178,17 @@ // TOC pointer at an ABI designated offset in the linkage area and the // linker will rewrite the nop to be a load of the TOC pointer from the // linkage area into gpr2. - RetOpc = callsShareTOCBase(&Caller, Callee, TM) ? PPCISD::CALL - : PPCISD::CALL_NOP; + // + // Callee is either a GlobalAddress or an ExternalSymbol. ExternalSymbols + // don't have enough information to determine if the caller and callee share + // the same TOC base, so we have to pessimistically assume they don't for + // correctness. + bool ShareTOCBase = isa(Callee); + if (ShareTOCBase) + ShareTOCBase = Subtarget.getTargetLowering()->callsShareTOCBase( + &Caller, cast(Callee)->getGlobal()); + RetOpc = ShareTOCBase ? PPCISD::CALL : PPCISD::CALL_NOP; + } else RetOpc = PPCISD::CALL; if (IsStrictFPCall) { @@ -18171,3 +18109,74 @@ return Builder.CreateOr( Lo, Builder.CreateShl(Hi, ConstantInt::get(ValTy, 64)), "val64"); } + +bool PPCTargetLowering::callsShareTOCBase(const Function *Caller, + const GlobalValue *GV) const { + const TargetMachine &TM = getTargetMachine(); + + // It does not make sense to call callsShareTOCBase() with a caller that + // is PC Relative since PC Relative callers do not have a TOC. +#ifndef NDEBUG + const PPCSubtarget *STICaller = &TM.getSubtarget(*Caller); + assert(!STICaller->isUsingPCRelativeCalls() && + "PC Relative callers do not have a TOC and cannot share a TOC Base"); +#endif + + // If the callee is preemptable, then the static linker will use a plt-stub + // which saves the toc to the stack, and needs a nop after the call + // instruction to convert to a toc-restore. + if (!TM.shouldAssumeDSOLocal(*Caller->getParent(), GV)) + return false; + + // Functions with PC Relative enabled may clobber the TOC in the same DSO. + // We may need a TOC restore in the situation where the caller requires a + // valid TOC but the callee is PC Relative and does not. + const Function *F = dyn_cast(GV); + const GlobalAlias *Alias = dyn_cast(GV); + + // If we have an Alias we can try to get the function from there. + if (Alias) { + const GlobalObject *GlobalObj = Alias->getAliaseeObject(); + F = dyn_cast(GlobalObj); + } + + // If we still have no valid function pointer we do not have enough + // information to determine if the callee uses PC Relative calls so we must + // assume that it does. + if (!F) + return false; + + // If the callee uses PC Relative we cannot guarantee that the callee won't + // clobber the TOC of the caller and so we must assume that the two + // functions do not share a TOC base. + const PPCSubtarget *STICallee = &TM.getSubtarget(*F); + if (STICallee->isUsingPCRelativeCalls()) + return false; + + // If the GV is not a strong definition then we need to assume it can be + // replaced by another function at link time. The function that replaces + // it may not share the same TOC as the caller since the callee may be + // replaced by a PC Relative version of the same function. + if (!GV->isStrongDefinitionForLinker()) + return false; + + // The medium and large code models are expected to provide a sufficiently + // large TOC to provide all data addressing needs of a module with a + // single TOC. + if (CodeModel::Medium == TM.getCodeModel() || + CodeModel::Large == TM.getCodeModel()) + return true; + + // Any explicitly-specified sections and section prefixes must also match. + // Also, if we're using -ffunction-sections, then each function is always in + // a different section (the same is true for COMDAT functions). + if (TM.getFunctionSections() || GV->hasComdat() || Caller->hasComdat() || + GV->getSection() != Caller->getSection()) + return false; + if (const auto *F = dyn_cast(GV)) { + if (F->getSectionPrefix() != Caller->getSectionPrefix()) + return false; + } + + return true; +}