Index: include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- include/llvm/IR/ModuleSummaryIndex.h +++ include/llvm/IR/ModuleSummaryIndex.h @@ -101,17 +101,26 @@ /// possibly referenced from inline assembly, etc). unsigned NoRename : 1; + /// Indicate if value may reference a NoRename value (e.g. via inline + /// assembly that is opaque). Use a flag rather than bloating the + /// summary with references to every possible NoRename value in the + /// llvm.used set. + unsigned MayReferenceNoRename : 1; + /// Indicate if the function is not viable to inline. unsigned IsNotViableToInline : 1; /// Convenience Constructors explicit GVFlags(GlobalValue::LinkageTypes Linkage, bool NoRename, + bool MayReferenceNoRename, bool IsNotViableToInline) : Linkage(Linkage), NoRename(NoRename), + MayReferenceNoRename(MayReferenceNoRename), IsNotViableToInline(IsNotViableToInline) {} GVFlags(const GlobalValue &GV) - : Linkage(GV.getLinkage()), NoRename(GV.hasSection()) { + : Linkage(GV.getLinkage()), NoRename(GV.hasSection()), + MayReferenceNoRename(false) { IsNotViableToInline = false; if (const auto *F = dyn_cast(&GV)) // Inliner doesn't handle variadic functions. @@ -198,6 +207,14 @@ /// possibly referenced from inline assembly, etc). void setNoRename() { Flags.NoRename = true; } + /// Return true if this global value possibly references another value + /// that can't be renamed. + bool mayReferenceNoRename() const { return Flags.MayReferenceNoRename; } + + /// Flag that this global value possibly references another value that + /// can't be renamed. + void setMayReferenceNoRename() { Flags.MayReferenceNoRename = true; } + /// Record a reference from this global value to the global value identified /// by \p RefGUID. void addRefEdge(GlobalValue::GUID RefGUID) { RefEdgeList.push_back(RefGUID); } Index: lib/Analysis/ModuleSummaryAnalysis.cpp =================================================================== --- lib/Analysis/ModuleSummaryAnalysis.cpp +++ lib/Analysis/ModuleSummaryAnalysis.cpp @@ -78,7 +78,7 @@ static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M, const Function &F, BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, - SmallPtrSetImpl &LocalsUsed) { + bool HasLocalsInUsed) { // Summary not currently supported for anonymous functions, they should // have been named. assert(F.hasName()); @@ -90,8 +90,8 @@ DenseMap IndirectCallEdges; DenseSet RefEdges; ICallPromotionAnalysis ICallAnalysis; - bool HasLocalsInUsed = !LocalsUsed.empty(); + bool MayReferenceNoRename = false; SmallPtrSet Visited; for (const BasicBlock &BB : F) for (const Instruction &I : BB) { @@ -105,11 +105,11 @@ const auto *CI = dyn_cast(&I); // Since we don't know exactly which local values are referenced in inline - // assembly, conservatively reference all of them from this function, to - // ensure we don't export a reference (which would require renaming and - // promotion). + // assembly, conservatively mark the function as possibly referencing + // a NoRename value to ensure we don't export a reference (which would + // require renaming and promotion of the referenced value). if (HasLocalsInUsed && CI && CI->isInlineAsm()) - RefEdges.insert(LocalsUsed.begin(), LocalsUsed.end()); + MayReferenceNoRename = true; auto *CalledValue = CS.getCalledValue(); auto *CalledFunction = CS.getCalledFunction(); @@ -162,6 +162,8 @@ FuncSummary->addCallGraphEdges(CallGraphEdges); FuncSummary->addCallGraphEdges(IndirectCallEdges); FuncSummary->addRefEdges(RefEdges); + if (MayReferenceNoRename) + FuncSummary->setMayReferenceNoRename(); Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary)); } @@ -222,7 +224,7 @@ BFI = BFIPtr.get(); } - computeFunctionSummary(Index, M, F, BFI, PSI, LocalsUsed); + computeFunctionSummary(Index, M, F, BFI, PSI, !LocalsUsed.empty()); } // Compute summaries for all variables defined in module, and save in the Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -796,7 +796,9 @@ RawFlags = RawFlags >> 4; bool NoRename = RawFlags & 0x1; bool IsNotViableToInline = RawFlags & 0x2; - return GlobalValueSummary::GVFlags(Linkage, NoRename, IsNotViableToInline); + bool MayReferenceNoRename = RawFlags & 0x4; + return GlobalValueSummary::GVFlags(Linkage, NoRename, MayReferenceNoRename, + IsNotViableToInline); } static GlobalValue::VisibilityTypes getDecodedVisibility(unsigned Val) { Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -992,6 +992,7 @@ RawFlags |= Flags.NoRename; // bool RawFlags |= (Flags.IsNotViableToInline << 1); + RawFlags |= (Flags.MayReferenceNoRename << 2); // Linkage don't need to be remapped at that time for the summary. Any future // change to the getEncodedLinkage() function will need to be taken into // account here as well. Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -153,7 +153,11 @@ // Check references (and potential calls) in the same module. If the current // value references a global that can't be externally referenced it is not - // eligible for import. + // eligible for import. First check the flag set when we have possible + // opaque references (e.g. inline asm calls), then check the call and + // reference sets. + if (Summary.mayReferenceNoRename()) + return false; bool AllRefsCanBeExternallyReferenced = llvm::all_of(Summary.refs(), [&](const ValueInfo &VI) { return canBeExternallyReferenced(Index, VI.getGUID());