forked from OSchip/llvm-project
[LTO] Add option to enable LTOUnit splitting, and disable unless needed
Summary: Adds a new -f[no]split-lto-unit flag that is disabled by default to control module splitting during ThinLTO. It is automatically enabled for -fsanitize=cfi and -fwhole-program-vtables. The new EnableSplitLTOUnit codegen flag is passed down to llvm via a new module flag of the same name. Depends on D53890. Reviewers: pcc Subscribers: ormris, mehdi_amini, inglorion, eraman, steven_wu, dexonsmith, cfe-commits, llvm-commits Differential Revision: https://reviews.llvm.org/D53891 llvm-svn: 350949
This commit is contained in:
parent
290a839891
commit
84cecfcb3d
|
@ -116,6 +116,10 @@ CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the
|
|||
///< compile step.
|
||||
CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole
|
||||
///< program vtable opt).
|
||||
CODEGENOPT(EnableSplitLTOUnit, 1, 0) ///< Enable LTO unit splitting to support
|
||||
/// CFI and traditional whole program
|
||||
/// devirtualization that require whole
|
||||
/// program IR support.
|
||||
CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can
|
||||
///< be used with an incremental
|
||||
///< linker.
|
||||
|
|
|
@ -1776,6 +1776,11 @@ def fwhole_program_vtables : Flag<["-"], "fwhole-program-vtables">, Group<f_Grou
|
|||
HelpText<"Enables whole-program vtable optimization. Requires -flto">;
|
||||
def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group<f_Group>,
|
||||
Flags<[CoreOption]>;
|
||||
def fsplit_lto_unit : Flag<["-"], "fsplit-lto-unit">, Group<f_Group>,
|
||||
Flags<[CoreOption, CC1Option]>,
|
||||
HelpText<"Enables splitting of the LTO unit.">;
|
||||
def fno_split_lto_unit : Flag<["-"], "fno-split-lto-unit">, Group<f_Group>,
|
||||
Flags<[CoreOption]>;
|
||||
def fforce_emit_vtables : Flag<["-"], "fforce-emit-vtables">, Group<f_Group>,
|
||||
Flags<[CC1Option]>,
|
||||
HelpText<"Emits more virtual tables to improve devirtualization">;
|
||||
|
|
|
@ -81,6 +81,7 @@ class SanitizerArgs {
|
|||
|
||||
bool requiresPIE() const;
|
||||
bool needsUnwindTables() const;
|
||||
bool needsLTO() const;
|
||||
bool linkCXXRuntimes() const { return LinkCXXRuntimes; }
|
||||
bool hasCrossDsoCfi() const { return CfiCrossDso; }
|
||||
bool hasAnySanitizer() const { return !Sanitizers.empty(); }
|
||||
|
|
|
@ -814,6 +814,8 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
|
|||
if (!ThinLinkOS)
|
||||
return;
|
||||
}
|
||||
TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
|
||||
CodeGenOpts.EnableSplitLTOUnit);
|
||||
PerModulePasses.add(createWriteThinLTOBitcodePass(
|
||||
*OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));
|
||||
} else {
|
||||
|
@ -824,12 +826,15 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
|
|||
!CodeGenOpts.DisableLLVMPasses &&
|
||||
llvm::Triple(TheModule->getTargetTriple()).getVendor() !=
|
||||
llvm::Triple::Apple);
|
||||
if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO"))
|
||||
if (EmitLTOSummary) {
|
||||
if (!TheModule->getModuleFlag("ThinLTO"))
|
||||
TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
|
||||
TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
|
||||
CodeGenOpts.EnableSplitLTOUnit);
|
||||
}
|
||||
|
||||
PerModulePasses.add(
|
||||
createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
|
||||
EmitLTOSummary));
|
||||
PerModulePasses.add(createBitcodeWriterPass(
|
||||
*OS, CodeGenOpts.EmitLLVMUseLists, EmitLTOSummary));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1054,6 +1059,8 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
|
|||
if (!ThinLinkOS)
|
||||
return;
|
||||
}
|
||||
TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
|
||||
CodeGenOpts.EnableSplitLTOUnit);
|
||||
MPM.addPass(ThinLTOBitcodeWriterPass(*OS, ThinLinkOS ? &ThinLinkOS->os()
|
||||
: nullptr));
|
||||
} else {
|
||||
|
@ -1064,11 +1071,14 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
|
|||
!CodeGenOpts.DisableLLVMPasses &&
|
||||
llvm::Triple(TheModule->getTargetTriple()).getVendor() !=
|
||||
llvm::Triple::Apple);
|
||||
if (EmitLTOSummary && !TheModule->getModuleFlag("ThinLTO"))
|
||||
if (EmitLTOSummary) {
|
||||
if (!TheModule->getModuleFlag("ThinLTO"))
|
||||
TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
|
||||
|
||||
MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
|
||||
EmitLTOSummary));
|
||||
TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
|
||||
CodeGenOpts.EnableSplitLTOUnit);
|
||||
}
|
||||
MPM.addPass(
|
||||
BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, EmitLTOSummary));
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -207,6 +207,8 @@ bool SanitizerArgs::needsUnwindTables() const {
|
|||
return Sanitizers.Mask & NeedsUnwindTables;
|
||||
}
|
||||
|
||||
bool SanitizerArgs::needsLTO() const { return Sanitizers.Mask & NeedsLTO; }
|
||||
|
||||
SanitizerArgs::SanitizerArgs(const ToolChain &TC,
|
||||
const llvm::opt::ArgList &Args) {
|
||||
SanitizerMask AllRemove = 0; // During the loop below, the accumulated set of
|
||||
|
|
|
@ -5226,6 +5226,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
CmdArgs.push_back("-fwhole-program-vtables");
|
||||
}
|
||||
|
||||
bool RequiresSplitLTOUnit = WholeProgramVTables || Sanitize.needsLTO();
|
||||
bool SplitLTOUnit =
|
||||
Args.hasFlag(options::OPT_fsplit_lto_unit,
|
||||
options::OPT_fno_split_lto_unit, RequiresSplitLTOUnit);
|
||||
if (RequiresSplitLTOUnit && !SplitLTOUnit)
|
||||
D.Diag(diag::err_drv_argument_not_allowed_with)
|
||||
<< "-fno-split-lto-unit"
|
||||
<< (WholeProgramVTables ? "-fwhole-program-vtables" : "-fsanitize=cfi");
|
||||
if (SplitLTOUnit)
|
||||
CmdArgs.push_back("-fsplit-lto-unit");
|
||||
|
||||
if (Arg *A = Args.getLastArg(options::OPT_fexperimental_isel,
|
||||
options::OPT_fno_experimental_isel)) {
|
||||
CmdArgs.push_back("-mllvm");
|
||||
|
|
|
@ -907,6 +907,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
|||
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
|
||||
}
|
||||
Opts.LTOUnit = Args.hasFlag(OPT_flto_unit, OPT_fno_lto_unit, false);
|
||||
Opts.EnableSplitLTOUnit = Args.hasArg(OPT_fsplit_lto_unit);
|
||||
if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
|
||||
if (IK.getLanguage() != InputKind::LLVM_IR)
|
||||
Diags.Report(diag::err_drv_argument_only_allowed_with)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
; It additionally enables -fwhole-program-vtables to get more information in
|
||||
; TYPE_IDs of GLOBALVAL_SUMMARY_BLOCK.
|
||||
|
||||
; RUN: opt -thinlto-bc -o %t.o %s
|
||||
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t.o %s
|
||||
|
||||
; FIXME: Fix machine verifier issues and remove -verify-machineinstrs=0. PR39436.
|
||||
; RUN: llvm-lto2 run -thinlto-distributed-indexes %t.o \
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
; Backend test for distribute ThinLTO with CFI.
|
||||
|
||||
; RUN: opt -thinlto-bc -o %t.o %s
|
||||
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t.o %s
|
||||
|
||||
; RUN: llvm-lto2 run -thinlto-distributed-indexes %t.o \
|
||||
; RUN: -o %t2.index \
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// RUN: llvm-dis -o - %t | FileCheck %s
|
||||
// RUN: %clang_cc1 -flto=thin -flto-unit -fno-lto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s
|
||||
// RUN: llvm-dis -o - %t | FileCheck %s
|
||||
// RUN: llvm-bcanalyzer -dump %t | FileCheck %s --check-prefix=NOLTOUNIT
|
||||
// NOLTOUNIT: <FLAGS op0=0/>
|
||||
|
||||
// CHECK-NOT: !type
|
||||
class A {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// RUN: %clang_cc1 -flto=thin -flto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s
|
||||
// RUN: %clang_cc1 -flto=thin -flto-unit -fsplit-lto-unit -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm-bc -o %t %s
|
||||
// RUN: llvm-modextract -o - -n 1 %t | llvm-dis | FileCheck %s
|
||||
// RUN: llvm-modextract -b -o - -n 1 %t | llvm-bcanalyzer -dump | FileCheck %s --check-prefix=LTOUNIT
|
||||
// LTOUNIT: <FLAGS op0=8/>
|
||||
|
||||
// CHECK: @_ZTV1A = linkonce_odr
|
||||
class A {
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin 2>&1 | FileCheck --check-prefix=NOUNIT %s
|
||||
// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin -fsplit-lto-unit 2>&1 | FileCheck --check-prefix=UNIT %s
|
||||
// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin -fno-split-lto-unit 2>&1 | FileCheck --check-prefix=NOUNIT %s
|
||||
// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin -fno-split-lto-unit -fwhole-program-vtables 2>&1 | FileCheck --check-prefix=ERROR1 %s
|
||||
// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin -fno-split-lto-unit -fsanitize=cfi 2>&1 | FileCheck --check-prefix=ERROR2 %s
|
||||
|
||||
// UNIT: "-fsplit-lto-unit"
|
||||
// NOUNIT-NOT: "-fsplit-lto-unit"
|
||||
// ERROR1: error: invalid argument '-fno-split-lto-unit' not allowed with '-fwhole-program-vtables'
|
||||
// ERROR2: error: invalid argument '-fno-split-lto-unit' not allowed with '-fsanitize=cfi'
|
Loading…
Reference in New Issue