[flang-commits] [flang] 0fdfb65 - [Flang] Add support to use LTO specific pipelines
via flang-commits
flang-commits at lists.llvm.org
Thu Mar 9 13:28:33 PST 2023
Author: Nadeem, Usman
Date: 2023-03-09T13:27:43-08:00
New Revision: 0fdfb65e2624aa151cb07a9c842331f7af9a21ca
URL: https://github.com/llvm/llvm-project/commit/0fdfb65e2624aa151cb07a9c842331f7af9a21ca
DIFF: https://github.com/llvm/llvm-project/commit/0fdfb65e2624aa151cb07a9c842331f7af9a21ca.diff
LOG: [Flang] Add support to use LTO specific pipelines
Thin and full LTO modes use different pre-link pipelines compared to
regular compilation. This patch adds support for calling those pipelines.
This patch closely mimics Clang's implementation with the exception that I
changed the codegen option name from `PrepareForLTO` to `PrepareForFullLTO`
to be more precise.
With this patch:
- Compilation for full LTO should be as we expect (except possibly
missing optimizations enabled by module summaries which we do not
produce yet).
- thinLTO uses the correct prelink pipeline but will use the postlink
backend for fullLTO due to missing metadata and summary in the llvm
module. I have added a warning regarding this: `flang-new: warning: the
option '-flto=thin' is a work in progress`.
Differential Revision: https://reviews.llvm.org/D142420
Change-Id: I6b94b775b5b8e93340e520c5cd4bf60834b2e209
Added:
flang/test/Driver/lto-bc.f90
flang/test/Driver/lto-flags.f90
Modified:
clang/include/clang/Driver/Options.td
clang/lib/Driver/ToolChains/Flang.cpp
flang/include/flang/Frontend/CodeGenOptions.def
flang/lib/Frontend/CompilerInvocation.cpp
flang/lib/Frontend/FrontendActions.cpp
flang/test/Driver/default-optimization-pipelines.f90
flang/test/Driver/driver-help-hidden.f90
flang/test/Driver/driver-help.f90
Removed:
################################################################################
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 97b9fdbb31a02..cf7194a855835 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2237,13 +2237,13 @@ def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Gr
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
def fapple_link_rtlib : Flag<["-"], "fapple-link-rtlib">, Group<f_Group>,
HelpText<"Force linking the clang builtins runtime library">;
-def flto_EQ : Joined<["-"], "flto=">, Flags<[CoreOption, CC1Option]>, Group<f_Group>,
+def flto_EQ : Joined<["-"], "flto=">, Flags<[CoreOption, CC1Option, FC1Option, FlangOption]>, Group<f_Group>,
HelpText<"Set LTO mode">, Values<"thin,full">;
def flto_EQ_jobserver : Flag<["-"], "flto=jobserver">, Group<f_Group>,
Alias<flto_EQ>, AliasArgs<["full"]>, HelpText<"Enable LTO in 'full' mode">;
def flto_EQ_auto : Flag<["-"], "flto=auto">, Group<f_Group>,
Alias<flto_EQ>, AliasArgs<["full"]>, HelpText<"Enable LTO in 'full' mode">;
-def flto : Flag<["-"], "flto">, Flags<[CoreOption, CC1Option]>, Group<f_Group>,
+def flto : Flag<["-"], "flto">, Flags<[CoreOption, CC1Option, FC1Option, FlangOption]>, Group<f_Group>,
Alias<flto_EQ>, AliasArgs<["full"]>, HelpText<"Enable LTO in 'full' mode">;
def fno_lto : Flag<["-"], "fno-lto">, Flags<[CoreOption, CC1Option]>, Group<f_Group>,
HelpText<"Disable LTO mode (default)">;
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index b50d2c5c4f8d2..84d93f56a4419 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -252,6 +252,7 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
const Driver &D = TC.getDriver();
ArgStringList CmdArgs;
+ DiagnosticsEngine &Diags = D.getDiags();
// Invoke ourselves in -fc1 mode.
CmdArgs.push_back("-fc1");
@@ -299,9 +300,21 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
// to avoid warn_drv_unused_argument.
Args.getLastArg(options::OPT_fcolor_diagnostics,
options::OPT_fno_color_diagnostics);
- if (D.getDiags().getDiagnosticOptions().ShowColors)
+ if (Diags.getDiagnosticOptions().ShowColors)
CmdArgs.push_back("-fcolor-diagnostics");
+ // LTO mode is parsed by the Clang driver library.
+ LTOKind LTOMode = D.getLTOMode(/* IsOffload */ false);
+ assert(LTOMode != LTOK_Unknown && "Unknown LTO mode.");
+ if (LTOMode == LTOK_Full)
+ CmdArgs.push_back("-flto=full");
+ else if (LTOMode == LTOK_Thin) {
+ Diags.Report(
+ Diags.getCustomDiagID(DiagnosticsEngine::Warning,
+ "the option '-flto=thin' is a work in progress"));
+ CmdArgs.push_back("-flto=thin");
+ }
+
// -fPIC and related options.
addPicOptions(Args, CmdArgs);
diff --git a/flang/include/flang/Frontend/CodeGenOptions.def b/flang/include/flang/Frontend/CodeGenOptions.def
index 7f50442af6d09..c6bd7a5838c48 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.def
+++ b/flang/include/flang/Frontend/CodeGenOptions.def
@@ -24,8 +24,12 @@ CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
///< pass manager.
-CODEGENOPT(PICLevel, 2, 0) ///< PIC level of the LLVM module.
CODEGENOPT(IsPIE, 1, 0) ///< PIE level is the same as PIC Level.
+CODEGENOPT(PICLevel, 2, 0) ///< PIC level of the LLVM module.
+CODEGENOPT(PrepareForFullLTO , 1, 0) ///< Set when -flto is enabled on the
+ ///< compile step.
+CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the
+ ///< compile step.
CODEGENOPT(StackArrays, 1, 0) ///< -fstack-arrays (enable the stack-arrays pass)
CODEGENOPT(Underscoring, 1, 1)
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index d0434444df3d7..6e963e2528101 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -139,35 +139,47 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
args.filtered(clang::driver::options::OPT_fembed_offload_object_EQ))
opts.OffloadObjects.push_back(a->getValue());
+ // -flto=full/thin option.
+ if (const llvm::opt::Arg *a =
+ args.getLastArg(clang::driver::options::OPT_flto_EQ)) {
+ llvm::StringRef s = a->getValue();
+ assert((s == "full" || s == "thin") && "Unknown LTO mode.");
+ if (s == "full")
+ opts.PrepareForFullLTO = true;
+ else
+ opts.PrepareForThinLTO = true;
+ }
+
// -mrelocation-model option.
- if (const llvm::opt::Arg *A =
+ if (const llvm::opt::Arg *a =
args.getLastArg(clang::driver::options::OPT_mrelocation_model)) {
- llvm::StringRef ModelName = A->getValue();
- auto RM = llvm::StringSwitch<std::optional<llvm::Reloc::Model>>(ModelName)
- .Case("static", llvm::Reloc::Static)
- .Case("pic", llvm::Reloc::PIC_)
- .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC)
- .Case("ropi", llvm::Reloc::ROPI)
- .Case("rwpi", llvm::Reloc::RWPI)
- .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI)
- .Default(std::nullopt);
- if (RM.has_value())
- opts.setRelocationModel(*RM);
+ llvm::StringRef modelName = a->getValue();
+ auto relocModel =
+ llvm::StringSwitch<std::optional<llvm::Reloc::Model>>(modelName)
+ .Case("static", llvm::Reloc::Static)
+ .Case("pic", llvm::Reloc::PIC_)
+ .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC)
+ .Case("ropi", llvm::Reloc::ROPI)
+ .Case("rwpi", llvm::Reloc::RWPI)
+ .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI)
+ .Default(std::nullopt);
+ if (relocModel.has_value())
+ opts.setRelocationModel(*relocModel);
else
diags.Report(clang::diag::err_drv_invalid_value)
- << A->getAsString(args) << ModelName;
+ << a->getAsString(args) << modelName;
}
// -pic-level and -pic-is-pie option.
- if (int PICLevel = getLastArgIntValue(
+ if (int picLevel = getLastArgIntValue(
args, clang::driver::options::OPT_pic_level, 0, diags)) {
- if (PICLevel > 2)
+ if (picLevel > 2)
diags.Report(clang::diag::err_drv_invalid_value)
<< args.getLastArg(clang::driver::options::OPT_pic_level)
->getAsString(args)
- << PICLevel;
+ << picLevel;
- opts.PICLevel = PICLevel;
+ opts.PICLevel = picLevel;
if (args.hasArg(clang::driver::options::OPT_pic_is_pie))
opts.IsPIE = 1;
}
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index d6c06e4c370d0..3cf0b5f968068 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -727,7 +727,12 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
// Create the pass manager.
llvm::ModulePassManager mpm;
if (opts.OptimizationLevel == 0)
- mpm = pb.buildO0DefaultPipeline(level, false);
+ mpm = pb.buildO0DefaultPipeline(level, opts.PrepareForFullLTO ||
+ opts.PrepareForThinLTO);
+ else if (opts.PrepareForFullLTO)
+ mpm = pb.buildLTOPreLinkDefaultPipeline(level);
+ else if (opts.PrepareForThinLTO)
+ mpm = pb.buildThinLTOPreLinkDefaultPipeline(level);
else
mpm = pb.buildPerModuleDefaultPipeline(level);
diff --git a/flang/test/Driver/default-optimization-pipelines.f90 b/flang/test/Driver/default-optimization-pipelines.f90
index 8a6ea57bdab33..08e407f73da5c 100644
--- a/flang/test/Driver/default-optimization-pipelines.f90
+++ b/flang/test/Driver/default-optimization-pipelines.f90
@@ -1,10 +1,18 @@
! Verify that`-O{n}` is indeed taken into account when defining the LLVM optimization/middle-end pass pipeline.
! RUN: %flang -S -O0 %s -Xflang -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O0
+! RUN: %flang -S -O0 %s -flto -Xflang -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O0-ANYLTO
+! RUN: %flang -S -O0 %s -flto=thin -Xflang -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O0-ANYLTO
! RUN: %flang_fc1 -S -O0 %s -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O0
+! RUN: %flang_fc1 -S -O0 %s -flto=full -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O0-ANYLTO
+! RUN: %flang_fc1 -S -O0 %s -flto=thin -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O0-ANYLTO
! RUN: %flang -S -O2 %s -Xflang -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O2
+! RUN: %flang -S -O2 %s -flto -Xflang -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O2-LTO
+! RUN: %flang -S -O2 %s -flto=thin -Xflang -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O2-THINLTO
! RUN: %flang_fc1 -S -O2 %s -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O2
+! RUN: %flang_fc1 -S -O2 %s -flto=full -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O2-LTO
+! RUN: %flang_fc1 -S -O2 %s -flto=thin -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O2-THINLTO
! Verify that only the left-most `-O{n}` is used
! RUN: %flang -S -O2 -O0 %s -Xflang -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O0
@@ -12,9 +20,19 @@
! CHECK-O0-NOT: Running pass: SimplifyCFGPass on simple_loop_
! CHECK-O0: Running analysis: TargetLibraryAnalysis on simple_loop_
+! CHECK-O0-ANYLTO: Running pass: CanonicalizeAliasesPass on [module]
+! CHECK-O0-ANYLTO: Running pass: NameAnonGlobalPass on [module]
! CHECK-O2: Running pass: SimplifyCFGPass on simple_loop_
+! CHECK-O2-LTO-NOT: Running pass: EliminateAvailableExternallyPass
+! CHECK-O2-LTO: Running pass: CanonicalizeAliasesPass on [module]
+! CHECK-O2-LTO: Running pass: NameAnonGlobalPass on [module]
+
+! CHECK-O2-THINLTO-NOT: Running pass: LoopVectorizePass
+! CHECK-O2-THINLTO: Running pass: CanonicalizeAliasesPass on [module]
+! CHECK-O2-THINLTO: Running pass: NameAnonGlobalPass on [module]
+
subroutine simple_loop
integer :: i
do i=1,5
diff --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90
index 18666ae2c6214..bcb77c9f8bccb 100644
--- a/flang/test/Driver/driver-help-hidden.f90
+++ b/flang/test/Driver/driver-help-hidden.f90
@@ -43,6 +43,8 @@
! CHECK-NEXT: Enable support for generating executables (experimental)
! CHECK-NEXT: -flarge-sizes Use INTEGER(KIND=8) for the result type in size-related intrinsics
! CHECK-NEXT: -flogical-abbreviations Enable logical abbreviations
+! CHECK-NEXT: -flto=<value> Set LTO mode
+! CHECK-NEXT: -flto Enable LTO in 'full' mode
! CHECK-NEXT: -fno-automatic Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE
! CHECK-NEXT: -fno-color-diagnostics Disable colors in diagnostics
! CHECK-NEXT: -fno-integrated-as Disable the integrated assembler
diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index ca5d7cf42a3c3..7bafcc6f5991d 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -41,6 +41,8 @@
! HELP-NEXT: Specify where to find the compiled intrinsic modules
! HELP-NEXT: -flarge-sizes Use INTEGER(KIND=8) for the result type in size-related intrinsics
! HELP-NEXT: -flogical-abbreviations Enable logical abbreviations
+! HELP-NEXT: -flto=<value> Set LTO mode
+! HELP-NEXT: -flto Enable LTO in 'full' mode
! HELP-NEXT: -fno-automatic Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE
! HELP-NEXT: -fno-color-diagnostics Disable colors in diagnostics
! HELP-NEXT: -fno-integrated-as Disable the integrated assembler
@@ -130,6 +132,8 @@
! HELP-FC1-NEXT: Specify where to find the compiled intrinsic modules
! HELP-FC1-NEXT: -flarge-sizes Use INTEGER(KIND=8) for the result type in size-related intrinsics
! HELP-FC1-NEXT: -flogical-abbreviations Enable logical abbreviations
+! HELP-FC1-NEXT: -flto=<value> Set LTO mode
+! HELP-FC1-NEXT: -flto Enable LTO in 'full' mode
! HELP-FC1-NEXT: -fno-analyzed-objects-for-unparse
! HELP-FC1-NEXT: Do not use the analyzed objects when unparsing
! HELP-FC1-NEXT: -fno-automatic Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE
diff --git a/flang/test/Driver/lto-bc.f90 b/flang/test/Driver/lto-bc.f90
new file mode 100644
index 0000000000000..5e34cdb87c5b1
--- /dev/null
+++ b/flang/test/Driver/lto-bc.f90
@@ -0,0 +1,21 @@
+! Test that the output is LLVM bitcode for LTO and not a native objectfile by
+! disassembling it to LLVM IR.
+! Right now there is nothing special about it and it is similar to non-lto IR,
+! more work is needed to add things like module summaries.
+
+! RUN: %flang %s -c -o - | not llvm-dis -o %t
+! RUN: %flang_fc1 %s -emit-llvm-bc -o - | llvm-dis -o - | FileCheck %s
+
+! RUN: %flang -flto %s -c -o - | llvm-dis -o - | FileCheck %s
+! RUN: %flang -flto=thin %s -c -o - | llvm-dis -o - | FileCheck %s
+
+! CHECK: define void @_QQmain()
+! CHECK-NEXT: ret void
+! CHECK-NEXT: }
+
+! CHECK-NOT: ^0 = module:
+! CHECK-NOT: ^1 = gv: (name:
+! CHECK-NOT: ^2 = flags:
+! CHECK-NOT: ^3 = blockcount:
+
+end program
diff --git a/flang/test/Driver/lto-flags.f90 b/flang/test/Driver/lto-flags.f90
new file mode 100644
index 0000000000000..5c69f79d35216
--- /dev/null
+++ b/flang/test/Driver/lto-flags.f90
@@ -0,0 +1,32 @@
+! UNSUPPORTED: system-windows
+! RUN: %flang -### -S %s 2>&1 | FileCheck %s --check-prefix=NO-LTO
+! RUN: %flang -### -S -fno-lto %s 2>&1 | FileCheck %s --check-prefix=NO-LTO
+
+! Full LTO and aliases.
+! RUN: %flang -### -S -flto %s 2>&1 | FileCheck %s --check-prefix=FULL-LTO
+! RUN: %flang -### -S -flto=full %s 2>&1 | FileCheck %s --check-prefix=FULL-LTO
+! RUN: %flang -### -S -flto=auto %s 2>&1 | FileCheck %s --check-prefix=FULL-LTO
+! RUN: %flang -### -S -flto=jobserver %s 2>&1 | FileCheck %s --check-prefix=FULL-LTO
+
+! Also check linker plugin opt for Thin LTO
+! RUN: %flang -### -flto=thin %s 2>&1 | FileCheck %s --check-prefix=THIN-LTO
+
+! RUN: %flang -### -S -flto=somelto %s 2>&1 | FileCheck %s --check-prefix=ERROR
+
+! FC1 tests. Check that it does not crash.
+! RUN: %flang_fc1 -S %s -flto -o /dev/null
+! RUN: %flang_fc1 -S %s -flto=full -o /dev/null
+! RUN: %flang_fc1 -S %s -flto=thin -o /dev/null
+
+! NO-LTO: "-fc1"
+! NO-LTO-NOT: flto
+
+! FULL-LTO: "-fc1"
+! FULL-LTO-SAME: "-flto=full"
+
+! THIN-LTO: flang-new: warning: the option '-flto=thin' is a work in progress
+! THIN-LTO: "-fc1"
+! THIN-LTO-SAME: "-flto=thin"
+! THIN-LTO: "-plugin-opt=thinlto"
+
+! ERROR: error: unsupported argument 'somelto' to option '-flto=
More information about the flang-commits
mailing list