Index: include/llvm/LTO/LTOBackend.h =================================================================== --- include/llvm/LTO/LTOBackend.h +++ include/llvm/LTO/LTOBackend.h @@ -46,6 +46,10 @@ const FunctionImporter::ImportMapTy &ImportList, const GVSummaryMapTy &DefinedGlobals, MapVector &ModuleMap); + +/// Collect the list of undefined symbols used in asm in the Module and update +/// llvm.compiler.used to prevent optimization from dropping these from the IR. +Error handleAsmUndefinedRefsInMod(Config &C, Module &Mod); } } Index: include/llvm/LTO/legacy/LTOCodeGenerator.h =================================================================== --- include/llvm/LTO/legacy/LTOCodeGenerator.h +++ include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -79,7 +79,6 @@ /// Resets \a HasVerifiedInput. void setModule(std::unique_ptr M); - void setAsmUndefinedRefs(struct LTOModule *); void setTargetOptions(const TargetOptions &Options); void setDebugInfo(lto_debug_model); void setCodePICModel(Optional Model) { RelocModel = Model; } @@ -218,7 +217,6 @@ bool HasVerifiedInput = false; Optional RelocModel; StringSet<> MustPreserveSymbols; - StringSet<> AsmUndefinedRefs; StringMap ExternalSymbols; std::vector CodegenOptions; std::string FeatureStr; Index: include/llvm/LTO/legacy/LTOModule.h =================================================================== --- include/llvm/LTO/legacy/LTOModule.h +++ include/llvm/LTO/legacy/LTOModule.h @@ -154,8 +154,6 @@ StringRef getLinkerOpts() { return LinkerOpts; } - const std::vector &getAsmUndefinedRefs() { return _asm_undefines; } - private: /// Parse metadata from the module // FIXME: it only parses "Linker Options" metadata at the moment @@ -165,6 +163,10 @@ /// either the defined or undefined lists. void parseSymbols(); + /// Update the llvm.compiler_used globals to force preserving libcalls and + /// symbols referenced from asm. + void updateCompilerUsed(); + /// Add a symbol which isn't defined just yet to a list to be resolved later. void addPotentialUndefinedSymbol(ModuleSymbolTable::Symbol Sym, bool isFunc); Index: lib/LTO/LTO.cpp =================================================================== --- lib/LTO/LTO.cpp +++ lib/LTO/LTO.cpp @@ -468,6 +468,11 @@ ModuleSymbolTable SymTab; SymTab.addModule(&M); + // Update the llvm.compiler.used with symbols referenced from module + // level asm so that we keep the necessary symbols when merging into + // the combined module. + if (Error Err = handleAsmUndefinedRefsInMod(Conf, M)) + return Err; SmallPtrSet Used; collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false); Index: lib/LTO/LTOBackend.cpp =================================================================== --- lib/LTO/LTOBackend.cpp +++ lib/LTO/LTOBackend.cpp @@ -362,6 +362,18 @@ updateCompilerUsed(Mod, TM, AsmUndefinedRefs); } +Error lto::handleAsmUndefinedRefsInMod(Config &C, Module &Mod) { + Expected TOrErr = initAndLookupTarget(C, Mod); + if (!TOrErr) + return TOrErr.takeError(); + + std::unique_ptr TM = + createTargetMachine(C, Mod.getTargetTriple(), *TOrErr); + + handleAsmUndefinedRefs(Mod, *TM); + return Error::success(); +} + Error lto::backend(Config &C, AddStreamFn AddStream, unsigned ParallelCodeGenParallelismLevel, std::unique_ptr Mod, @@ -373,8 +385,6 @@ std::unique_ptr TM = createTargetMachine(C, Mod->getTargetTriple(), *TOrErr); - handleAsmUndefinedRefs(*Mod, *TM); - // Setup optimization remarks. auto DiagFileOrErr = lto::setupOptimizationRemarks( Mod->getContext(), C.RemarksFilename, C.RemarksWithHotness); Index: lib/LTO/LTOCodeGenerator.cpp =================================================================== --- lib/LTO/LTOCodeGenerator.cpp +++ lib/LTO/LTOCodeGenerator.cpp @@ -37,7 +37,6 @@ #include "llvm/InitializePasses.h" #include "llvm/LTO/LTO.h" #include "llvm/LTO/legacy/LTOModule.h" -#include "llvm/LTO/legacy/UpdateCompilerUsed.h" #include "llvm/Linker/Linker.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -143,18 +142,11 @@ initializeCFGSimplifyPassPass(R); } -void LTOCodeGenerator::setAsmUndefinedRefs(LTOModule *Mod) { - const std::vector &undefs = Mod->getAsmUndefinedRefs(); - for (int i = 0, e = undefs.size(); i != e; ++i) - AsmUndefinedRefs[undefs[i]] = 1; -} - bool LTOCodeGenerator::addModule(LTOModule *Mod) { assert(&Mod->getModule().getContext() == &Context && "Expected module in same context"); bool ret = TheLinker->linkInModule(Mod->takeModule()); - setAsmUndefinedRefs(Mod); // We've just changed the input, so let's make sure we verify it. HasVerifiedInput = false; @@ -166,11 +158,8 @@ assert(&Mod->getModule().getContext() == &Context && "Expected module in same context"); - AsmUndefinedRefs.clear(); - MergedModule = Mod->takeModule(); TheLinker = make_unique(*MergedModule); - setAsmUndefinedRefs(&*Mod); // We've just changed the input, so let's make sure we verify it. HasVerifiedInput = false; @@ -450,10 +439,6 @@ RecordLinkage(GV); } - // Update the llvm.compiler_used globals to force preserving libcalls and - // symbols referenced from asm - updateCompilerUsed(*MergedModule, *TargetMach, AsmUndefinedRefs); - internalizeModule(*MergedModule, mustPreserveGV); ScopeRestrictionsDone = true; Index: lib/LTO/LTOModule.cpp =================================================================== --- lib/LTO/LTOModule.cpp +++ lib/LTO/LTOModule.cpp @@ -22,6 +22,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" +#include "llvm/LTO/legacy/UpdateCompilerUsed.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" @@ -238,6 +239,10 @@ std::unique_ptr Ret(new LTOModule(std::move(M), Buffer, target)); Ret->parseSymbols(); Ret->parseMetadata(); + // Update the llvm.compiler_used globals to force preserving libcalls and + // symbols referenced from asm, to ensure the necessary symbols are + // kept when merging the module. + Ret->updateCompilerUsed(); return std::move(Ret); } @@ -632,6 +637,13 @@ } } +void LTOModule::updateCompilerUsed() { + StringSet<> AsmUndefinedRefs; + for (int i = 0, e = _asm_undefines.size(); i != e; ++i) + AsmUndefinedRefs[_asm_undefines[i]] = 1; + llvm::updateCompilerUsed(getModule(), *_target, AsmUndefinedRefs); +} + /// parseMetadata - Parse metadata from the module void LTOModule::parseMetadata() { raw_string_ostream OS(LinkerOpts); Index: test/LTO/X86/symver-asm.ll =================================================================== --- test/LTO/X86/symver-asm.ll +++ test/LTO/X86/symver-asm.ll @@ -1,16 +1,26 @@ ; RUN: llvm-as < %s >%t1 -; RUN: llvm-lto -o %t2 %t1 +; RUN: llvm-lto -exported-symbol=io_cancel_0_4 -o %t2 %t1 ; RUN: llvm-nm %t2 | FileCheck %s +; RUN: llvm-lto2 -r %t1,io_cancel_0_4,plx -r %t1,io_cancel_0_4,plx -r %t1,io_cancel_local_0_4,plx -o %t3 %t1 -save-temps +; RUN: llvm-nm %t3.0 | FileCheck %s +; RUN: llvm-dis %t3.0.2.internalize.bc -o - | FileCheck %s --check-prefix=INTERN +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" module asm ".symver io_cancel_0_4,io_cancel@@LIBAIO_0.4" +module asm ".symver io_cancel_local_0_4,io_cancel_local@@LIBAIO_0.4" -; Even without -exported-symbol, io_cancel_0_4 should be noticed by LTOModule's -; RecordStreamer, so it shouldn't get eliminated. However, the object file will -; contain the aliased symver as well as the original. define i32 @io_cancel_0_4() { -; CHECK: io_cancel@@LIBAIO_0.4 -; CHECK: io_cancel_0_4 +; CHECK-DAG: T io_cancel@@LIBAIO_0.4 +; CHECK-DAG: T io_cancel_0_4 + ret i32 0 +} + +define internal i32 @io_cancel_local_0_4() { +; INTERN: llvm.compiler.used {{.*}} @io_cancel_local_0_4 +; INTERN: define internal i32 @io_cancel_local_0_4() +; CHECK-DAG: t io_cancel_local@@LIBAIO_0.4 +; CHECK-DAG: t io_cancel_local_0_4 ret i32 0 } Index: test/tools/llvm-lto2/errors.ll =================================================================== --- test/tools/llvm-lto2/errors.ll +++ test/tools/llvm-lto2/errors.ll @@ -10,5 +10,6 @@ ; ERR4: invalid resolution: foo target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" @foo = global i32 0 Index: tools/llvm-lto2/llvm-lto2.cpp =================================================================== --- tools/llvm-lto2/llvm-lto2.cpp +++ tools/llvm-lto2/llvm-lto2.cpp @@ -157,9 +157,11 @@ Res.FinalDefinitionInLinkageUnit = true; else if (C == 'x') Res.VisibleToRegularObj = true; - else + else { llvm::errs() << "invalid character " << C << " in resolution: " << R << '\n'; + return 1; + } } CommandLineResolutions[{FileName, SymbolName}].push_back(Res); }