Index: lib/Analysis/ModuleSummaryAnalysis.cpp =================================================================== --- lib/Analysis/ModuleSummaryAnalysis.cpp +++ lib/Analysis/ModuleSummaryAnalysis.cpp @@ -85,6 +85,17 @@ return GV.hasSection() && GV.hasLocalLinkage(); } +/// ELF linkers generate __start_ and __stop_ symbols +/// when there is a value in a section where the name is a valid +/// C identifier. If dead stripping determines that the values declared +/// in section are dead, and we then internalize (and delete) +/// such a symbol, programs that reference the corresponding start and end +/// section symbols will get undefined reference linking errors. +/// We prevent internalization in the backends, but here we mark them as +/// as live roots so that any values reached by these values are not +/// detected as dead and internalized. +static bool isLive(const GlobalValue &GV) { return GV.hasSection(); }; + /// Determine whether this call has all constant integer arguments (excluding /// "this") and summarize it to VCalls or ConstVCalls as appropriate. static void addVCallToSet(DevirtCallSite Call, GlobalValue::GUID Guid, @@ -275,7 +286,7 @@ // FIXME: refactor this to use the same code that inliner is using. F.isVarArg(); GlobalValueSummary::GVFlags Flags(F.getLinkage(), NotEligibleForImport, - /* Live = */ false); + /* Live = */ isLive(F)); auto FuncSummary = llvm::make_unique( Flags, NumInsts, RefEdges.takeVector(), CallGraphEdges.takeVector(), TypeTests.takeVector(), TypeTestAssumeVCalls.takeVector(), @@ -295,7 +306,7 @@ findRefEdges(Index, &V, RefEdges, Visited); bool NonRenamableLocal = isNonRenamableLocal(V); GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal, - /* Live = */ false); + /* Live = */ isLive(V)); auto GVarSummary = llvm::make_unique(Flags, RefEdges.takeVector()); if (NonRenamableLocal) @@ -308,7 +319,7 @@ DenseSet &CantBePromoted) { bool NonRenamableLocal = isNonRenamableLocal(A); GlobalValueSummary::GVFlags Flags(A.getLinkage(), NonRenamableLocal, - /* Live = */ false); + /* Live = */ isLive(A)); auto AS = llvm::make_unique(Flags, ArrayRef{}); auto *Aliasee = A.getBaseObject(); auto *AliaseeSummary = Index.getGlobalValueSummary(*Aliasee); Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -617,6 +617,15 @@ if (AsmUndefinedRefs.count(GV.getName())) return true; + // ELF linkers generate __start_ and __stop_ symbols + // when there is a value in a section where the name is a valid + // C identifier. If dead stripping determines that the values declared + // in section are dead, and we then internalize (and delete) + // such a symbol, programs that reference the corresponding start and end + // section symbols will get undefined reference linking errors. + if (GV.hasSection()) + return true; + // Lookup the linkage recorded in the summaries during global analysis. auto GS = DefinedGlobals.find(GV.getGUID()); if (GS == DefinedGlobals.end()) { Index: test/Bitcode/thinlto-summary-section.ll =================================================================== --- test/Bitcode/thinlto-summary-section.ll +++ test/Bitcode/thinlto-summary-section.ll @@ -4,10 +4,11 @@ ; RUN: llvm-lto -thinlto -o %t2 %t.o ; RUN: llvm-bcanalyzer -dump %t2.thinlto.bc | FileCheck %s --check-prefix=COMBINED -; Flags should be 0x17 (23) for local linkage (0x3) and not being importable -; (0x10) due to local linkage plus having a section. -; CHECK: