diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -162,6 +162,7 @@ ///< compile step. CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole ///< program vtable opt). +CODEGENOPT(FatLTO, 1, 0) ///< Set when -ffat-lto-objects is enabled. CODEGENOPT(EnableSplitLTOUnit, 1, 0) ///< Enable LTO unit splitting to support /// CFI and traditional whole program /// devirtualization that require whole diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2265,6 +2265,11 @@ Flags<[CoreOption, CC1Option]>, Group, HelpText<"Write minimized bitcode to for the ThinLTO thin link only">, MarshallingInfoString>; +defm fat_lto_objects : BoolFOption<"fat-lto-objects", + CodeGenOpts<"FatLTO">, DefaultFalse, + PosFlag, + NegFlag, + BothFlags<[CC1Option], "">>; def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, Group, Flags<[NoXarchOption, CoreOption]>; defm merge_all_constants : BoolFOption<"merge-all-constants", @@ -4923,7 +4928,6 @@ defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group; defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group; defm default_inline : BooleanFFlag<"default-inline">, Group; -defm fat_lto_objects : BooleanFFlag<"fat-lto-objects">, Group; defm float_store : BooleanFFlag<"float-store">, Group; defm friend_injection : BooleanFFlag<"friend-injection">, Group; defm function_attribute_list : BooleanFFlag<"function-attribute-list">, Group; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -24,6 +24,7 @@ #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Bitcode/BitcodeWriterPass.h" +#include "llvm/Bitcode/EmbedBitcodePass.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" @@ -991,7 +992,11 @@ MPM.addPass(InstrProfiling(*Options, false)); }); - if (IsThinLTO) { + if (CodeGenOpts.FatLTO) { + MPM = PB.buildFatLTODefaultPipeline( + Level, IsThinLTO, CodeGenOpts.EmitLLVMUseLists, + IsThinLTO || shouldEmitRegularLTOSummary()); + } else if (IsThinLTO) { MPM = PB.buildThinLTOPreLinkDefaultPipeline(Level); } else if (IsLTO) { MPM = PB.buildLTOPreLinkDefaultPipeline(Level); @@ -1049,6 +1054,13 @@ } } + if (CodeGenOpts.FatLTO) { + // Set EnableSplitLTOUnit, since the config above won't + if (!TheModule->getModuleFlag("EnableSplitLTOUnit")) + TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", + uint32_t(CodeGenOpts.EnableSplitLTOUnit)); + } + // Now that we have all of the passes ready, run them. { PrettyStackTraceString CrashInfo("Optimizer"); diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -4641,8 +4641,13 @@ } case phases::Backend: { if (isUsingLTO() && TargetDeviceOffloadKind == Action::OFK_None) { - types::ID Output = - Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; + types::ID Output; + if (Args.hasArg(options::OPT_S)) + Output = types::TY_LTO_IR; + else if (Args.hasArg(options::OPT_ffat_lto_objects)) + Output = types::TY_PP_Asm; + else + Output = types::TY_LTO_BC; return C.MakeAction(Input, Output); } if (isUsingLTO(/* IsOffload */ true) && diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7262,6 +7262,14 @@ } } + if (IsUsingLTO && Args.getLastArg(options::OPT_ffat_lto_objects)) { + assert(LTOMode == LTOK_Full || LTOMode == LTOK_Thin); + CmdArgs.push_back(Args.MakeArgString( + Twine("-flto=") + (LTOMode == LTOK_Thin ? "thin" : "full"))); + CmdArgs.push_back("-flto-unit"); + CmdArgs.push_back("-ffat-lto-objects"); + } + if (Args.hasArg(options::OPT_forder_file_instrumentation)) { CmdArgs.push_back("-forder-file-instrumentation"); // Enable order file instrumentation when ThinLTO is not on. When ThinLTO is diff --git a/clang/test/CodeGen/embed-lto-fatlto.c b/clang/test/CodeGen/embed-lto-fatlto.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/embed-lto-fatlto.c @@ -0,0 +1,9 @@ +// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -S -flto=full -ffat-lto-objects -emit-llvm < %s | FileCheck %s +// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -S -flto=full -ffat-lto-objects -emit-llvm < %s | FileCheck %s +// +// CHECK: !{{[0-9]+}} = !{i32 1, !"ThinLTO", i32 0} +// CHECK: !{{[0-9]+}} = !{i32 1, !"EnableSplitLTOUnit", i32 1} + +int test(void) { + return 0xabcd; +} diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c --- a/clang/test/Driver/clang_f_opts.c +++ b/clang/test/Driver/clang_f_opts.c @@ -421,7 +421,6 @@ // CHECK-WARNING-DAG: optimization flag '-fwhole-program' is not supported // CHECK-WARNING-DAG: optimization flag '-fcaller-saves' is not supported // CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported -// CHECK-WARNING-DAG: optimization flag '-ffat-lto-objects' is not supported // CHECK-WARNING-DAG: optimization flag '-fmerge-constants' is not supported // CHECK-WARNING-DAG: optimization flag '-finline-small-functions' is not supported // CHECK-WARNING-DAG: optimization flag '-ftree-dce' is not supported diff --git a/clang/test/Driver/fatlto-objects.c b/clang/test/Driver/fatlto-objects.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/fatlto-objects.c @@ -0,0 +1,10 @@ +// REQUIRES: x86_64-linux +// RUN: %clang -target x86_64-unknown-linux-gnu -flto -ffat-lto-objects -fintegrated-as -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC +// CHECK-CC: -cc1 +// CHECK-CC: -emit-obj +// CHECK-CC: -ffat-lto-objects + +// RUN: %clang -target x86_64-unknown-linux-gnu -ffat-lto-objects -fintegrated-as -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC-NOLTO +// CHECK-CC-NOLTO: -cc1 +// CHECK-CC-NOLTO: -emit-obj +// CHECK-CC-NOLTO-NOT: -ffat-lto-objects