diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp --- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -646,15 +646,20 @@ Index.addGlobalValueSummary(V, std::move(GVarSummary)); } -static void -computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A, - DenseSet &CantBePromoted) { +static void computeAliasSummary(ModuleSummaryIndex &Index, const GlobalAlias &A, + DenseSet &CantBePromoted) { + auto *Aliasee = A.getAliaseeObject(); + + // Skip summary for indirect function aliases as summary for aliasee will not + // be emitted. + if (isa(Aliasee)) + return; + bool NonRenamableLocal = isNonRenamableLocal(A); GlobalValueSummary::GVFlags Flags( A.getLinkage(), A.getVisibility(), NonRenamableLocal, /* Live = */ false, A.isDSOLocal(), A.canBeOmittedFromSymbolTable()); auto AS = std::make_unique(Flags); - auto *Aliasee = A.getAliaseeObject(); auto AliaseeVI = Index.getValueInfo(Aliasee->getGUID()); assert(AliaseeVI && "Alias expects aliasee summary to be available"); assert(AliaseeVI.getSummaryList().size() == 1 && @@ -811,6 +816,12 @@ for (const GlobalAlias &A : M.aliases()) computeAliasSummary(Index, A, CantBePromoted); + // Iterate through ifuncs, set their resolvers all alive. + for (const GlobalIFunc &I : M.ifuncs()) { + const GlobalValue &GV = *dyn_cast(I.getResolver()); + Index.getGlobalValueSummary(GV)->setLive(true); + } + for (auto *V : LocalsUsed) { auto *Summary = Index.getGlobalValueSummary(*V); assert(Summary && "Missing summary for global value"); diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -4103,8 +4103,9 @@ for (const GlobalAlias &A : M.aliases()) { auto *Aliasee = A.getAliaseeObject(); - if (!Aliasee->hasName()) - // Nameless function don't have an entry in the summary, skip it. + // IFunc function and Nameless function don't have an entry in the + // summary, skip it. + if (!Aliasee->hasName() || isa(Aliasee)) continue; auto AliasId = VE.getValueID(&A); auto AliaseeId = VE.getValueID(Aliasee); diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -1169,10 +1169,13 @@ // recorded in the index using the original name. // FIXME: This may not be needed once PR27866 is fixed. GS = DefinedGlobals.find(GlobalValue::getGUID(OrigName)); - assert(GS != DefinedGlobals.end()); } } - return !GlobalValue::isLocalLinkage(GS->second->linkage()); + // It maybe the case that GV is on a chain of an ifunc, its alias and + // subsequent aliases. In this case, the summary for the value is not + // available. + return GS == DefinedGlobals.end() || + !GlobalValue::isLocalLinkage(GS->second->linkage()); }; // FIXME: See if we can just internalize directly here via linkage changes diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp --- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp +++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp @@ -59,7 +59,13 @@ // in this module. auto Summary = ImportIndex.findSummaryInModule( VI, SGV->getParent()->getModuleIdentifier()); - assert(Summary && "Missing summary for global value when exporting"); + + // It maybe the case that SGV is on a chain of an ifunc, its alias and + // subsequent aliases. In this case, the summary for the value is not + // available. + if (!Summary) + return false; + auto Linkage = Summary->linkage(); if (!GlobalValue::isLocalLinkage(Linkage)) { assert(!isNonRenamableLocal(*SGV) && diff --git a/llvm/test/LTO/Resolution/X86/alias-indirect-function-lto.ll b/llvm/test/LTO/Resolution/X86/alias-indirect-function-lto.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/Resolution/X86/alias-indirect-function-lto.ll @@ -0,0 +1,31 @@ +; RUN: opt -module-summary -o %t.bc %s +; RUN: llvm-lto2 run %t.bc -r %t.bc,foo,px -r %t.bc,bar,px -r %t.bc,baz,px -r %t.bc,qux,px -r %t.bc,grault,px -o %t2 +; RUN: llvm-nm %t2.1 | FileCheck %s +; CHECK: i bar +; CHECK: i baz +; CHECK: i foo +; CHECK: t foo_resolver +; CHECK: i grault +; CHECK: i quuz +; CHECK: i qux + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@foo = ifunc i32 (i32), i32 (i32)* ()* @foo_resolver + +define internal i32 (i32)* @foo_resolver() { +entry: + ret i32 (i32)* null +} + +@bar = alias i32 (i32), i32 (i32)* @foo +@baz = weak alias i32 (i32), i32 (i32)* @foo +@qux = alias i32 (i32), i32 (i32)* @bar + +@quux = internal alias i32 (i32)* (), i32 (i32)* ()* @foo_resolver +@quuz = internal ifunc i32 (i32), i32 (i32)* ()* @quux +@corge = internal alias i32 (i32), i32 (i32)* @quuz +@grault = alias i32 (i32), i32 (i32)* @corge + +; no crash