Index: include/llvm/IR/Module.h =================================================================== --- include/llvm/IR/Module.h +++ include/llvm/IR/Module.h @@ -35,6 +35,7 @@ class LLVMContext; class RandomNumberGenerator; class StructType; +template class SmallPtrSetImpl; template<> struct ilist_traits : public ilist_default_traits { @@ -748,6 +749,12 @@ /// @} }; +/// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect +/// the initializer elements of that global in Set and return the global itself. +GlobalVariable *collectUsedGlobalVariables(const Module &M, + SmallPtrSetImpl &Set, + bool CompilerUsed); + /// An raw_ostream inserter for modules. inline raw_ostream &operator<<(raw_ostream &O, const Module &M) { M.print(O, nullptr); Index: include/llvm/Transforms/Utils/ModuleUtils.h =================================================================== --- include/llvm/Transforms/Utils/ModuleUtils.h +++ include/llvm/Transforms/Utils/ModuleUtils.h @@ -28,7 +28,6 @@ class StringRef; class Value; class Type; -template class SmallPtrSetImpl; /// Append F to the list of global ctors of module M with the given Priority. /// This wraps the function in the appropriate structure and stores it along @@ -41,12 +40,6 @@ void appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data = nullptr); -/// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect -/// the initializer elements of that global in Set and return the global itself. -GlobalVariable *collectUsedGlobalVariables(Module &M, - SmallPtrSetImpl &Set, - bool CompilerUsed); - // Validate the result of Module::getOrInsertFunction called for an interface // function of given sanitizer. If the instrumented module defines a function // with the same name, their prototypes must match, otherwise Index: lib/Analysis/ModuleSummaryAnalysis.cpp =================================================================== --- lib/Analysis/ModuleSummaryAnalysis.cpp +++ lib/Analysis/ModuleSummaryAnalysis.cpp @@ -120,6 +120,18 @@ const Module *M, std::function Ftor) : Index(llvm::make_unique()), M(M) { + // We cannot currently promote or rename anything that is in llvm.used, + // since any such value may have a use that won't see the new name. + // Specifically, any uses within inline assembly are not visible to the + // compiler. Prevent importing of any modules containing these uses by + // suppressing generation of the index. + SmallPtrSet Used; + collectUsedGlobalVariables(*M, Used, /*CompilerUsed*/ false); + for (GlobalValue *V : Used) { + if (V->hasLocalLinkage()) + return; + } + // Compute summaries for all functions defined in module, and save in the // index. for (auto &F : *M) { Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2887,6 +2887,9 @@ if (M->empty()) return; + if (Index.begin() == Index.end()) + return; + Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3); // Abbrev for FS_PERMODULE. Index: lib/IR/Module.cpp =================================================================== --- lib/IR/Module.cpp +++ lib/IR/Module.cpp @@ -15,6 +15,7 @@ #include "SymbolTableListTraitsImpl.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Constants.h" @@ -516,3 +517,18 @@ Metadata *Module::getProfileSummary() { return getModuleFlag("ProfileSummary"); } + +GlobalVariable *llvm::collectUsedGlobalVariables( + const Module &M, SmallPtrSetImpl &Set, bool CompilerUsed) { + const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used"; + GlobalVariable *GV = M.getGlobalVariable(Name); + if (!GV || !GV->hasInitializer()) + return GV; + + const ConstantArray *Init = cast(GV->getInitializer()); + for (Value *Op : Init->operands()) { + GlobalValue *G = cast(Op->stripPointerCastsNoFollowAliases()); + Set.insert(G); + } + return GV; +} Index: lib/Transforms/IPO/GlobalOpt.cpp =================================================================== --- lib/Transforms/IPO/GlobalOpt.cpp +++ lib/Transforms/IPO/GlobalOpt.cpp @@ -43,7 +43,6 @@ #include "llvm/Transforms/Utils/CtorUtils.h" #include "llvm/Transforms/Utils/Evaluator.h" #include "llvm/Transforms/Utils/GlobalStatus.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" #include #include using namespace llvm; Index: lib/Transforms/IPO/Internalize.cpp =================================================================== --- lib/Transforms/IPO/Internalize.cpp +++ lib/Transforms/IPO/Internalize.cpp @@ -30,7 +30,6 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/GlobalStatus.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" #include #include using namespace llvm; Index: lib/Transforms/Utils/FunctionImportUtils.cpp =================================================================== --- lib/Transforms/Utils/FunctionImportUtils.cpp +++ lib/Transforms/Utils/FunctionImportUtils.cpp @@ -206,6 +206,24 @@ } void FunctionImportGlobalProcessing::processGlobalsForThinLTO() { + // We cannot currently promote or rename anything that is in llvm.used, + // since any such value may have a use that won't see the new name. + // Specifically, any uses within inline assembly are not visible to the + // compiler. Prevent changing any such values on the exporting side, + // since we would already have guarded against an import from this module by + // suppressing its index generation. + SmallPtrSet Used; + collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false); + for (GlobalValue *V : Used) { + if (!V->hasLocalLinkage()) + continue; + // We would have blocked importing from this module by suppressing index + // generation. + assert(!isPerformingImport() && + "Should have blocked importing from module with local used"); + return; + } + for (GlobalVariable &GV : M.globals()) processGlobalForThinLTO(GV); for (Function &SF : M) Index: lib/Transforms/Utils/ModuleUtils.cpp =================================================================== --- lib/Transforms/Utils/ModuleUtils.cpp +++ lib/Transforms/Utils/ModuleUtils.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/ModuleUtils.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" @@ -90,22 +89,6 @@ appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data); } -GlobalVariable * -llvm::collectUsedGlobalVariables(Module &M, SmallPtrSetImpl &Set, - bool CompilerUsed) { - const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used"; - GlobalVariable *GV = M.getGlobalVariable(Name); - if (!GV || !GV->hasInitializer()) - return GV; - - const ConstantArray *Init = cast(GV->getInitializer()); - for (Value *Op : Init->operands()) { - GlobalValue *G = cast(Op->stripPointerCastsNoFollowAliases()); - Set.insert(G); - } - return GV; -} - Function *llvm::checkSanitizerInterfaceFunction(Constant *FuncOrBitcast) { if (isa(FuncOrBitcast)) return cast(FuncOrBitcast); Index: test/Transforms/FunctionImport/Inputs/inlineasm.ll =================================================================== --- /dev/null +++ test/Transforms/FunctionImport/Inputs/inlineasm.ll @@ -0,0 +1,11 @@ +@myvar = internal constant i8 1, align 1 +@llvm.used = appending global [1 x i8*] [i8* @myvar], section "llvm.metadata" + +define void @foo(i64* %v) #0 { +entry: + %v.addr = alloca i64*, align 8 + store i64* %v, i64** %v.addr, align 8 + %0 = load i64*, i64** %v.addr, align 8 + call void asm sideeffect "movzbl myvar(%rip), %eax\0A\09movq %rax, $0\0A\09", "=*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i64* %0) #1 + ret void +} Index: test/Transforms/FunctionImport/inlineasm.ll =================================================================== --- /dev/null +++ test/Transforms/FunctionImport/inlineasm.ll @@ -0,0 +1,19 @@ +; Do setup work for all below tests: generate bitcode and combined index +; RUN: llvm-as -module-summary %s -o %t.bc +; RUN: llvm-as -module-summary %p/Inputs/inlineasm.ll -o %t2.bc +; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc + +; Attempt the import now, ensure below that file containing inline assembly +; is not imported from. Otherwise we would need to promote its local variable +; used in the inline assembly, which would not see the rename. +; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=CHECK + +define i32 @main() #0 { +entry: + %f = alloca i64, align 8 + call void @foo(i64* %f) + ret i32 0 +} + +; CHECK: declare void @foo(i64*) +declare void @foo(i64*) #1 Index: tools/gold/gold-plugin.cpp =================================================================== --- tools/gold/gold-plugin.cpp +++ tools/gold/gold-plugin.cpp @@ -45,7 +45,6 @@ #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" #include "llvm/Transforms/Utils/GlobalStatus.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" #include "llvm/Transforms/Utils/ValueMapper.h" #include #include