[clang] c3821b8 - [flang] Add -fpass-plugin option to flang
Tarun Prabhu via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 10 07:08:22 PST 2022
Author: Tarun Prabhu
Date: 2022-11-10T08:03:46-07:00
New Revision: c3821b8d2aacd1d7c0281db1b8db011e1158cf4d
URL: https://github.com/llvm/llvm-project/commit/c3821b8d2aacd1d7c0281db1b8db011e1158cf4d
DIFF: https://github.com/llvm/llvm-project/commit/c3821b8d2aacd1d7c0281db1b8db011e1158cf4d.diff
LOG: [flang] Add -fpass-plugin option to flang
This patch adds the -fpass-plugin option to flang which dynamically loads LLVM
passes from the shared object passed as the argument to the flag. The behavior
of the option is designed to replicate that of the same option in clang and
thus has the same capabilities and limitations.
Features:
Multiple instances of -fpass-plugin=path-to-file can be specified and each
of the files will be loaded in that order.
The flag can be passed to both flang-new and flang-new -fc1.
The flag will be listed when the -help flag is passed to both flang-new and
flang-new -fc1. It will also be listed when the --help-hidden flag is passed.
Limitations:
Dynamically loaded plugins are not supported in clang on Windows and are not
supported in flang either.
Addenda:
Some minor stylistic changes are made in the files that were modified to
enable this functionality. Those changes make the naming of functions more
consistent, but do not change any functionality that is not directly
related to enabling -fpass-plugin.
Differential Revision: https://reviews.llvm.org/D129156
Added:
flang/test/Driver/pass-plugin-not-found.f90
flang/test/Driver/pass-plugin.f90
Modified:
clang/include/clang/Driver/Options.td
clang/lib/Driver/ToolChains/Flang.cpp
clang/lib/Driver/ToolChains/Flang.h
flang/docs/FlangDriver.md
flang/docs/ReleaseNotes.md
flang/include/flang/Frontend/CodeGenOptions.h
flang/lib/Frontend/CompilerInvocation.cpp
flang/lib/Frontend/FrontendActions.cpp
flang/test/CMakeLists.txt
flang/test/Driver/driver-help-hidden.f90
flang/test/Driver/driver-help.f90
flang/test/Driver/frontend-forwarding.f90
Removed:
################################################################################
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index debe038196c06..a501306632afb 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2719,7 +2719,7 @@ def fplugin_arg : Joined<["-"], "fplugin-arg-">,
MetaVarName<"<name>-<arg>">,
HelpText<"Pass <arg> to plugin <name>">;
def fpass_plugin_EQ : Joined<["-"], "fpass-plugin=">,
- Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<dsopath>">,
+ Group<f_Group>, Flags<[CC1Option,FlangOption,FC1Option]>, MetaVarName<"<dsopath>">,
HelpText<"Load pass plugin from a dynamic shared object file (only with new pass manager).">,
MarshallingInfoStringVector<CodeGenOpts<"PassPlugins">>;
defm preserve_as_comments : BoolFOption<"preserve-as-comments",
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index c9016238ee65e..588fabd560009 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -51,15 +51,15 @@ void Flang::addPreprocessingOptions(const ArgList &Args,
options::OPT_I, options::OPT_cpp, options::OPT_nocpp});
}
-void Flang::forwardOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
+void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
Args.AddAllArgs(CmdArgs,
{options::OPT_module_dir, options::OPT_fdebug_module_writer,
options::OPT_fintrinsic_modules_path, options::OPT_pedantic,
options::OPT_std_EQ, options::OPT_W_Joined,
- options::OPT_fconvert_EQ});
+ options::OPT_fconvert_EQ, options::OPT_fpass_plugin_EQ});
}
-void Flang::AddPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
+void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
// ParsePICArgs parses -fPIC/-fPIE and their variants and returns a tuple of
// (RelocationModel, PICLevel, IsPIE).
llvm::Reloc::Model RelocationModel;
@@ -238,13 +238,13 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fcolor-diagnostics");
// -fPIC and related options.
- AddPicOptions(Args, CmdArgs);
+ addPicOptions(Args, CmdArgs);
// Floating point related options
addFloatingPointOptions(D, Args, CmdArgs);
- // Handle options which are simply forwarded to -fc1.
- forwardOptions(Args, CmdArgs);
+ // Add other compile options
+ addOtherOptions(Args, CmdArgs);
// Forward -Xflang arguments to -fc1
Args.AddAllArgValues(CmdArgs, options::OPT_Xflang);
diff --git a/clang/lib/Driver/ToolChains/Flang.h b/clang/lib/Driver/ToolChains/Flang.h
index 4d8e2e8ee5aa9..de72ac3601f96 100644
--- a/clang/lib/Driver/ToolChains/Flang.h
+++ b/clang/lib/Driver/ToolChains/Flang.h
@@ -45,15 +45,16 @@ class LLVM_LIBRARY_VISIBILITY Flang : public Tool {
///
/// \param [in] Args The list of input driver arguments
/// \param [out] CmdArgs The list of output command arguments
- void AddPicOptions(const llvm::opt::ArgList &Args,
+ void addPicOptions(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
- /// This method will effectively copy options from \a Args into \a CmdArgs.
+ /// Extract other compilation options from the driver arguments and add them
+ /// to the command arguments.
///
/// \param [in] Args The list of input driver arguments
/// \param [out] CmdArgs The list of output command arguments
- void forwardOptions(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const;
+ void addOtherOptions(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
public:
Flang(const ToolChain &TC);
diff --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md
index af1fddc8f750a..389bb1cf6cd01 100644
--- a/flang/docs/FlangDriver.md
+++ b/flang/docs/FlangDriver.md
@@ -507,3 +507,28 @@ Lastly, if `ParseTree` modifications are performed, then it might be necessary
to re-analyze expressions and modify scope or symbols. You can check
[Semantics.md](Semantics.md) for more details on how `ParseTree` is edited
e.g. during the semantic checks.
+
+# LLVM Pass Plugins
+
+Pass plugins are dynamic shared objects that consist of one or more LLVM IR
+passes. The `-fpass-plugin` option enables these passes to be passed to the
+middle-end where they are added to the optimization pass pipeline and run after
+lowering to LLVM IR.The exact position of the pass in the pipeline will depend
+on how it has been registered with the `llvm::PassBuilder`. See the
+documentation for
+[`llvm::PassBuilder`](https://llvm.org/doxygen/classllvm_1_1PassBuilder.html)
+for details.
+
+The framework to enable pass plugins in `flang-new` uses the exact same
+machinery as that used by `clang` and thus has the same capabilities and
+limitations.
+
+In order to use a pass plugin, the pass(es) must be compiled into a dynamic
+shared object which is then loaded using the `-fpass-plugin` option.
+
+```
+flang-new -fpass-plugin=/path/to/plugin.so <file.f90>
+```
+
+This option is available in both the compiler driver and the frontend driver.
+Note that LLVM plugins are not officially supported on Windows.
diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md
index fd1db3b00eb83..0cc85db9debc5 100644
--- a/flang/docs/ReleaseNotes.md
+++ b/flang/docs/ReleaseNotes.md
@@ -24,6 +24,10 @@ page](https://llvm.org/releases/).
## Major New Features
+* Flang now supports loading LLVM pass plugins with the `-fpass-plugin` option
+ which is also available in clang. The option mimics the behavior of the
+ corresponding option in clang and has the same capabilities and limitations.
+
## Bug Fixes
## Non-comprehensive list of changes in this release
diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h
index 025f67cd8e177..7bb10d4b0f3c8 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.h
+++ b/flang/include/flang/Frontend/CodeGenOptions.h
@@ -46,6 +46,9 @@ class CodeGenOptionsBase {
class CodeGenOptions : public CodeGenOptionsBase {
public:
+ /// The paths to the pass plugins that were registered using -fpass-plugin.
+ std::vector<std::string> LLVMPassPlugins;
+
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
#define ENUM_CODEGENOPT(Name, Type, Bits, Default) \
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 4ae35762b2bf9..f0f070eab0135 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -125,6 +125,9 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
clang::driver::options::OPT_fno_debug_pass_manager, false))
opts.DebugPassManager = 1;
+ for (auto *a : args.filtered(clang::driver::options::OPT_fpass_plugin_EQ))
+ opts.LLVMPassPlugins.push_back(a->getValue());
+
// -mrelocation-model option.
if (const llvm::opt::Arg *A =
args.getLastArg(clang::driver::options::OPT_mrelocation_model)) {
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 9042332822c8c..40f30a90554e7 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -48,6 +48,7 @@
#include "llvm/IRReader/IRReader.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SourceMgr.h"
@@ -675,6 +676,7 @@ static void generateMachineCodeOrAssemblyImpl(clang::DiagnosticsEngine &diags,
void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
auto opts = getInstance().getInvocation().getCodeGenOpts();
+ auto &diags = getInstance().getDiagnostics();
llvm::OptimizationLevel level = mapToLevel(opts);
// Create the analysis managers.
@@ -691,6 +693,17 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
si.registerCallbacks(pic, &fam);
llvm::PassBuilder pb(tm.get(), pto, pgoOpt, &pic);
+ // Attempt to load pass plugins and register their callbacks with PB.
+ for (auto &pluginFile : opts.LLVMPassPlugins) {
+ auto passPlugin = llvm::PassPlugin::Load(pluginFile);
+ if (passPlugin) {
+ passPlugin->registerPassBuilderCallbacks(pb);
+ } else {
+ diags.Report(clang::diag::err_fe_unable_to_load_plugin)
+ << pluginFile << passPlugin.takeError();
+ }
+ }
+
// Register all the basic analyses with the managers.
pb.registerModuleAnalyses(mam);
pb.registerCGSCCAnalyses(cgam);
diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt
index 7601e1e4c87a4..f31396ad2bc4b 100644
--- a/flang/test/CMakeLists.txt
+++ b/flang/test/CMakeLists.txt
@@ -63,6 +63,9 @@ set(FLANG_TEST_DEPENDS
Fortran_main
FortranDecimal
)
+if (LLVM_ENABLE_PLUGINS AND NOT WIN32)
+ list(APPEND FLANG_TEST_DEPENDS Bye)
+endif()
if (FLANG_INCLUDE_TESTS)
if (FLANG_GTEST_AVAIL)
diff --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90
index 3bce2a57caa1a..e079bb66cfa5c 100644
--- a/flang/test/Driver/driver-help-hidden.f90
+++ b/flang/test/Driver/driver-help-hidden.f90
@@ -48,6 +48,7 @@
! CHECK-NEXT: -fno-signed-zeros Allow optimizations that ignore the sign of floating point zeros
! CHECK-NEXT: -fopenacc Enable OpenACC
! CHECK-NEXT: -fopenmp Parse OpenMP pragmas and generate parallel code.
+! CHECK-NEXT: -fpass-plugin=<dsopath> Load pass plugin from a dynamic shared object file (only with new pass manager).
! CHECK-NEXT: -freciprocal-math Allow division operations to be reassociated
! CHECK-NEXT: -fsyntax-only Run the preprocessor, parser and semantic analysis stages
! CHECK-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV.
@@ -76,4 +77,3 @@
! Frontend driver -help-hidden is not supported
! ERROR-FLANG-FC1: error: unknown argument: '{{.*}}'
-
diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index 8d24deee0b1ad..4f04b85440399 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -46,6 +46,7 @@
! HELP-NEXT: -fno-signed-zeros Allow optimizations that ignore the sign of floating point zeros
! HELP-NEXT: -fopenacc Enable OpenACC
! HELP-NEXT: -fopenmp Parse OpenMP pragmas and generate parallel code.
+! HELP-NEXT: -fpass-plugin=<dsopath> Load pass plugin from a dynamic shared object file (only with new pass manager).
! HELP-NEXT: -freciprocal-math Allow division operations to be reassociated
! HELP-NEXT: -fsyntax-only Run the preprocessor, parser and semantic analysis stages
! HELP-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV.
@@ -129,6 +130,7 @@
! HELP-FC1-NEXT: -fno-signed-zeros Allow optimizations that ignore the sign of floating point zeros
! HELP-FC1-NEXT: -fopenacc Enable OpenACC
! HELP-FC1-NEXT: -fopenmp Parse OpenMP pragmas and generate parallel code.
+! HELP-FC1-NEXT: -fpass-plugin=<dsopath> Load pass plugin from a dynamic shared object file (only with new pass manager).
! HELP-FC1-NEXT: -freciprocal-math Allow division operations to be reassociated
! HELP-FC1-NEXT: -fsyntax-only Run the preprocessor, parser and semantic analysis stages
! HELP-FC1-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV.
diff --git a/flang/test/Driver/frontend-forwarding.f90 b/flang/test/Driver/frontend-forwarding.f90
index 9d1d7cb8d3c88..2c81b518ddd33 100644
--- a/flang/test/Driver/frontend-forwarding.f90
+++ b/flang/test/Driver/frontend-forwarding.f90
@@ -15,6 +15,7 @@
! RUN: -fno-signed-zeros \
! RUN: -fassociative-math \
! RUN: -freciprocal-math \
+! RUN: -fpass-plugin=Bye%pluginext \
! RUN: -mllvm -print-before-all\
! RUN: -P \
! RUN: | FileCheck %s
@@ -33,4 +34,5 @@
! CHECK: "-mreassociate"
! CHECK: "-freciprocal-math"
! CHECK: "-fconvert=little-endian"
-! CHECK: "-mllvm" "-print-before-all"
+! CHECK: "-fpass-plugin=Bye
+! CHECK: "-mllvm" "-print-before-all"
diff --git a/flang/test/Driver/pass-plugin-not-found.f90 b/flang/test/Driver/pass-plugin-not-found.f90
new file mode 100644
index 0000000000000..a93567af64672
--- /dev/null
+++ b/flang/test/Driver/pass-plugin-not-found.f90
@@ -0,0 +1,8 @@
+! Check the correct error diagnostic is reported when a pass plugin shared object isn't found
+
+! REQUIRES: plugins, shell
+
+! RUN: not %flang -fpass-plugin=X.Y %s 2>&1 | FileCheck %s --check-prefix=ERROR
+! RUN: not %flang_fc1 -emit-llvm -o /dev/null -fpass-plugin=X.Y %s 2>&1 | FileCheck %s --check-prefix=ERROR
+
+! ERROR: error: unable to load plugin 'X.Y': 'Could not load library 'X.Y': X.Y: cannot open shared object file: No such file or directory'
diff --git a/flang/test/Driver/pass-plugin.f90 b/flang/test/Driver/pass-plugin.f90
new file mode 100644
index 0000000000000..546bd9237d6b8
--- /dev/null
+++ b/flang/test/Driver/pass-plugin.f90
@@ -0,0 +1,13 @@
+! Verify that the plugin passed to -fpass-plugin is loaded and run
+
+! UNSUPPORTED: system-windows
+
+! REQUIRES: plugins, shell
+
+! RUN: %flang -S %s -fpass-plugin=%llvmshlibdir/Bye%pluginext -Xflang -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s
+! RUN: %flang_fc1 -S %s -fpass-plugin=%llvmshlibdir/Bye%pluginext -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s
+
+! CHECK: Running pass: {{.*}}Bye on empty_
+
+subroutine empty
+end subroutine empty
More information about the cfe-commits
mailing list