aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Kirth <paulkirth@google.com>2024-01-23 14:04:52 -0800
committerGitHub <noreply@github.com>2024-01-23 14:04:52 -0800
commit9d476e1e1a18af390e3455a6622ee67a69c64103 (patch)
treef4dfc7844153746db48b935dd4123f1d64cf7bd4
parenta829f109ffd518230df5191c64aa427603cf10d9 (diff)
downloadllvm-9d476e1e1a18af390e3455a6622ee67a69c64103.zip
llvm-9d476e1e1a18af390e3455a6622ee67a69c64103.tar.gz
llvm-9d476e1e1a18af390e3455a6622ee67a69c64103.tar.bz2
[clang][FatLTO] Avoid UnifiedLTO until it can support WPD/CFI (#79061)
Currently, the UnifiedLTO pipeline seems to have trouble with several LTO features, like SplitLTO units, which means we cannot use important optimizations like Whole Program Devirtualization or security hardening instrumentation like CFI. This patch reverts FatLTO to using distinct pipelines for Full LTO and ThinLTO. It still avoids module cloning, since that was error prone.
-rw-r--r--clang/lib/CodeGen/BackendUtil.cpp8
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp4
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp14
-rw-r--r--clang/test/CodeGen/fat-lto-objects.c38
-rw-r--r--clang/test/Driver/fat-lto-objects.c14
-rw-r--r--llvm/docs/FatLTO.rst4
-rw-r--r--llvm/include/llvm/Passes/PassBuilder.h9
-rw-r--r--llvm/include/llvm/Transforms/IPO/EmbedBitcodePass.h16
-rw-r--r--llvm/lib/Passes/PassBuilder.cpp20
-rw-r--r--llvm/lib/Passes/PassBuilderPipelines.cpp15
-rw-r--r--llvm/lib/Passes/PassRegistry.def5
-rw-r--r--llvm/lib/Transforms/IPO/EmbedBitcodePass.cpp12
-rw-r--r--llvm/test/CodeGen/X86/fat-lto-section.ll2
-rw-r--r--llvm/test/Transforms/EmbedBitcode/embed.ll3
14 files changed, 92 insertions, 72 deletions
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index a6142d9..ec203f6 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1001,8 +1001,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
}
if (CodeGenOpts.FatLTO) {
- assert(CodeGenOpts.UnifiedLTO && "FatLTO requires UnifiedLTO");
- MPM.addPass(PB.buildFatLTODefaultPipeline(Level));
+ MPM.addPass(PB.buildFatLTODefaultPipeline(
+ Level, PrepareForThinLTO,
+ PrepareForThinLTO || shouldEmitRegularLTOSummary()));
} else if (PrepareForThinLTO) {
MPM.addPass(PB.buildThinLTOPreLinkDefaultPipeline(Level));
} else if (PrepareForLTO) {
@@ -1073,8 +1074,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit",
uint32_t(CodeGenOpts.EnableSplitLTOUnit));
- // FatLTO always means UnifiedLTO
- if (!TheModule->getModuleFlag("UnifiedLTO"))
+ if (CodeGenOpts.UnifiedLTO && !TheModule->getModuleFlag("UnifiedLTO"))
TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1));
}
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index bcba7cb..5dc614e 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4854,9 +4854,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool UnifiedLTO = false;
if (IsUsingLTO) {
UnifiedLTO = Args.hasFlag(options::OPT_funified_lto,
- options::OPT_fno_unified_lto, Triple.isPS()) ||
- Args.hasFlag(options::OPT_ffat_lto_objects,
- options::OPT_fno_fat_lto_objects, false);
+ options::OPT_fno_unified_lto, Triple.isPS());
if (UnifiedLTO)
CmdArgs.push_back("-funified-lto");
}
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 7edea77..feb4de2 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1861,20 +1861,6 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
if (Args.hasArg(OPT_funified_lto))
Opts.PrepareForThinLTO = true;
}
- if (Arg *A = Args.getLastArg(options::OPT_ffat_lto_objects,
- options::OPT_fno_fat_lto_objects)) {
- if (A->getOption().matches(options::OPT_ffat_lto_objects)) {
- if (Arg *Uni = Args.getLastArg(options::OPT_funified_lto,
- options::OPT_fno_unified_lto)) {
- if (Uni->getOption().matches(options::OPT_fno_unified_lto))
- Diags.Report(diag::err_drv_incompatible_options)
- << A->getAsString(Args) << "-fno-unified-lto";
- } else
- Diags.Report(diag::err_drv_argument_only_allowed_with)
- << A->getAsString(Args) << "-funified-lto";
- }
- }
-
if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
if (IK.getLanguage() != Language::LLVM_IR)
Diags.Report(diag::err_drv_argument_only_allowed_with)
diff --git a/clang/test/CodeGen/fat-lto-objects.c b/clang/test/CodeGen/fat-lto-objects.c
index 5c8ad1f..afce798 100644
--- a/clang/test/CodeGen/fat-lto-objects.c
+++ b/clang/test/CodeGen/fat-lto-objects.c
@@ -1,34 +1,37 @@
// REQUIRES: x86-registered-target
-// RUN: not %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -ffat-lto-objects -fsplit-lto-unit -emit-llvm < %s 2>&1 | FileCheck %s --check-prefixes=NO-UNIFIED
+// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -ffat-lto-objects -fsplit-lto-unit -emit-llvm < %s | FileCheck %s --check-prefixes=FULL,SPLIT
+// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -ffat-lto-objects -emit-llvm < %s | FileCheck %s --check-prefixes=FULL,SPLIT
-// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -funified-lto -ffat-lto-objects -fsplit-lto-unit -emit-llvm < %s | FileCheck %s --check-prefixes=FULL,SPLIT,UNIFIED
-// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -funified-lto -ffat-lto-objects -emit-llvm < %s | FileCheck %s --check-prefixes=FULL,NOSPLIT,UNIFIED
+// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=thin -fsplit-lto-unit -ffat-lto-objects -emit-llvm < %s | FileCheck %s --check-prefixes=THIN,SPLIT
+// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=thin -ffat-lto-objects -emit-llvm < %s | FileCheck %s --check-prefixes=THIN,NOSPLIT
-// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=thin -funified-lto -fsplit-lto-unit -ffat-lto-objects -emit-llvm < %s | FileCheck %s --check-prefixes=THIN,SPLIT,UNIFIED
-// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=thin -funified-lto -ffat-lto-objects -emit-llvm < %s | FileCheck %s --check-prefixes=THIN,NOSPLIT,UNIFIED
-
-// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -funified-lto -ffat-lto-objects -fsplit-lto-unit -emit-obj < %s -o %t.full.split.o
+// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -ffat-lto-objects -fsplit-lto-unit -emit-obj < %s -o %t.full.split.o
// RUN: llvm-readelf -S %t.full.split.o | FileCheck %s --check-prefixes=ELF
// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.full.split.bc %t.full.split.o
-// RUN: llvm-dis %t.full.split.bc -o - | FileCheck %s --check-prefixes=THIN,SPLIT,UNIFIED
+// RUN: llvm-dis %t.full.split.bc -o - | FileCheck %s --check-prefixes=FULL,SPLIT,NOUNIFIED
-// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -funified-lto -ffat-lto-objects -emit-obj < %s -o %t.full.nosplit.o
+// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -ffat-lto-objects -emit-obj < %s -o %t.full.nosplit.o
// RUN: llvm-readelf -S %t.full.nosplit.o | FileCheck %s --check-prefixes=ELF
// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.full.nosplit.bc %t.full.nosplit.o
-// RUN: llvm-dis %t.full.nosplit.bc -o - | FileCheck %s --check-prefixes=THIN,NOSPLIT,UNIFIED
+// RUN: llvm-dis %t.full.nosplit.bc -o - | FileCheck %s --check-prefixes=FULL,NOSPLIT,NOUNIFIED
-// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=thin -funified-lto -fsplit-lto-unit -ffat-lto-objects -emit-obj < %s -o %t.thin.split.o
+// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=thin -fsplit-lto-unit -ffat-lto-objects -emit-obj < %s -o %t.thin.split.o
// RUN: llvm-readelf -S %t.thin.split.o | FileCheck %s --check-prefixes=ELF
// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.thin.split.bc %t.thin.split.o
-// RUN: llvm-dis %t.thin.split.bc -o - | FileCheck %s --check-prefixes=THIN,SPLIT,UNIFIED
+// RUN: llvm-dis %t.thin.split.bc -o - | FileCheck %s --check-prefixes=THIN,SPLIT,NOUNIFIED
-// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=thin -funified-lto -ffat-lto-objects -emit-obj < %s -o %t.thin.nosplit.o
+// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=thin -ffat-lto-objects -emit-obj < %s -o %t.thin.nosplit.o
// RUN: llvm-readelf -S %t.thin.nosplit.o | FileCheck %s --check-prefixes=ELF
// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.thin.nosplit.bc %t.thin.nosplit.o
-// RUN: llvm-dis %t.thin.nosplit.bc -o - | FileCheck %s --check-prefixes=THIN,NOSPLIT,UNIFIED
+// RUN: llvm-dis %t.thin.nosplit.bc -o - | FileCheck %s --check-prefixes=THIN,NOSPLIT,NOUNIFIED
+
+// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=thin -funified-lto -ffat-lto-objects -emit-obj < %s -o %t.unified.o
+// RUN: llvm-readelf -S %t.unified.o | FileCheck %s --check-prefixes=ELF
+// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.unified.bc %t.unified.o
+// RUN: llvm-dis %t.unified.bc -o - | FileCheck %s --check-prefixes=THIN,NOSPLIT,UNIFIED
-// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -funified-lto -ffat-lto-objects -fsplit-lto-unit -S < %s -o - \
+// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -ffat-lto-objects -fsplit-lto-unit -S < %s -o - \
// RUN: | FileCheck %s --check-prefixes=ASM
/// Be sure we enable split LTO units correctly under -ffat-lto-objects.
@@ -38,9 +41,8 @@
// FULL-NOT: ![[#]] = !{i32 1, !"ThinLTO", i32 0}
// THIN-NOT: ![[#]] = !{i32 1, !"ThinLTO", i32 0}
-/// FatLTO always uses UnifiedLTO. It's an error if they aren't set together
-// UNIFIED: ![[#]] = !{i32 1, !"UnifiedLTO", i32 1}
-// NO-UNIFIED: error: invalid argument '-ffat-lto-objects' only allowed with '-funified-lto'
+// UNIFIED: ![[#]] = !{i32 1, !"UnifiedLTO", i32 1}
+// NOUNIFIED-NOT: ![[#]] = !{i32 1, !"UnifiedLTO", i32 1}
// ELF: .llvm.lto
diff --git a/clang/test/Driver/fat-lto-objects.c b/clang/test/Driver/fat-lto-objects.c
index 203175d6..97002db 100644
--- a/clang/test/Driver/fat-lto-objects.c
+++ b/clang/test/Driver/fat-lto-objects.c
@@ -1,6 +1,5 @@
// RUN: %clang --target=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC
// CHECK-CC: -cc1
-// CHECK-CC-SAME: -funified-lto
// CHECK-CC-SAME: -emit-obj
// CHECK-CC-SAME: -ffat-lto-objects
@@ -15,21 +14,18 @@
/// When fat LTO is enabled with -S, we expect asm output and -ffat-lto-objects to be passed to cc1.
// RUN: %clang --target=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -### %s -S 2>&1 | FileCheck %s -check-prefix=CHECK-CC-S-LTO
// CHECK-CC-S-LTO: -cc1
-// CHECK-CC-S-LTO-SAME: -funified-lto
// CHECK-CC-S-NOT: -emit-llvm
// CHECK-CC-S-LTO-SAME: -ffat-lto-objects
/// When fat LTO is enabled with -S and -emit-llvm, we expect IR output and -ffat-lto-objects to be passed to cc1.
// RUN: %clang --target=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -### %s -S -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-CC-S-EL-LTO
// CHECK-CC-S-EL-LTO: -cc1
-// CHECK-CC-S-EL-LTO-SAME: -funified-lto
// CHECK-CC-S-EL-LTO-SAME: -emit-llvm
// CHECK-CC-S-EL-LTO-SAME: -ffat-lto-objects
/// When fat LTO is enabled wihtout -S we expect native object output and -ffat-lto-object to be passed to cc1.
// RUN: %clang --target=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC-C-LTO
// CHECK-CC-C-LTO: -cc1
-// CHECK-CC-C-LTO: -funified-lto
// CHECK-CC-C-LTO: -emit-obj
// CHECK-CC-C-LTO: -ffat-lto-objects
@@ -47,13 +43,3 @@
// RUN: -fuse-ld=lld -fno-lto -ffat-lto-objects -### 2>&1 | FileCheck --check-prefix=NOLTO %s
// LTO: "--fat-lto-objects"
// NOLTO-NOT: "--fat-lto-objects"
-
-/// Make sure that incompatible options emit the correct diagnostics, since -ffat-lto-objects requires -funified-lto
-// RUN: %clang -cc1 -triple=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -funified-lto -emit-llvm-only %s 2>&1 | FileCheck %s -check-prefix=UNIFIED --allow-empty
-// UNIFIED-NOT: error:
-
-// RUN: not %clang -cc1 -triple=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -emit-llvm-only %s 2>&1 | FileCheck %s -check-prefix=MISSING_UNIFIED
-// MISSING_UNIFIED: error: invalid argument '-ffat-lto-objects' only allowed with '-funified-lto'
-
-// RUN: not %clang -cc1 -triple=x86_64-unknown-linux-gnu -flto -fno-unified-lto -ffat-lto-objects -emit-llvm-only %s 2>&1 | FileCheck %s -check-prefix=NO-UNIFIED
-// NO-UNIFIED: error: the combination of '-ffat-lto-objects' and '-fno-unified-lto' is incompatible
diff --git a/llvm/docs/FatLTO.rst b/llvm/docs/FatLTO.rst
index 76b849b..5864944 100644
--- a/llvm/docs/FatLTO.rst
+++ b/llvm/docs/FatLTO.rst
@@ -29,9 +29,9 @@ Overview
Within LLVM, FatLTO is supported by choosing the ``FatLTODefaultPipeline``.
This pipeline will:
-#) Run the pre-link UnifiedLTO pipeline on the current module.
+#) Run the pre-link (Thin)LTO pipeline on the current module.
#) Embed the pre-link bitcode in a special ``.llvm.lto`` section.
-#) Finish optimizing the module using the post-link ThinLTO pipeline.
+#) Finish optimizing the module using the ModuleOptimization pipeline.
#) Emit the object file, including the new ``.llvm.lto`` section.
.. NOTE
diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h
index 33cf8af8..7339b8a 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -250,12 +250,9 @@ public:
///
/// This builds a pipeline that runs the LTO/ThinLTO pre-link pipeline, and
/// emits a section containing the pre-link bitcode along side the object code
- /// generated by running the PerModuleDefaultPipeline, used when compiling
- /// without LTO. It clones the module and runs the LTO/non-LTO pipelines
- /// separately to avoid any inconsistencies with an ad-hoc pipeline that tries
- /// to approximate the PerModuleDefaultPipeline from the pre-link LTO
- /// pipelines.
- ModulePassManager buildFatLTODefaultPipeline(OptimizationLevel Level);
+ /// generated in non-LTO compilation.
+ ModulePassManager buildFatLTODefaultPipeline(OptimizationLevel Level,
+ bool ThinLTO, bool EmitSummary);
/// Build a pre-link, ThinLTO-targeting default optimization pipeline to
/// a pass manager.
diff --git a/llvm/include/llvm/Transforms/IPO/EmbedBitcodePass.h b/llvm/include/llvm/Transforms/IPO/EmbedBitcodePass.h
index 2bb7d5f..12bf0dd 100644
--- a/llvm/include/llvm/Transforms/IPO/EmbedBitcodePass.h
+++ b/llvm/include/llvm/Transforms/IPO/EmbedBitcodePass.h
@@ -24,13 +24,25 @@ namespace llvm {
class Module;
class Pass;
+struct EmbedBitcodeOptions {
+ EmbedBitcodeOptions() : EmbedBitcodeOptions(false, false) {}
+ EmbedBitcodeOptions(bool IsThinLTO, bool EmitLTOSummary)
+ : IsThinLTO(IsThinLTO), EmitLTOSummary(EmitLTOSummary) {}
+ bool IsThinLTO;
+ bool EmitLTOSummary;
+};
+
/// Pass embeds a copy of the module optimized with the provided pass pipeline
/// into a global variable.
class EmbedBitcodePass : public PassInfoMixin<EmbedBitcodePass> {
- ModulePassManager MPM;
+ bool IsThinLTO;
+ bool EmitLTOSummary;
public:
- EmbedBitcodePass() {}
+ EmbedBitcodePass(EmbedBitcodeOptions Opts)
+ : EmbedBitcodePass(Opts.IsThinLTO, Opts.EmitLTOSummary) {}
+ EmbedBitcodePass(bool IsThinLTO, bool EmitLTOSummary)
+ : IsThinLTO(IsThinLTO), EmitLTOSummary(EmitLTOSummary) {}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 19fb136..000594f 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -752,6 +752,26 @@ Expected<HWAddressSanitizerOptions> parseHWASanPassOptions(StringRef Params) {
return Result;
}
+Expected<EmbedBitcodeOptions> parseEmbedBitcodePassOptions(StringRef Params) {
+ EmbedBitcodeOptions Result;
+ while (!Params.empty()) {
+ StringRef ParamName;
+ std::tie(ParamName, Params) = Params.split(';');
+
+ if (ParamName == "thinlto") {
+ Result.IsThinLTO = true;
+ } else if (ParamName == "emit-summary") {
+ Result.EmitLTOSummary = true;
+ } else {
+ return make_error<StringError>(
+ formatv("invalid EmbedBitcode pass parameter '{0}' ", ParamName)
+ .str(),
+ inconvertibleErrorCode());
+ }
+ }
+ return Result;
+}
+
Expected<MemorySanitizerOptions> parseMSanPassOptions(StringRef Params) {
MemorySanitizerOptions Result;
while (!Params.empty()) {
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index 525b83d..6ede863 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -1531,14 +1531,17 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
}
ModulePassManager
-PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level) {
+PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level, bool ThinLTO,
+ bool EmitSummary) {
ModulePassManager MPM;
- // FatLTO always uses UnifiedLTO, so use the ThinLTOPreLink pipeline
- MPM.addPass(buildThinLTOPreLinkDefaultPipeline(Level));
- MPM.addPass(EmbedBitcodePass());
+ if (ThinLTO)
+ MPM.addPass(buildThinLTOPreLinkDefaultPipeline(Level));
+ else
+ MPM.addPass(buildLTOPreLinkDefaultPipeline(Level));
+ MPM.addPass(EmbedBitcodePass(ThinLTO, EmitSummary));
- // Use the ThinLTO post-link pipeline with sample profiling, other
- if (PGOOpt && PGOOpt->Action == PGOOptions::SampleUse)
+ // Use the ThinLTO post-link pipeline with sample profiling
+ if (ThinLTO && PGOOpt && PGOOpt->Action == PGOOptions::SampleUse)
MPM.addPass(buildThinLTODefaultPipeline(Level, /*ImportSummary=*/nullptr));
else {
// otherwise, just use module optimization
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 5f25302..e59795c 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -58,7 +58,6 @@ MODULE_PASS("dfsan", DataFlowSanitizerPass())
MODULE_PASS("dot-callgraph", CallGraphDOTPrinterPass())
MODULE_PASS("dxil-upgrade", DXILUpgradePass())
MODULE_PASS("elim-avail-extern", EliminateAvailableExternallyPass())
-MODULE_PASS("embed-bitcode", EmbedBitcodePass())
MODULE_PASS("extract-blocks", BlockExtractorPass({}, false))
MODULE_PASS("forceattrs", ForceFunctionAttrsPass())
MODULE_PASS("function-import", FunctionImportPass())
@@ -162,6 +161,10 @@ MODULE_PASS_WITH_PARAMS(
"no-group-by-use;no-ignore-single-use;no-merge-const;no-merge-external;"
"size-only")
MODULE_PASS_WITH_PARAMS(
+ "embed-bitcode", "EmbedBitcodePass",
+ [](EmbedBitcodeOptions Opts) { return EmbedBitcodePass(Opts); },
+ parseEmbedBitcodePassOptions, "thinlto;emit-summary")
+MODULE_PASS_WITH_PARAMS(
"globaldce", "GlobalDCEPass",
[](bool InLTOPostLink) { return GlobalDCEPass(InLTOPostLink); },
parseGlobalDCEPassOptions, "in-lto-post-link")
diff --git a/llvm/lib/Transforms/IPO/EmbedBitcodePass.cpp b/llvm/lib/Transforms/IPO/EmbedBitcodePass.cpp
index 48ef077..6af3a45 100644
--- a/llvm/lib/Transforms/IPO/EmbedBitcodePass.cpp
+++ b/llvm/lib/Transforms/IPO/EmbedBitcodePass.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/EmbedBitcodePass.h"
+#include "llvm/Bitcode/BitcodeWriter.h"
+#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/ErrorHandling.h"
@@ -16,6 +18,7 @@
#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
+#include <memory>
#include <string>
using namespace llvm;
@@ -30,9 +33,16 @@ PreservedAnalyses EmbedBitcodePass::run(Module &M, ModuleAnalysisManager &AM) {
report_fatal_error(
"EmbedBitcode pass currently only supports ELF object format",
/*gen_crash_diag=*/false);
+
std::string Data;
raw_string_ostream OS(Data);
- ThinLTOBitcodeWriterPass(OS, /*ThinLinkOS=*/nullptr).run(M, AM);
+ if (IsThinLTO)
+ ThinLTOBitcodeWriterPass(OS, /*ThinLinkOS=*/nullptr).run(M, AM);
+ else
+ BitcodeWriterPass(OS, /*ShouldPreserveUseListOrder=*/false, EmitLTOSummary)
+ .run(M, AM);
+
embedBufferInModule(M, MemoryBufferRef(Data, "ModuleData"), ".llvm.lto");
+
return PreservedAnalyses::all();
}
diff --git a/llvm/test/CodeGen/X86/fat-lto-section.ll b/llvm/test/CodeGen/X86/fat-lto-section.ll
index 9a4359b..30c5622 100644
--- a/llvm/test/CodeGen/X86/fat-lto-section.ll
+++ b/llvm/test/CodeGen/X86/fat-lto-section.ll
@@ -1,5 +1,5 @@
;; Ensure that the .llvm.lto section has SHT_EXCLUDE set.
-; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode" -S \
+; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode<thinlto;emit-summary>" -S \
; RUN: | llc --mtriple x86_64-unknown-linux-gnu -filetype=obj \
; RUN: | llvm-readelf - --sections \
; RUN: | FileCheck %s --check-prefix=EXCLUDE
diff --git a/llvm/test/Transforms/EmbedBitcode/embed.ll b/llvm/test/Transforms/EmbedBitcode/embed.ll
index 734bf52..dffb5cf 100644
--- a/llvm/test/Transforms/EmbedBitcode/embed.ll
+++ b/llvm/test/Transforms/EmbedBitcode/embed.ll
@@ -1,4 +1,7 @@
; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode" -S | FileCheck %s
+; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode<thinlto>" -S | FileCheck %s
+; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode<emit-summary>" -S | FileCheck %s
+; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode<thinlto;emit-summary>" -S | FileCheck %s
@a = global i32 1