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 @@ -261,8 +261,8 @@ namespace { -using EdgeInfo = std::tuple; +using EdgeInfo = + std::tuple; } // anonymous namespace @@ -282,8 +282,9 @@ } 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) { for (auto &VI : Summary.refs()) { @@ -321,6 +322,11 @@ // which is more efficient than adding them here. if (ExportLists) (*ExportLists)[RefSummary->modulePath()].insert(VI); + + // If variable is not writeonly we attempt to recursively analyze + // its references in order to import referenced constants. + if (!Index.isWriteOnly(cast(RefSummary.get()))) + Worklist.emplace_back(RefSummary.get(), 0); break; } } @@ -360,7 +366,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; @@ -508,7 +514,7 @@ ImportCount++; // Insert the newly imported function to the worklist. - Worklist.emplace_back(ResolvedCalleeSummary, AdjThreshold, VI.getGUID()); + Worklist.emplace_back(ResolvedCalleeSummary, AdjThreshold); } } @@ -549,13 +555,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 diff --git a/llvm/test/ThinLTO/X86/import-constant.ll b/llvm/test/ThinLTO/X86/import-constant.ll --- a/llvm/test/ThinLTO/X86/import-constant.ll +++ b/llvm/test/ThinLTO/X86/import-constant.ll @@ -14,13 +14,23 @@ ; RUN: llvm-dis %t-out.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT ; RUN: llvm-dis %t-out.1.4.opt.bc -o - | FileCheck %s --check-prefix=OPT +; Check when importing references is prohibited +; RUN: llvm-lto2 run -save-temps %t1.bc %t2.bc -o %t-out-norefs \ +; RUN: -import-constants-with-refs=false \ +; RUN: -r=%t1.bc,main,plx \ +; RUN: -r=%t1.bc,_Z6getObjv,l \ +; RUN: -r=%t2.bc,_Z6getObjv,pl \ +; RUN: -r=%t2.bc,val,pl \ +; RUN: -r=%t2.bc,outer,pl +; RUN: llvm-dis %t-out-norefs.1.3.import.bc -o - | FileCheck %s --check-prefix=NOREFS + ; Check that variable has been promoted in the source module ; PROMOTE: @_ZL3Obj.llvm.{{.*}} = hidden constant %struct.S { i32 4, i32 8, i32* @val } ; @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: @_ZL3Obj.llvm.{{.*}} = available_externally hidden constant %struct.S { i32 4, i32 8, i32* @val } +; IMPORT-NEXT: @val = available_externally global i32 42 ; OPT: @outer = internal unnamed_addr global %struct.Q zeroinitializer @@ -29,6 +39,9 @@ ; OPT-NEXT: store %struct.S* null, %struct.S** getelementptr inbounds (%struct.Q, %struct.Q* @outer, i64 0, i32 0) ; OPT-NEXT: ret i32 12 +; NOREFS: @outer = internal local_unnamed_addr global %struct.Q zeroinitializer +; NOREFS-NEXT: @_ZL3Obj.llvm.{{.*}} = external hidden constant %struct.S + 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"