using irsymtab::Symbol::isWeak;
using irsymtab::Symbol::isIndirect;
using irsymtab::Symbol::getName;
+ using irsymtab::Symbol::getIRName;
using irsymtab::Symbol::getVisibility;
using irsymtab::Symbol::canBeOmittedFromSymbolTable;
using irsymtab::Symbol::isTLS;
// Returns a table with all the comdats used by this file.
ArrayRef<StringRef> getComdatTable() const { return ComdatTable; }
+ // Returns the only BitcodeModule from InputFile.
+ BitcodeModule &getSingleBitcodeModule();
+
private:
ArrayRef<Symbol> module_symbols(unsigned I) const {
const auto &Indices = ModuleSymIndices[I];
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/LTO/LTO.h"
#include "llvm/Support/CachePruning.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/MemoryBuffer.h"
class LLVMContext;
class TargetMachine;
-/// Wrapper around MemoryBufferRef, owning the identifier
-class ThinLTOBuffer {
- std::string OwnedIdentifier;
- StringRef Buffer;
-
-public:
- ThinLTOBuffer(StringRef Buffer, StringRef Identifier)
- : OwnedIdentifier(Identifier), Buffer(Buffer) {}
-
- MemoryBufferRef getMemBuffer() const {
- return MemoryBufferRef(Buffer,
- {OwnedIdentifier.c_str(), OwnedIdentifier.size()});
- }
- StringRef getBuffer() const { return Buffer; }
- StringRef getBufferIdentifier() const { return OwnedIdentifier; }
-};
-
/// Helper to gather options relevant to the target machine creation
struct TargetMachineBuilder {
Triple TheTriple;
* and additionally resolve weak and linkonce symbols.
* Index is updated to reflect linkage changes from weak resolution.
*/
- void promote(Module &Module, ModuleSummaryIndex &Index);
+ void promote(Module &Module, ModuleSummaryIndex &Index,
+ const lto::InputFile &File);
/**
* Compute and emit the imported files for module at \p ModulePath.
*/
void emitImports(Module &Module, StringRef OutputName,
- ModuleSummaryIndex &Index);
+ ModuleSummaryIndex &Index,
+ const lto::InputFile &File);
/**
* Perform cross-module importing for the module identified by
* ModuleIdentifier.
*/
- void crossModuleImport(Module &Module, ModuleSummaryIndex &Index);
+ void crossModuleImport(Module &Module, ModuleSummaryIndex &Index,
+ const lto::InputFile &File);
/**
* Compute the list of summaries needed for importing into module.
*/
void gatherImportedSummariesForModule(
Module &Module, ModuleSummaryIndex &Index,
- std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex);
+ std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex,
+ const lto::InputFile &File);
/**
* Perform internalization. Index is updated to reflect linkage changes.
*/
- void internalize(Module &Module, ModuleSummaryIndex &Index);
+ void internalize(Module &Module, ModuleSummaryIndex &Index,
+ const lto::InputFile &File);
/**
* Perform post-importing ThinLTO optimizations.
/// Vector holding the input buffers containing the bitcode modules to
/// process.
- std::vector<ThinLTOBuffer> Modules;
+ std::vector<std::unique_ptr<lto::InputFile>> Modules;
/// Set of symbols that need to be preserved outside of the set of bitcode
/// files.
return Mods[0].getModuleIdentifier();
}
+BitcodeModule &InputFile::getSingleBitcodeModule() {
+ assert(Mods.size() == 1 && "Expect only one bitcode module");
+ return Mods[0];
+}
+
LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
Config &Conf)
: ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel),
}
}
-static StringMap<MemoryBufferRef>
-generateModuleMap(const std::vector<ThinLTOBuffer> &Modules) {
- StringMap<MemoryBufferRef> ModuleMap;
- for (auto &ModuleBuffer : Modules) {
- assert(ModuleMap.find(ModuleBuffer.getBufferIdentifier()) ==
- ModuleMap.end() &&
+static StringMap<lto::InputFile *>
+generateModuleMap(std::vector<std::unique_ptr<lto::InputFile>> &Modules) {
+ StringMap<lto::InputFile *> ModuleMap;
+ for (auto &M : Modules) {
+ assert(ModuleMap.find(M->getName()) == ModuleMap.end() &&
"Expect unique Buffer Identifier");
- ModuleMap[ModuleBuffer.getBufferIdentifier()] = ModuleBuffer.getMemBuffer();
+ ModuleMap[M->getName()] = M.get();
}
return ModuleMap;
}
}
}
-static std::unique_ptr<Module>
-loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext &Context,
- bool Lazy, bool IsImporting) {
+static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile *Input,
+ LLVMContext &Context,
+ bool Lazy,
+ bool IsImporting) {
+ auto &Mod = Input->getSingleBitcodeModule();
SMDiagnostic Err;
Expected<std::unique_ptr<Module>> ModuleOrErr =
- Lazy
- ? getLazyBitcodeModule(Buffer, Context,
- /* ShouldLazyLoadMetadata */ true, IsImporting)
- : parseBitcodeFile(Buffer, Context);
+ Lazy ? Mod.getLazyModule(Context,
+ /* ShouldLazyLoadMetadata */ true, IsImporting)
+ : Mod.parseModule(Context);
if (!ModuleOrErr) {
handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
- SMDiagnostic Err = SMDiagnostic(Buffer.getBufferIdentifier(),
+ SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
SourceMgr::DK_Error, EIB.message());
Err.print("ThinLTO", errs());
});
}
if (!Lazy)
verifyLoadedModule(*ModuleOrErr.get());
- return std::move(ModuleOrErr.get());
+ return std::move(*ModuleOrErr);
}
static void
crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index,
- StringMap<MemoryBufferRef> &ModuleMap,
+ StringMap<lto::InputFile*> &ModuleMap,
const FunctionImporter::ImportMapTy &ImportList) {
auto Loader = [&](StringRef Identifier) {
- return loadModuleFromBuffer(ModuleMap[Identifier], TheModule.getContext(),
- /*Lazy=*/true, /*IsImporting*/ true);
+ auto &Input = ModuleMap[Identifier];
+ return loadModuleFromInput(Input, TheModule.getContext(),
+ /*Lazy=*/true, /*IsImporting*/ true);
};
FunctionImporter Importer(Index, Loader);
PM.run(TheModule);
}
+static void
+addUsedSymbolToPreservedGUID(const lto::InputFile &File,
+ DenseSet<GlobalValue::GUID> &PreservedGUID) {
+ for (const auto &Sym : File.symbols()) {
+ if (Sym.isUsed())
+ PreservedGUID.insert(GlobalValue::getGUID(Sym.getIRName()));
+ }
+}
+
// Convert the PreservedSymbols map from "Name" based to "GUID" based.
static DenseSet<GlobalValue::GUID>
computeGUIDPreservedSymbols(const StringSet<> &PreservedSymbols,
static std::unique_ptr<MemoryBuffer>
ProcessThinLTOModule(Module &TheModule, ModuleSummaryIndex &Index,
- StringMap<MemoryBufferRef> &ModuleMap, TargetMachine &TM,
+ StringMap<lto::InputFile *> &ModuleMap, TargetMachine &TM,
const FunctionImporter::ImportMapTy &ImportList,
const FunctionImporter::ExportSetTy &ExportList,
const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
} // end anonymous namespace
void ThinLTOCodeGenerator::addModule(StringRef Identifier, StringRef Data) {
- ThinLTOBuffer Buffer(Data, Identifier);
- LLVMContext Context;
- StringRef TripleStr;
- ErrorOr<std::string> TripleOrErr = expectedToErrorOrAndEmitErrors(
- Context, getBitcodeTargetTriple(Buffer.getMemBuffer()));
+ MemoryBufferRef Buffer(Data, Identifier);
- if (TripleOrErr)
- TripleStr = *TripleOrErr;
+ auto InputOrError = lto::InputFile::create(Buffer);
+ if (!InputOrError)
+ report_fatal_error("ThinLTO cannot create input file: " +
+ toString(InputOrError.takeError()));
+ auto TripleStr = (*InputOrError)->getTargetTriple();
Triple TheTriple(TripleStr);
if (Modules.empty())
initTMBuilder(TMBuilder, Triple(TMBuilder.TheTriple.merge(TheTriple)));
}
- Modules.push_back(Buffer);
+ Modules.emplace_back(std::move(*InputOrError));
}
void ThinLTOCodeGenerator::preserveSymbol(StringRef Name) {
std::unique_ptr<ModuleSummaryIndex> CombinedIndex =
llvm::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
uint64_t NextModuleId = 0;
- for (auto &ModuleBuffer : Modules) {
- if (Error Err = readModuleSummaryIndex(ModuleBuffer.getMemBuffer(),
- *CombinedIndex, NextModuleId++)) {
+ for (auto &Mod : Modules) {
+ auto &M = Mod->getSingleBitcodeModule();
+ if (Error Err =
+ M.readSummary(*CombinedIndex, Mod->getName(), NextModuleId++)) {
// FIXME diagnose
logAllUnhandledErrors(
std::move(Err), errs(),
* Perform promotion and renaming of exported internal functions.
* Index is updated to reflect linkage changes from weak resolution.
*/
-void ThinLTOCodeGenerator::promote(Module &TheModule,
- ModuleSummaryIndex &Index) {
+void ThinLTOCodeGenerator::promote(Module &TheModule, ModuleSummaryIndex &Index,
+ const lto::InputFile &File) {
auto ModuleCount = Index.modulePaths().size();
auto ModuleIdentifier = TheModule.getModuleIdentifier();
auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
PreservedSymbols, Triple(TheModule.getTargetTriple()));
+ // Add used symbol to the preserved symbols.
+ addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
+
// Compute "dead" symbols, we don't want to import/export these!
computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
* Perform cross-module importing for the module identified by ModuleIdentifier.
*/
void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule,
- ModuleSummaryIndex &Index) {
+ ModuleSummaryIndex &Index,
+ const lto::InputFile &File) {
auto ModuleMap = generateModuleMap(Modules);
auto ModuleCount = Index.modulePaths().size();
auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
PreservedSymbols, Triple(TheModule.getTargetTriple()));
+ addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
+
// Compute "dead" symbols, we don't want to import/export these!
computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
*/
void ThinLTOCodeGenerator::gatherImportedSummariesForModule(
Module &TheModule, ModuleSummaryIndex &Index,
- std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex) {
+ std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex,
+ const lto::InputFile &File) {
auto ModuleCount = Index.modulePaths().size();
auto ModuleIdentifier = TheModule.getModuleIdentifier();
auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
PreservedSymbols, Triple(TheModule.getTargetTriple()));
+ addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
+
// Compute "dead" symbols, we don't want to import/export these!
computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
* Emit the list of files needed for importing into module.
*/
void ThinLTOCodeGenerator::emitImports(Module &TheModule, StringRef OutputName,
- ModuleSummaryIndex &Index) {
+ ModuleSummaryIndex &Index,
+ const lto::InputFile &File) {
auto ModuleCount = Index.modulePaths().size();
auto ModuleIdentifier = TheModule.getModuleIdentifier();
auto GUIDPreservedSymbols = computeGUIDPreservedSymbols(
PreservedSymbols, Triple(TheModule.getTargetTriple()));
+ addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
+
// Compute "dead" symbols, we don't want to import/export these!
computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols);
}
/**
- * Perform internalization. Index is updated to reflect linkage changes.
+ * Perform internalization. Runs promote and internalization together.
+ * Index is updated to reflect linkage changes.
*/
void ThinLTOCodeGenerator::internalize(Module &TheModule,
- ModuleSummaryIndex &Index) {
+ ModuleSummaryIndex &Index,
+ const lto::InputFile &File) {
initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
auto ModuleCount = Index.modulePaths().size();
auto ModuleIdentifier = TheModule.getModuleIdentifier();
auto GUIDPreservedSymbols =
computeGUIDPreservedSymbols(PreservedSymbols, TMBuilder.TheTriple);
+ addUsedSymbolToPreservedGUID(File, GUIDPreservedSymbols);
+
// Collect for each module the list of function it defines (GUID -> Summary).
StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries(ModuleCount);
Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
if (ExportList.empty() && GUIDPreservedSymbols.empty())
return;
- // Internalization
+ // Resolve prevailing symbols
+ StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
+ resolvePrevailingInIndex(Index, ResolvedODR);
+
+ // Promote the exported values in the index, so that they are promoted
+ // in the module.
internalizeAndPromoteInIndex(ExportLists, GUIDPreservedSymbols, Index);
+
+ promoteModule(TheModule, Index);
+
+ // Internalization
+ thinLTOResolvePrevailingInModule(
+ TheModule, ModuleToDefinedGVSummaries[ModuleIdentifier]);
+
thinLTOInternalizeModule(TheModule,
ModuleToDefinedGVSummaries[ModuleIdentifier]);
}
// Perform only parallel codegen and return.
ThreadPool Pool;
int count = 0;
- for (auto &ModuleBuffer : Modules) {
+ for (auto &Mod : Modules) {
Pool.async([&](int count) {
LLVMContext Context;
Context.setDiscardValueNames(LTODiscardValueNames);
// Parse module now
- auto TheModule =
- loadModuleFromBuffer(ModuleBuffer.getMemBuffer(), Context, false,
- /*IsImporting*/ false);
+ auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
+ /*IsImporting*/ false);
// CodeGen
auto OutputBuffer = codegenModule(*TheModule, *TMBuilder.create());
auto GUIDPreservedSymbols =
computeGUIDPreservedSymbols(PreservedSymbols, TMBuilder.TheTriple);
+ // Add used symbol from inputs to the preserved symbols.
+ for (const auto &M : Modules)
+ addUsedSymbolToPreservedGUID(*M, GUIDPreservedSymbols);
+
// Compute "dead" symbols, we don't want to import/export these!
computeDeadSymbolsInIndex(*Index, GUIDPreservedSymbols);
// GVSummary and ResolvedODR maps to enable threaded access to these maps
// below.
for (auto &Module : Modules) {
- auto ModuleIdentifier = Module.getBufferIdentifier();
+ auto ModuleIdentifier = Module->getName();
ExportLists[ModuleIdentifier];
ImportLists[ModuleIdentifier];
ResolvedODR[ModuleIdentifier];
ModulesOrdering.resize(Modules.size());
std::iota(ModulesOrdering.begin(), ModulesOrdering.end(), 0);
llvm::sort(ModulesOrdering, [&](int LeftIndex, int RightIndex) {
- auto LSize = Modules[LeftIndex].getBuffer().size();
- auto RSize = Modules[RightIndex].getBuffer().size();
+ auto LSize =
+ Modules[LeftIndex]->getSingleBitcodeModule().getBuffer().size();
+ auto RSize =
+ Modules[RightIndex]->getSingleBitcodeModule().getBuffer().size();
return LSize > RSize;
});
{
ThreadPool Pool(ThreadCount);
for (auto IndexCount : ModulesOrdering) {
- auto &ModuleBuffer = Modules[IndexCount];
+ auto &Mod = Modules[IndexCount];
Pool.async([&](int count) {
- auto ModuleIdentifier = ModuleBuffer.getBufferIdentifier();
+ auto ModuleIdentifier = Mod->getName();
auto &ExportList = ExportLists[ModuleIdentifier];
auto &DefinedGVSummaries = ModuleToDefinedGVSummaries[ModuleIdentifier];
}
// Parse module now
- auto TheModule =
- loadModuleFromBuffer(ModuleBuffer.getMemBuffer(), Context, false,
- /*IsImporting*/ false);
+ auto TheModule = loadModuleFromInput(Mod.get(), Context, false,
+ /*IsImporting*/ false);
// Save temps: original file.
saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
; Needs a function for the combined index to be populated
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
define void @bar() {
ret void
}
; COMBINED-DAG: <HASH abbrevid={{[0-9]*}} op0=[[HASH1_1]] op1=[[HASH1_2]] op2=[[HASH1_3]] op3=[[HASH1_4]] op4=[[HASH1_5]]/>
; COMBINED-DAG: <HASH abbrevid={{[0-9]*}} op0=[[HASH2_1]] op1=[[HASH2_2]] op2=[[HASH2_3]] op3=[[HASH2_4]] op4=[[HASH2_5]]/>
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
; Need a function for the combined index to be populated.
define void @foo() {
-
-
-
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
@globalfuncAlias = alias void (...), bitcast (void ()* @globalfunc to void (...)*)
@globalfuncWeakAlias = weak alias void (...), bitcast (void ()* @globalfunc to void (...)*)
-
-
-
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
@globalfuncAlias = alias void (...), bitcast (void ()* @globalfunc to void (...)*)
@globalfuncWeakAlias = weak alias void (...), bitcast (void ()* @globalfunc to void (...)*)
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
define void @g() {
entry:
ret void
target triple = "x86_64-apple-macosx10.11.0"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
; An internal global variable that can't be renamed because it has a section
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
@var_with_section = internal global i32 0, section "some_section"
; @reference_gv_with_section() can't be imported
--- /dev/null
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.15.0"
+
+define i32 @main() {
+entry:
+ %call = call i32 @bar()
+ ret i32 0
+}
+
+declare i32 @bar()
; IMPORT-DAG: declare void @linkonceODRfuncLinkonceAlias()
; IMPORT-DAG: define available_externally void @linkonceODRfuncLinkonceODRAlias()
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
define i32 @main() #0 {
entry:
call void @globalfuncAlias()
; PROMOTE_MOD1: @weakfuncLinkonceODRAlias = weak_odr alias void (...), bitcast (void ()* @weakfunc.mod1 to void (...)*)
; PROMOTE_MOD2: @weakfuncLinkonceODRAlias = linkonce_odr alias void (...), bitcast (void ()* @weakfunc to void (...)*)
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
@linkonceODRfuncAlias = alias void (...), bitcast (void ()* @linkonceODRfunc.mod1 to void (...)*)
@linkonceODRfuncWeakAlias = weak alias void (...), bitcast (void ()* @linkonceODRfunc.mod1 to void (...)*)
; RUN: opt -module-summary %p/Inputs/deadstrip.ll -o %t2.bc
; RUN: llvm-lto -thinlto-action=thinlink -o %t.index.bc %t1.bc %t2.bc
-; RUN: llvm-lto -exported-symbol=_main -thinlto-action=promote %t1.bc -thinlto-index=%t.index.bc -o - | llvm-lto -exported-symbol=_main -thinlto-action=internalize -thinlto-index %t.index.bc -thinlto-module-id=%t1.bc - -o - | llvm-dis -o - | FileCheck %s
-; RUN: llvm-lto -exported-symbol=_main -thinlto-action=promote %t2.bc -thinlto-index=%t.index.bc -o - | llvm-lto -exported-symbol=_main -thinlto-action=internalize -thinlto-index %t.index.bc -thinlto-module-id=%t2.bc - -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK2
+; RUN: llvm-lto -exported-symbol=_main -thinlto-action=internalize %t1.bc -thinlto-index=%t.index.bc -o - | llvm-dis -o - | FileCheck %s
+; RUN: llvm-lto -exported-symbol=_main -thinlto-action=internalize %t2.bc -thinlto-index=%t.index.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK2
; RUN: llvm-lto -exported-symbol=_main -thinlto-action=run -stats %t1.bc %t2.bc 2>&1 | FileCheck %s --check-prefix=STATS
; RUN: llvm-nm %t1.bc.thinlto.o | FileCheck %s --check-prefix=CHECK-NM
; RUN: llvm-dis %t1.bc.thinlto.bc -o - | FileCheck %s --check-prefix=DIS
; DIS: aliasee: null
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
declare void @g(...)
declare void @analias(...)
; INTERNALIZE: define internal void @linkonce_func()
; INTERNALIZE-OPTION-DISABLE: define void @foo
; INTERNALIZE-OPTION-DISABLE: define void @bar
-; INTERNALIZE-OPTION-DISABLE: define linkonce void @linkonce_func()
+; INTERNALIZE-OPTION-DISABLE: define weak void @linkonce_func()
; INTERNALIZE2: define dso_local void @foo
; INTERNALIZE2: define internal void @bar
; INTERNALIZE2: define internal void @linkonce_func()
; RUN: llvm-lto -thinlto-action=thinlink -o %t3.bc %t.bc %t2.bc
; RUN: llvm-lto -thinlto-action=promote %t.bc -thinlto-index=%t3.bc -o - | llvm-dis -o - | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
; CHECK: @linkonceodrunnamed = weak_odr hidden unnamed_addr constant i32 0
@linkonceodrunnamed = linkonce_odr unnamed_addr constant i32 0
; RUN: llvm-dis < %t1.bc.thinlto.imported.bc | FileCheck %s --check-prefix=CHECK1
; RUN: llvm-dis < %t2.bc.thinlto.imported.bc | FileCheck %s --check-prefix=CHECK2
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"
; CHECK1: target triple = "x86_64-apple-macosx10.12.0"
; RUN: llvm-lto -thinlto-action=distributedindexes -thinlto-prefix-replace="%t/oldpath/;%t/newpath/" -thinlto-index %t.index.bc %t/oldpath/prefix_replace.o
; RUN: ls %t/newpath/prefix_replace.o.thinlto.bc
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
define void @f() {
entry:
; IMPORT: declare void @reference_gv_with_section()
; Canary to check that importing is correctly set up.
; IMPORT: define available_externally void @foo()
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
define i32 @main() {
--- /dev/null
+; RUN: opt -module-summary -o %t.bc %s
+; RUN: opt -module-summary -o %t-main.bc %S/Inputs/thinlto-internalize-used2.ll
+; RUN: llvm-lto -thinlto-action=thinlink %t.bc %t-main.bc -o %t-index.bc
+; RUN: llvm-lto -thinlto-action=internalize -thinlto-index %t-index.bc %t.bc -o %t.promote.bc
+; RUN: llvm-dis %t.promote.bc -o - | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.15.0"
+
+@llvm.used = appending global [1 x i8*] [i8* bitcast (i32 ()* @foo to i8*)], section "llvm.metadata"
+
+; Make sure foo is not internalized.
+; CHECK: define i32 @foo()
+define i32 @foo() {
+ ret i32 0
+}
+
+define hidden i32 @bar() {
+ ret i32 0
+}
+
; non-prevailing ODR are not kept when possible, but non-ODR non-prevailing
; are not affected.
; RUN: llvm-lto -thinlto-action=promote %t.bc -thinlto-index=%t3.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=MOD1
-; RUN: llvm-lto -thinlto-action=promote %t.bc -thinlto-index=%t3.bc -exported-symbol=linkoncefunc -o - | llvm-lto -thinlto-action=internalize -thinlto-module-id=%t.bc - -thinlto-index=%t3.bc -exported-symbol=linkoncefunc -o - | llvm-dis -o - | FileCheck %s --check-prefix=MOD1-INT
+; RUN: llvm-lto -thinlto-action=internalize %t.bc -thinlto-index=%t3.bc -exported-symbol=linkoncefunc -o - | llvm-dis -o - | FileCheck %s --check-prefix=MOD1-INT
; RUN: llvm-lto -thinlto-action=promote %t2.bc -thinlto-index=%t3.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=MOD2
; When exported, we always preserve a linkonce
; RUN: llvm-lto -thinlto-action=promote %t.bc -thinlto-index=%t3.bc -o - --exported-symbol=linkonceodrfuncInSingleModule | llvm-dis -o - | FileCheck %s --check-prefix=EXPORTED
; RUN: opt -module-summary %s -o %t.bc
; RUN: llvm-lto -thinlto-action=thinlink -o %t2.bc %t.bc
-; RUN: llvm-lto -thinlto-action=promote %t.bc -thinlto-index=%t2.bc -exported-symbol=foo -o - | llvm-lto -thinlto-action=internalize -thinlto-module-id=%t.bc - -thinlto-index=%t2.bc -exported-symbol=foo -o - | llvm-dis -o - | FileCheck %s
+; RUN: llvm-lto -thinlto-action=internalize %t.bc -thinlto-index=%t2.bc -exported-symbol=foo -o - | llvm-dis -o - | FileCheck %s
; CHECK: define weak_odr void @foo()
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
define linkonce_odr void @foo() {
ret void
}
; BCA: <GLOBALVAL_SUMMARY_BLOCK
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
; CHECK: @g = global i8 42
@g = global i8 42
return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
}
-static std::unique_ptr<Module> loadModule(StringRef Filename,
- LLVMContext &Ctx) {
- SMDiagnostic Err;
- std::unique_ptr<Module> M(parseIRFile(Filename, Err, Ctx));
- if (!M) {
- Err.print("llvm-lto", errs());
- report_fatal_error("Can't load module for file " + Filename);
- }
- maybeVerifyModule(*M);
+static std::unique_ptr<MemoryBuffer> loadFile(StringRef Filename) {
+ ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename.str() +
+ "': ");
+ return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
+}
+static std::unique_ptr<lto::InputFile> loadInputFile(MemoryBufferRef Buffer) {
+ ExitOnError ExitOnErr("llvm-lto: error loading input '" +
+ Buffer.getBufferIdentifier().str() + "': ");
+ return ExitOnErr(lto::InputFile::create(Buffer));
+}
+
+static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile &File,
+ LLVMContext &CTX) {
+ auto &Mod = File.getSingleBitcodeModule();
+ auto ModuleOrErr = Mod.parseModule(CTX);
+ if (!ModuleOrErr) {
+ handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
+ SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
+ SourceMgr::DK_Error, EIB.message());
+ Err.print("llvm-lto", errs());
+ });
+ report_fatal_error("Can't load module, abort.");
+ }
+ maybeVerifyModule(**ModuleOrErr);
if (ThinLTOModuleId.getNumOccurrences()) {
if (InputFilenames.size() != 1)
report_fatal_error("Can't override the module id for multiple files");
- M->setModuleIdentifier(ThinLTOModuleId);
+ (*ModuleOrErr)->setModuleIdentifier(ThinLTOModuleId);
}
- return M;
+ return std::move(*ModuleOrErr);
}
static void writeModuleToFile(Module &TheModule, StringRef Filename) {
auto Index = loadCombinedIndex();
for (auto &Filename : InputFilenames) {
LLVMContext Ctx;
- auto TheModule = loadModule(Filename, Ctx);
+ auto Buffer = loadFile(Filename);
+ auto Input = loadInputFile(Buffer->getMemBufferRef());
+ auto TheModule = loadModuleFromInput(*Input, Ctx);
// Build a map of module to the GUIDs and summary objects that should
// be written to its index.
std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
- ThinGenerator.gatherImportedSummariesForModule(*TheModule, *Index,
- ModuleToSummariesForIndex);
+ ThinGenerator.gatherImportedSummariesForModule(
+ *TheModule, *Index, ModuleToSummariesForIndex, *Input);
std::string OutputName = OutputFilename;
if (OutputName.empty()) {
auto Index = loadCombinedIndex();
for (auto &Filename : InputFilenames) {
LLVMContext Ctx;
- auto TheModule = loadModule(Filename, Ctx);
+ auto Buffer = loadFile(Filename);
+ auto Input = loadInputFile(Buffer->getMemBufferRef());
+ auto TheModule = loadModuleFromInput(*Input, Ctx);
std::string OutputName = OutputFilename;
if (OutputName.empty()) {
OutputName = Filename + ".imports";
}
- OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
- ThinGenerator.emitImports(*TheModule, OutputName, *Index);
+ OutputName =
+ getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
+ ThinGenerator.emitImports(*TheModule, OutputName, *Index, *Input);
}
}
auto Index = loadCombinedIndex();
for (auto &Filename : InputFilenames) {
LLVMContext Ctx;
- auto TheModule = loadModule(Filename, Ctx);
+ auto Buffer = loadFile(Filename);
+ auto Input = loadInputFile(Buffer->getMemBufferRef());
+ auto TheModule = loadModuleFromInput(*Input, Ctx);
- ThinGenerator.promote(*TheModule, *Index);
+ ThinGenerator.promote(*TheModule, *Index, *Input);
std::string OutputName = OutputFilename;
if (OutputName.empty()) {
for (auto &Filename : InputFilenames) {
LLVMContext Ctx;
- auto TheModule = loadModule(Filename, Ctx);
+ auto Buffer = loadFile(Filename);
+ auto Input = loadInputFile(Buffer->getMemBufferRef());
+ auto TheModule = loadModuleFromInput(*Input, Ctx);
- ThinGenerator.crossModuleImport(*TheModule, *Index);
+ ThinGenerator.crossModuleImport(*TheModule, *Index, *Input);
std::string OutputName = OutputFilename;
if (OutputName.empty()) {
for (auto &Filename : InputFilenames) {
LLVMContext Ctx;
- auto TheModule = loadModule(Filename, Ctx);
+ auto Buffer = loadFile(Filename);
+ auto Input = loadInputFile(Buffer->getMemBufferRef());
+ auto TheModule = loadModuleFromInput(*Input, Ctx);
- ThinGenerator.internalize(*TheModule, *Index);
+ ThinGenerator.internalize(*TheModule, *Index, *Input);
std::string OutputName = OutputFilename;
if (OutputName.empty()) {
for (auto &Filename : InputFilenames) {
LLVMContext Ctx;
- auto TheModule = loadModule(Filename, Ctx);
+ auto Buffer = loadFile(Filename);
+ auto Input = loadInputFile(Buffer->getMemBufferRef());
+ auto TheModule = loadModuleFromInput(*Input, Ctx);
ThinGenerator.optimize(*TheModule);