[clang] 43fe6f7 - [flang] Add -fpass-plugin option to Flang frontend

Tarun Prabhu via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 4 16:09:32 PDT 2022


Author: Tarun Prabhu
Date: 2022-10-04T17:02:45-06:00
New Revision: 43fe6f7cc35ded691bbc2fa844086d321e705d46

URL: https://github.com/llvm/llvm-project/commit/43fe6f7cc35ded691bbc2fa844086d321e705d46
DIFF: https://github.com/llvm/llvm-project/commit/43fe6f7cc35ded691bbc2fa844086d321e705d46.diff

LOG: [flang] Add -fpass-plugin option to Flang frontend

Add 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.

- 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.

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
    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/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 0b795184b7bd0..f09025d34346c 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2710,7 +2710,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 b279529a33184..9fe83ed0886b4 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -55,7 +55,8 @@ 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_std_EQ, options::OPT_W_Joined,
+                   options::OPT_fpass_plugin_EQ});
 }
 
 void Flang::AddPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const {

diff  --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md
index af1fddc8f750a..b44f44efc93fa 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 0ad63b06dd1bd..b00a2a3d399f8 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 be91a790c26f5..d1c1ec10563d6 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -46,6 +46,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"
@@ -660,6 +661,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.
@@ -676,6 +678,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/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90
index 8261620a2259e..3ee13fc2108af 100644
--- a/flang/test/Driver/driver-help-hidden.f90
+++ b/flang/test/Driver/driver-help-hidden.f90
@@ -44,6 +44,7 @@
 ! CHECK-NEXT: -fno-integrated-as     Disable the integrated assembler
 ! 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: -fsyntax-only          Run the preprocessor, parser and semantic analysis stages
 ! CHECK-NEXT: -fxor-operator         Enable .XOR. as a synonym of .NEQV.
 ! CHECK-NEXT: -help     Display available options
@@ -71,4 +72,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 99201e03ce771..e3a38072be7bc 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -42,6 +42,7 @@
 ! HELP-NEXT: -fno-integrated-as      Disable the integrated assembler
 ! 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: -fsyntax-only          Run the preprocessor, parser and semantic analysis stages
 ! HELP-NEXT: -fxor-operator         Enable .XOR. as a synonym of .NEQV.
 ! HELP-NEXT: -help                  Display available options
@@ -120,6 +121,7 @@
 ! HELP-FC1-NEXT: -fno-reformat          Dump the cooked character stream in -E mode
 ! 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: -fsyntax-only          Run the preprocessor, parser and semantic analysis stages
 ! HELP-FC1-NEXT: -fxor-operator         Enable .XOR. as a synonym of .NEQV.
 ! HELP-FC1-NEXT: -help                  Display available options

diff  --git a/flang/test/Driver/frontend-forwarding.f90 b/flang/test/Driver/frontend-forwarding.f90
index 14d7985c98984..bdf0c31d41f69 100644
--- a/flang/test/Driver/frontend-forwarding.f90
+++ b/flang/test/Driver/frontend-forwarding.f90
@@ -7,6 +7,7 @@
 ! RUN:     -fdefault-integer-8 \
 ! RUN:     -fdefault-real-8 \
 ! RUN:     -flarge-sizes \
+! RUN:     -fpass-plugin=Bye%pluginext \
 ! RUN:     -mllvm -print-before-all\
 ! RUN:     -P \
 ! RUN:   | FileCheck %s
@@ -17,4 +18,5 @@
 ! CHECK: "-fdefault-integer-8"
 ! CHECK: "-fdefault-real-8"
 ! CHECK: "-flarge-sizes"
-! 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