Index: llvm/lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- llvm/lib/Transforms/IPO/FunctionImport.cpp +++ llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -261,8 +261,8 @@ namespace { -using EdgeInfo = std::tuple; +using EdgeInfo = + std::tuple; } // anonymous namespace @@ -282,10 +282,12 @@ } static void computeImportForReferencedGlobals( - const FunctionSummary &Summary, const ModuleSummaryIndex &Index, + const GlobalValueSummary &Summary, const ModuleSummaryIndex &Index, const GVSummaryMapTy &DefinedGVSummaries, + SmallVectorImpl &Worklist, FunctionImporter::ImportMapTy &ImportList, StringMap *ExportLists) { + bool IsGlobalVar = isa(&Summary); for (auto &VI : Summary.refs()) { if (DefinedGVSummaries.count(VI.getGUID())) { LLVM_DEBUG( @@ -325,10 +327,13 @@ // we convert such variables initializers to "zeroinitializer". // See processGlobalForThinLTO. if (!Index.isWriteOnly(cast(RefSummary.get()))) - for (const auto &VI : RefSummary->refs()) - for (const auto &RefFn : VI.getSummaryList()) - MarkExported(VI, RefFn.get()); + Worklist.emplace_back(RefSummary.get(), 0); break; + } else if (IsGlobalVar) { + // We're examining references of global variable, which was + // previously marked for importing by this function. We need + // to promote all its references to avoid link errors. + MarkExported(VI, RefSummary.get()); } } } @@ -367,7 +372,7 @@ StringMap *ExportLists, FunctionImporter::ImportThresholdsTy &ImportThresholds) { computeImportForReferencedGlobals(Summary, Index, DefinedGVSummaries, - ImportList, ExportLists); + Worklist, ImportList, ExportLists); static int ImportCount = 0; for (auto &Edge : Summary.calls()) { ValueInfo VI = Edge.first; @@ -528,7 +533,7 @@ ImportCount++; // Insert the newly imported function to the worklist. - Worklist.emplace_back(ResolvedCalleeSummary, AdjThreshold, VI.getGUID()); + Worklist.emplace_back(ResolvedCalleeSummary, AdjThreshold); } } @@ -569,13 +574,17 @@ // Process the newly imported functions and add callees to the worklist. while (!Worklist.empty()) { - auto FuncInfo = Worklist.pop_back_val(); - auto *Summary = std::get<0>(FuncInfo); - auto Threshold = std::get<1>(FuncInfo); - - computeImportForFunction(*Summary, Index, Threshold, DefinedGVSummaries, - Worklist, ImportList, ExportLists, - ImportThresholds); + auto GVInfo = Worklist.pop_back_val(); + auto *Summary = std::get<0>(GVInfo); + auto Threshold = std::get<1>(GVInfo); + + if (auto *FS = dyn_cast(Summary)) + computeImportForFunction(*FS, Index, Threshold, DefinedGVSummaries, + Worklist, ImportList, ExportLists, + ImportThresholds); + else + computeImportForReferencedGlobals(*Summary, Index, DefinedGVSummaries, + Worklist, ImportList, ExportLists); } // Print stats about functions considered but rejected for importing Index: llvm/test/ThinLTO/X86/import-constant.ll =================================================================== --- llvm/test/ThinLTO/X86/import-constant.ll +++ llvm/test/ThinLTO/X86/import-constant.ll @@ -19,7 +19,7 @@ ; @outer is a write-only variable, so it's been converted to zeroinitializer. ; IMPORT: @outer = internal local_unnamed_addr global %struct.Q zeroinitializer ; IMPORT-NEXT: @_ZL3Obj.llvm.{{.*}} = available_externally hidden constant %struct.S { i32 4, i32 8, i32* @val } -; IMPORT-NEXT: @val = external dso_local global i32 +; IMPORT-NEXT: @val = available_externally dso_local global i32 42 ; OPT: @outer = internal unnamed_addr global %struct.Q zeroinitializer