forked from OSchip/llvm-project
[LTO] Suppress emission of empty combined module by default
Summary: That unless the user requested an output object (--lto-obj-path), the an unused empty combined module is not emitted. This changed is helpful for some target (ex. RISCV-V) which encoded the ABI info in IR module flags (target-abi). Empty unused module has no ABI info so the linker would get the linking error during merging incompatible ABIs. Reviewers: tejohnson, espindola, MaskRay Subscribers: emaste, inglorion, arichardson, hiraditya, simoncook, MaskRay, steven_wu, dexonsmith, PkmX, dang, lenary, s.egerton, luismarques, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D78988
This commit is contained in:
parent
36183811fb
commit
ad5fad0ac5
|
@ -81,6 +81,7 @@ static lto::Config createConfig() {
|
|||
c.CPU = getCPUStr();
|
||||
c.MAttrs = getMAttrs();
|
||||
c.CGOptLevel = args::getCGOptLevel(config->ltoo);
|
||||
c.AlwaysEmitRegularLTOObj = !config->ltoObjPath.empty();
|
||||
|
||||
if (config->saveTemps)
|
||||
checkError(c.addSaveTemps(std::string(config->outputFile) + ".",
|
||||
|
|
|
@ -138,6 +138,7 @@ static lto::Config createConfig() {
|
|||
c.DwoDir = std::string(config->dwoDir);
|
||||
|
||||
c.HasWholeProgramVisibility = config->ltoWholeProgramVisibility;
|
||||
c.AlwaysEmitRegularLTOObj = !config->ltoObjPath.empty();
|
||||
|
||||
c.TimeTraceEnabled = config->timeTraceEnabled;
|
||||
c.TimeTraceGranularity = config->timeTraceGranularity;
|
||||
|
@ -327,7 +328,8 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
|
|||
}
|
||||
|
||||
if (config->saveTemps) {
|
||||
saveBuffer(buf[0], config->outputFile + ".lto.o");
|
||||
if (!buf[0].empty())
|
||||
saveBuffer(buf[0], config->outputFile + ".lto.o");
|
||||
for (unsigned i = 1; i != maxTasks; ++i)
|
||||
saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o");
|
||||
}
|
||||
|
|
|
@ -11,6 +11,18 @@
|
|||
; RUN: llvm-nm %t4.obj 2>&1 | FileCheck %s -check-prefix=SYMBOLS
|
||||
; RUN: llvm-nm %t4.obj 2>&1 | count 1
|
||||
|
||||
;; Ensure lld emits empty combined module if specific obj-path.
|
||||
; RUN: rm -fr %t.dir/objpath && mkdir -p %t.dir/objpath
|
||||
; RUN: lld-link /out:%t.dir/objpath/a.exe -lto-obj-path:%t4.obj \
|
||||
; RUN: -entry:main %t1.obj %t2.obj -lldsavetemps
|
||||
; RUN: ls %t.dir/objpath/a.exe.lto.* | count 3
|
||||
|
||||
;; Ensure lld does not emit empty combined module in default.
|
||||
; RUN: rm -fr %t.dir/objpath && mkdir -p %t.dir/objpath
|
||||
; RUN: lld-link /out:%t.dir/objpath/a.exe \
|
||||
; RUN: -entry:main %t1.obj %t2.obj -lldsavetemps
|
||||
; RUN: ls %t.dir/objpath/a.exe.lto.* | count 2
|
||||
|
||||
; CHECK: Format: COFF-x86-64
|
||||
; SYMBOLS: @feat.00
|
||||
|
||||
|
|
|
@ -29,10 +29,8 @@ declare void @foo()
|
|||
|
||||
; CHECK: Modules
|
||||
; CHECK: ============================================================
|
||||
; CHECK: Mod 0000 | `{{.*}}main.exe.lto.obj`:
|
||||
; CHECK: Obj: `{{.*}}main.exe.lto.obj`:
|
||||
; CHECK: Mod 0001 | `{{.*}}main.exe.lto.1.obj`:
|
||||
; CHECK: Mod 0000 | `{{.*}}main.exe.lto.1.obj`:
|
||||
; CHECK: Obj: `{{.*}}main.exe.lto.1.obj`:
|
||||
; CHECK: Mod 0002 | `{{.*}}main.exe.lto.2.obj`:
|
||||
; CHECK: Mod 0001 | `{{.*}}main.exe.lto.2.obj`:
|
||||
; CHECK: Obj: `{{.*}}main.exe.lto.2.obj`:
|
||||
; CHECK: Mod 0003 | `* Linker *`:
|
||||
; CHECK: Mod 0002 | `* Linker *`:
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
; REQUIRES: x86
|
||||
; RUN: llvm-as %s -o %t.o
|
||||
|
||||
; RUN: rm -f %t2.*
|
||||
; RUN: echo "foo = 1;" > %t.script
|
||||
; RUN: ld.lld %t.o -o %t2 --script %t.script -save-temps
|
||||
;; Combined module is not empty, but it will be empty after optimization.
|
||||
;; Ensure lld still emits empty combined obj in this case.
|
||||
; RUN: llvm-nm %t2.lto.o | count 0
|
||||
|
||||
; CHECK-NOT: bar
|
||||
; CHECK-NOT: foo
|
||||
|
||||
; RUN: llvm-readobj --symbols %t2 | FileCheck %s --check-prefix=VAL
|
||||
; VAL: Symbol {
|
||||
; VAL: Name: foo
|
||||
|
|
|
@ -14,6 +14,16 @@
|
|||
; RUN: ld.lld -thinlto-index-only -lto-obj-path=%t4.o -shared %t1.o %t2.o -o /dev/null
|
||||
; RUN: llvm-readobj -h %t4.o | FileCheck %s
|
||||
|
||||
;; Ensure lld emits empty combined module if specific obj-path.
|
||||
; RUN: rm -fr %t.dir/objpath && mkdir -p %t.dir/objpath
|
||||
; RUN: ld.lld --plugin-opt=obj-path=%t4.o -shared %t1.o %t2.o -o %t.dir/objpath/a.out --save-temps
|
||||
; RUN: ls %t.dir/objpath/a.out*.lto.* | count 3
|
||||
|
||||
;; Ensure lld does not emit empty combined module in default.
|
||||
; RUN: rm -fr %t.dir/objpath && mkdir -p %t.dir/objpath
|
||||
; RUN: ld.lld %t1.o %t2.o -o %t.dir/objpath/a.out --save-temps
|
||||
; RUN: ls %t.dir/objpath/a.out*.lto.* | count 2
|
||||
|
||||
; CHECK: Format: elf64-x86-64
|
||||
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
|
|
|
@ -66,6 +66,11 @@ struct Config {
|
|||
/// link.
|
||||
bool HasWholeProgramVisibility = false;
|
||||
|
||||
/// Always emit a Regular LTO object even when it is empty because no Regular
|
||||
/// LTO modules were linked. This option is useful for some build system which
|
||||
/// want to know a priori all possible output files.
|
||||
bool AlwaysEmitRegularLTOObj = false;
|
||||
|
||||
/// If this field is set, the set of passes run in the middle-end optimizer
|
||||
/// will be the one specified by the string. Only works with the new pass
|
||||
/// manager as the old one doesn't have this ability.
|
||||
|
|
|
@ -331,6 +331,7 @@ private:
|
|||
std::vector<GlobalValue *> Keep;
|
||||
};
|
||||
std::vector<AddedModule> ModsWithSummaries;
|
||||
bool EmptyCombinedModule = true;
|
||||
} RegularLTO;
|
||||
|
||||
struct ThinLTOState {
|
||||
|
|
|
@ -603,6 +603,7 @@ Error LTO::addModule(InputFile &Input, unsigned ModI,
|
|||
if (LTOInfo->IsThinLTO)
|
||||
return addThinLTO(BM, ModSyms, ResI, ResE);
|
||||
|
||||
RegularLTO.EmptyCombinedModule = false;
|
||||
Expected<RegularLTOState::AddedModule> ModOrErr =
|
||||
addRegularLTO(BM, ModSyms, ResI, ResE);
|
||||
if (!ModOrErr)
|
||||
|
@ -1026,10 +1027,13 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) {
|
|||
!Conf.PostInternalizeModuleHook(0, *RegularLTO.CombinedModule))
|
||||
return Error::success();
|
||||
}
|
||||
if (Error Err =
|
||||
backend(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
|
||||
std::move(RegularLTO.CombinedModule), ThinLTO.CombinedIndex))
|
||||
return Err;
|
||||
|
||||
if (!RegularLTO.EmptyCombinedModule || Conf.AlwaysEmitRegularLTOObj) {
|
||||
if (Error Err = backend(
|
||||
Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
|
||||
std::move(RegularLTO.CombinedModule), ThinLTO.CombinedIndex))
|
||||
return Err;
|
||||
}
|
||||
|
||||
return finalizeOptimizationRemarks(std::move(*DiagFileOrErr));
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
; RUN: opt -module-summary -o %t.bc %s
|
||||
|
||||
; RUN: rm -f %t2.0
|
||||
; RUN: llvm-lto2 run %t.bc -r %t.bc,foo,pl -o %t2 -thinlto-distributed-indexes
|
||||
; RUN: llvm-readobj -h %t2.0 | FileCheck %s
|
||||
; RUN: llvm-nm %t2.0 2>&1 | count 0
|
||||
|
||||
; CHECK: Format: elf64-x86-64
|
||||
; RUN: rm -f %t2.*
|
||||
; RUN: llvm-lto2 run %t.bc -r %t.bc,foo,pl -o %t2 -thinlto-distributed-indexes -save-temps
|
||||
; Ensure lto does not emit empty combined module.
|
||||
; RUN: test ! -e %t2.0
|
||||
; Ensure empty combined module has only 2 temp files.
|
||||
; RUN: ls %t2.0.*.bc | count 2
|
||||
|
||||
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"
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
; Ensure gold generates an index as well as a binary with save-temps in ThinLTO mode.
|
||||
; First force single-threaded mode
|
||||
; RUN: rm -f %t4*
|
||||
; RUN: %gold -plugin %llvmshlibdir/LLVMgold%shlibext \
|
||||
; RUN: -m elf_x86_64 \
|
||||
; RUN: --plugin-opt=save-temps \
|
||||
|
@ -40,6 +41,8 @@
|
|||
; RUN: -shared %t.o %t2.o -o %t4
|
||||
; RUN: llvm-bcanalyzer -dump %t4.index.bc | FileCheck %s --check-prefix=COMBINED
|
||||
; RUN: llvm-nm %t4 | FileCheck %s --check-prefix=NM
|
||||
; Ensure ld does not emit empty combined module in default.
|
||||
; RUN: ls %t4.o* | count 2
|
||||
|
||||
; Check with --no-map-whole-files
|
||||
; RUN: %gold -plugin %llvmshlibdir/LLVMgold%shlibext \
|
||||
|
@ -72,6 +75,8 @@
|
|||
; RUN: -shared %t.o %t2.o -o %t4
|
||||
; RUN: llvm-nm %t5.o1 | FileCheck %s --check-prefix=NM2
|
||||
; RUN: llvm-nm %t5.o2 | FileCheck %s --check-prefix=NM2
|
||||
; Ensure ld emits empty combined module if specific obj-path.
|
||||
; RUN: ls %t5.o* | count 3
|
||||
|
||||
; Test to ensure that thinlto-index-only with obj-path creates the file.
|
||||
; RUN: rm -f %t5.o %t5.o1
|
||||
|
|
|
@ -871,6 +871,7 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
|
|||
Conf.OptLevel = options::OptLevel;
|
||||
Conf.PTO.LoopVectorization = options::OptLevel > 1;
|
||||
Conf.PTO.SLPVectorization = options::OptLevel > 1;
|
||||
Conf.AlwaysEmitRegularLTOObj = !options::obj_path.empty();
|
||||
|
||||
if (options::thinlto_index_only) {
|
||||
std::string OldPrefix, NewPrefix;
|
||||
|
|
Loading…
Reference in New Issue