diff options
Diffstat (limited to 'llvm/lib/Analysis/ModuleSummaryAnalysis.cpp')
-rw-r--r-- | llvm/lib/Analysis/ModuleSummaryAnalysis.cpp | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp index c3d15af..c863936 100644 --- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -95,9 +95,12 @@ extern cl::opt<unsigned> MaxNumVTableAnnotations; // global vars at all. When importing function we aren't interested if any // instruction in it takes an address of any basic block, because instruction // can only take an address of basic block located in the same function. +// Set `RefLocalLinkageIFunc` to true if the analyzed value references a +// local-linkage ifunc. static bool findRefEdges(ModuleSummaryIndex &Index, const User *CurUser, SetVector<ValueInfo, std::vector<ValueInfo>> &RefEdges, - SmallPtrSet<const User *, 8> &Visited) { + SmallPtrSet<const User *, 8> &Visited, + bool &RefLocalLinkageIFunc) { bool HasBlockAddress = false; SmallVector<const User *, 32> Worklist; if (Visited.insert(CurUser).second) @@ -119,8 +122,18 @@ static bool findRefEdges(ModuleSummaryIndex &Index, const User *CurUser, // We have a reference to a global value. This should be added to // the reference set unless it is a callee. Callees are handled // specially by WriteFunction and are added to a separate list. - if (!(CB && CB->isCallee(&OI))) + if (!(CB && CB->isCallee(&OI))) { + // If an ifunc has local linkage, do not add it into ref edges, and + // sets `RefLocalLinkageIFunc` to true. The referencer is not eligible + // for import. An ifunc doesn't have summary and ThinLTO cannot + // promote it; importing the referencer may cause linkage errors. + if (auto *GI = dyn_cast_if_present<GlobalIFunc>(GV); + GI && GI->hasLocalLinkage()) { + RefLocalLinkageIFunc = true; + continue; + } RefEdges.insert(Index.getOrInsertValueInfo(GV)); + } continue; } if (Visited.insert(Operand).second) @@ -313,7 +326,8 @@ static void computeFunctionSummary( // Add personality function, prefix data and prologue data to function's ref // list. - findRefEdges(Index, &F, RefEdges, Visited); + bool HasLocalIFuncCallOrRef = false; + findRefEdges(Index, &F, RefEdges, Visited, HasLocalIFuncCallOrRef); std::vector<const Instruction *> NonVolatileLoads; std::vector<const Instruction *> NonVolatileStores; @@ -326,7 +340,6 @@ static void computeFunctionSummary( bool HasInlineAsmMaybeReferencingInternal = false; bool HasIndirBranchToBlockAddress = false; - bool HasIFuncCall = false; bool HasUnknownCall = false; bool MayThrow = false; for (const BasicBlock &BB : F) { @@ -372,11 +385,11 @@ static void computeFunctionSummary( // of calling it we should add GV to RefEdges directly. RefEdges.insert(Index.getOrInsertValueInfo(GV)); else if (auto *U = dyn_cast<User>(Stored)) - findRefEdges(Index, U, RefEdges, Visited); + findRefEdges(Index, U, RefEdges, Visited, HasLocalIFuncCallOrRef); continue; } } - findRefEdges(Index, &I, RefEdges, Visited); + findRefEdges(Index, &I, RefEdges, Visited, HasLocalIFuncCallOrRef); const auto *CB = dyn_cast<CallBase>(&I); if (!CB) { if (I.mayThrow()) @@ -450,7 +463,7 @@ static void computeFunctionSummary( // Non-local ifunc is not cloned and does not have the issue. if (auto *GI = dyn_cast_if_present<GlobalIFunc>(CalledValue)) if (GI->hasLocalLinkage()) - HasIFuncCall = true; + HasLocalIFuncCallOrRef = true; // Skip inline assembly calls. if (CI && CI->isInlineAsm()) continue; @@ -555,7 +568,7 @@ static void computeFunctionSummary( SmallPtrSet<const User *, 8> &Cache) { for (const auto *I : Instrs) { Cache.erase(I); - findRefEdges(Index, I, Edges, Cache); + findRefEdges(Index, I, Edges, Cache, HasLocalIFuncCallOrRef); } }; @@ -631,9 +644,9 @@ static void computeFunctionSummary( #endif bool NonRenamableLocal = isNonRenamableLocal(F); - bool NotEligibleForImport = NonRenamableLocal || - HasInlineAsmMaybeReferencingInternal || - HasIndirBranchToBlockAddress || HasIFuncCall; + bool NotEligibleForImport = + NonRenamableLocal || HasInlineAsmMaybeReferencingInternal || + HasIndirBranchToBlockAddress || HasLocalIFuncCallOrRef; GlobalValueSummary::GVFlags Flags( F.getLinkage(), F.getVisibility(), NotEligibleForImport, /* Live = */ false, F.isDSOLocal(), F.canBeOmittedFromSymbolTable(), @@ -787,7 +800,10 @@ static void computeVariableSummary(ModuleSummaryIndex &Index, SmallVectorImpl<MDNode *> &Types) { SetVector<ValueInfo, std::vector<ValueInfo>> RefEdges; SmallPtrSet<const User *, 8> Visited; - bool HasBlockAddress = findRefEdges(Index, &V, RefEdges, Visited); + bool RefLocalIFunc = false; + bool HasBlockAddress = + findRefEdges(Index, &V, RefEdges, Visited, RefLocalIFunc); + const bool NotEligibleForImport = (HasBlockAddress || RefLocalIFunc); bool NonRenamableLocal = isNonRenamableLocal(V); GlobalValueSummary::GVFlags Flags( V.getLinkage(), V.getVisibility(), NonRenamableLocal, @@ -821,7 +837,7 @@ static void computeVariableSummary(ModuleSummaryIndex &Index, RefEdges.takeVector()); if (NonRenamableLocal) CantBePromoted.insert(V.getGUID()); - if (HasBlockAddress) + if (NotEligibleForImport) GVarSummary->setNotEligibleToImport(); if (!VTableFuncs.empty()) GVarSummary->setVTableFuncs(VTableFuncs); |