[flang-commits] [flang] [flang] Add the MLIR pass pipelines for dumping (PR #183144)

via flang-commits flang-commits at lists.llvm.org
Fri Apr 17 06:00:35 PDT 2026


https://github.com/tmjbios updated https://github.com/llvm/llvm-project/pull/183144

>From 50a6975a6e0d99323f2bc83d95ac7d19937c7feb Mon Sep 17 00:00:00 2001
From: Ted Johnson <tedmjohnson at protonmail.com>
Date: Tue, 24 Feb 2026 13:32:41 -0600
Subject: [PATCH 1/7] [flang] Add the MLIR pipelines for dumping

The flang driver never registered passes in the MLIR pass registry, so
--mlir-print-ir-before=<pass> always failed with `Cannot find option`.

This commit adds pass registration calls before CLI option parsing in the
-mmlir handler such that all ~30 pipeline passes are now selectable.
---
 flang/docs/Overview.md                        | 47 +++++++++++++++++++
 flang/lib/FrontendTool/CMakeLists.txt         | 11 +++++
 .../ExecuteCompilerInvocation.cpp             | 24 ++++++++++
 3 files changed, 82 insertions(+)

diff --git a/flang/docs/Overview.md b/flang/docs/Overview.md
index 77ed21c021f8a..3a92a2cb1faff 100644
--- a/flang/docs/Overview.md
+++ b/flang/docs/Overview.md
@@ -182,6 +182,53 @@ LLVM IR representation of the program.
 **Commands:**
   - `flang -mmlir --mlir-print-ir-after-all -S src.f90` dumps the FIR code after each pass to standard error
   - `flang -fc1 -emit-llvm src.f90` dumps the LLVM IR to src.ll
+  - `flang -mmlir --mlir-print-ir-before=<pass> -S src.f90` dumps the FIR code before a specific pass to standard error
+  - `flang -mmlir --mlir-print-ir-after=<pass> -S src.f90` dumps the FIR code after a specific pass to standard error
+
+The following pass names are valid arguments to `--mlir-print-ir-before=` and
+`--mlir-print-ir-after=` (listed in pipeline order):
+
+| Pass name | Description |
+|---|---|
+| `inline-elementals` | Inline elemental functions |
+| `lower-hlfir-ordered-assignments` | Lower HLFIR ordered assignments |
+| `lower-hlfir-intrinsics` | Lower HLFIR intrinsics |
+| `bufferize-hlfir` | Bufferize HLFIR |
+| `convert-hlfir-to-fir` | Convert HLFIR to FIR |
+| `cse` | Common subexpression elimination |
+| `array-value-copy` | Array value copy |
+| `character-conversion` | Character conversion |
+| `canonicalize` | Canonicalize |
+| `simplify-region-lite` | Simplify region (lite) |
+| `stack-arrays` | Convert heap allocations to stack allocations (requires `-fstack-arrays`) |
+| `inline` | Inliner |
+| `fir-polymorphic-op` | Polymorphic operation conversion |
+| `fir-assumed-rank-op` | Assumed rank operation conversion |
+| `lower-repack-arrays` | Lower repack arrays |
+| `simplify-fir-operations` | Simplify FIR operations |
+| `stack-reclaim` | Stack reclaim |
+| `cfg-conversion` | CFG conversion |
+| `convert-scf-to-cf` | Convert SCF to control flow |
+| `convert-complex-pow` | Convert complex power operations |
+| `mif-convert` | MIF conversion |
+| `boxed-procedure` | Boxed procedure conversion |
+| `abstract-result` | Abstract result optimization |
+| `cg-rewrite` | Code generation rewrite |
+| `external-name-interop` | External name interop conversion |
+| `target-rewrite` | Target rewrite |
+| `compiler-generated-names` | Compiler generated names conversion |
+| `function-attr` | Function attributes |
+| `fir-to-llvm-ir` | FIR to LLVM IR lowering |
+| `convert-math-to-funcs` | Convert math operations to function calls |
+| `convert-complex-to-standard` | Convert complex operations to standard |
+| `convert-math-to-llvm` | Convert math operations to LLVM |
+| `llvm-add-comdats` | Add COMDAT sections |
+| `reconcile-unrealized-casts` | Reconcile unrealized casts |
+
+Note: The exact set of passes depends on compilation options.  For example,
+`stack-arrays` only appears when `-fstack-arrays` is enabled.  To see the
+complete list for a given compilation, use `--mlir-print-ir-before-all` and
+look at the `IR Dump Before` headers.
 
 ## Object code generation and linking
 
diff --git a/flang/lib/FrontendTool/CMakeLists.txt b/flang/lib/FrontendTool/CMakeLists.txt
index 666fab1a6e2c0..05c740f46e564 100644
--- a/flang/lib/FrontendTool/CMakeLists.txt
+++ b/flang/lib/FrontendTool/CMakeLists.txt
@@ -8,6 +8,10 @@ add_flang_library(flangFrontendTool
 
   LINK_LIBS
   flangFrontend
+  FIRCodeGen
+  FIRTransforms
+  HLFIRTransforms
+  FlangOpenMPTransforms
 
   LINK_COMPONENTS
   Option
@@ -15,7 +19,14 @@ add_flang_library(flangFrontendTool
   Support
 
   MLIR_LIBS
+  MLIRComplexToStandard
+  MLIRLLVMIRTransforms
+  MLIRMathToFuncs
+  MLIRMathToLLVM
   MLIRPass
+  MLIRReconcileUnrealizedCasts
+  MLIRSCFToControlFlow
+  MLIRTransforms
 
   CLANG_LIBS
   clangBasic
diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 429a98416daf1..e0c19a95e16a3 100644
--- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -18,10 +18,17 @@
 #include "flang/Frontend/CompilerInstance.h"
 #include "flang/Frontend/FrontendActions.h"
 #include "flang/Frontend/FrontendPluginRegistry.h"
+#include "flang/Optimizer/CodeGen/CodeGen.h"
+#include "flang/Optimizer/HLFIR/Passes.h"
+#include "flang/Optimizer/OpenMP/Passes.h"
+#include "flang/Optimizer/Transforms/Passes.h"
 
 #include "mlir/IR/AsmState.h"
 #include "mlir/IR/MLIRContext.h"
 #include "mlir/Pass/PassManager.h"
+#include "mlir/Conversion/Passes.h"
+#include "mlir/Dialect/LLVMIR/Transforms/Passes.h"
+#include "mlir/Transforms/Passes.h"
 #include "clang/Basic/DiagnosticFrontend.h"
 #include "clang/Options/Options.h"
 #include "llvm/Option/OptTable.h"
@@ -207,6 +214,23 @@ bool executeCompilerInvocation(CompilerInstance *flang) {
 
   // Honor -mmlir. This should happen AFTER plugins have been loaded!
   if (!flang->getFrontendOpts().mlirArgs.empty()) {
+    // Register MLIR and FIR passes so that --mlir-print-ir-before=<pass> works.
+    // This must happen BEFORE registerPassManagerCLOptions() because that
+    // function creates the PassNameCLParser which snapshots the pass registry
+    // during initialization.
+    mlir::registerCSEPass();
+    mlir::registerCanonicalizerPass();
+    mlir::registerInlinerPass();
+    mlir::registerSCFToControlFlowPass();
+    mlir::registerConvertMathToFuncs();
+    mlir::registerConvertComplexToStandardPass();
+    mlir::registerConvertMathToLLVMPass();
+    mlir::LLVM::registerLLVMAddComdats();
+    mlir::registerReconcileUnrealizedCastsPass();
+    fir::registerOptCodeGenPasses();
+    fir::registerOptTransformPasses();
+    hlfir::registerHLFIRPasses();
+    flangomp::registerFlangOpenMPPasses();
     mlir::registerMLIRContextCLOptions();
     mlir::registerPassManagerCLOptions();
     mlir::registerAsmPrinterCLOptions();

>From 15e2afef82a74099a4639f23f68a6753b7470519 Mon Sep 17 00:00:00 2001
From: tedj <tedmjohnson at protonmail.com>
Date: Tue, 24 Feb 2026 12:42:29 -0700
Subject: [PATCH 2/7] Update ExecuteCompilerInvocation.cpp

clang-format fix
---
 flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index e0c19a95e16a3..7b6279f6f2629 100644
--- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -23,11 +23,11 @@
 #include "flang/Optimizer/OpenMP/Passes.h"
 #include "flang/Optimizer/Transforms/Passes.h"
 
+#include "mlir/Conversion/Passes.h"
+#include "mlir/Dialect/LLVMIR/Transforms/Passes.h"
 #include "mlir/IR/AsmState.h"
 #include "mlir/IR/MLIRContext.h"
 #include "mlir/Pass/PassManager.h"
-#include "mlir/Conversion/Passes.h"
-#include "mlir/Dialect/LLVMIR/Transforms/Passes.h"
 #include "mlir/Transforms/Passes.h"
 #include "clang/Basic/DiagnosticFrontend.h"
 #include "clang/Options/Options.h"

>From 0142586be73b29ac0a962cdf53ae909631e324f9 Mon Sep 17 00:00:00 2001
From: Ted Johnson <tedmjohnson at protonmail.com>
Date: Tue, 24 Feb 2026 16:58:14 -0600
Subject: [PATCH 3/7] [flang] Add test for new pass dumper(s)

---
 flang/test/Driver/mmlir-print-ir-before.f90 | 8 ++++++++
 1 file changed, 8 insertions(+)
 create mode 100644 flang/test/Driver/mmlir-print-ir-before.f90

diff --git a/flang/test/Driver/mmlir-print-ir-before.f90 b/flang/test/Driver/mmlir-print-ir-before.f90
new file mode 100644
index 0000000000000..3914a4c7e2ef7
--- /dev/null
+++ b/flang/test/Driver/mmlir-print-ir-before.f90
@@ -0,0 +1,8 @@
+! Verify that --mlir-print-ir-before=<pass> works for registered passes.
+
+! RUN: %flang_fc1 -emit-llvm -mmlir --mlir-print-ir-before=cse -o /dev/null %s 2>&1 | FileCheck %s
+
+! CHECK: IR Dump Before CSE
+! CHECK: func.func @_QQmain
+
+end program

>From c15571dd8c33c3cb6567007a16a982bfc405b4ea Mon Sep 17 00:00:00 2001
From: "Ted M. Johnson" <tedmjohnson at protonmail.com>
Date: Wed, 25 Feb 2026 20:21:13 -0700
Subject: [PATCH 4/7] [flang] Remove pass description table from Overview

---
 flang/docs/Overview.md | 42 +-----------------------------------------
 1 file changed, 1 insertion(+), 41 deletions(-)

diff --git a/flang/docs/Overview.md b/flang/docs/Overview.md
index 3a92a2cb1faff..64df20efd1895 100644
--- a/flang/docs/Overview.md
+++ b/flang/docs/Overview.md
@@ -180,51 +180,11 @@ perform various optimizations and transformations.  The final pass creates an
 LLVM IR representation of the program.
 
 **Commands:**
-  - `flang -mmlir --mlir-print-ir-after-all -S src.f90` dumps the FIR code after each pass to standard error
   - `flang -fc1 -emit-llvm src.f90` dumps the LLVM IR to src.ll
+  - `flang -mmlir --mlir-print-ir-after-all -S src.f90` dumps the FIR code after each pass to standard error
   - `flang -mmlir --mlir-print-ir-before=<pass> -S src.f90` dumps the FIR code before a specific pass to standard error
   - `flang -mmlir --mlir-print-ir-after=<pass> -S src.f90` dumps the FIR code after a specific pass to standard error
 
-The following pass names are valid arguments to `--mlir-print-ir-before=` and
-`--mlir-print-ir-after=` (listed in pipeline order):
-
-| Pass name | Description |
-|---|---|
-| `inline-elementals` | Inline elemental functions |
-| `lower-hlfir-ordered-assignments` | Lower HLFIR ordered assignments |
-| `lower-hlfir-intrinsics` | Lower HLFIR intrinsics |
-| `bufferize-hlfir` | Bufferize HLFIR |
-| `convert-hlfir-to-fir` | Convert HLFIR to FIR |
-| `cse` | Common subexpression elimination |
-| `array-value-copy` | Array value copy |
-| `character-conversion` | Character conversion |
-| `canonicalize` | Canonicalize |
-| `simplify-region-lite` | Simplify region (lite) |
-| `stack-arrays` | Convert heap allocations to stack allocations (requires `-fstack-arrays`) |
-| `inline` | Inliner |
-| `fir-polymorphic-op` | Polymorphic operation conversion |
-| `fir-assumed-rank-op` | Assumed rank operation conversion |
-| `lower-repack-arrays` | Lower repack arrays |
-| `simplify-fir-operations` | Simplify FIR operations |
-| `stack-reclaim` | Stack reclaim |
-| `cfg-conversion` | CFG conversion |
-| `convert-scf-to-cf` | Convert SCF to control flow |
-| `convert-complex-pow` | Convert complex power operations |
-| `mif-convert` | MIF conversion |
-| `boxed-procedure` | Boxed procedure conversion |
-| `abstract-result` | Abstract result optimization |
-| `cg-rewrite` | Code generation rewrite |
-| `external-name-interop` | External name interop conversion |
-| `target-rewrite` | Target rewrite |
-| `compiler-generated-names` | Compiler generated names conversion |
-| `function-attr` | Function attributes |
-| `fir-to-llvm-ir` | FIR to LLVM IR lowering |
-| `convert-math-to-funcs` | Convert math operations to function calls |
-| `convert-complex-to-standard` | Convert complex operations to standard |
-| `convert-math-to-llvm` | Convert math operations to LLVM |
-| `llvm-add-comdats` | Add COMDAT sections |
-| `reconcile-unrealized-casts` | Reconcile unrealized casts |
-
 Note: The exact set of passes depends on compilation options.  For example,
 `stack-arrays` only appears when `-fstack-arrays` is enabled.  To see the
 complete list for a given compilation, use `--mlir-print-ir-before-all` and

>From 60e867b9d11e07b56ccf23f02f0285ce7a3e9114 Mon Sep 17 00:00:00 2001
From: Ted Johnson <tedmjohnson at protonmail.com>
Date: Thu, 26 Feb 2026 08:31:47 -0600
Subject: [PATCH 5/7] [flang] Expand test to cover both -before and -after

---
 flang/test/Driver/mmlir-print-ir-before.f90 |  8 --------
 flang/test/Driver/mmlir-print-ir.f90        | 13 +++++++++++++
 2 files changed, 13 insertions(+), 8 deletions(-)
 delete mode 100644 flang/test/Driver/mmlir-print-ir-before.f90
 create mode 100644 flang/test/Driver/mmlir-print-ir.f90

diff --git a/flang/test/Driver/mmlir-print-ir-before.f90 b/flang/test/Driver/mmlir-print-ir-before.f90
deleted file mode 100644
index 3914a4c7e2ef7..0000000000000
--- a/flang/test/Driver/mmlir-print-ir-before.f90
+++ /dev/null
@@ -1,8 +0,0 @@
-! Verify that --mlir-print-ir-before=<pass> works for registered passes.
-
-! RUN: %flang_fc1 -emit-llvm -mmlir --mlir-print-ir-before=cse -o /dev/null %s 2>&1 | FileCheck %s
-
-! CHECK: IR Dump Before CSE
-! CHECK: func.func @_QQmain
-
-end program
diff --git a/flang/test/Driver/mmlir-print-ir.f90 b/flang/test/Driver/mmlir-print-ir.f90
new file mode 100644
index 0000000000000..140fef10710cf
--- /dev/null
+++ b/flang/test/Driver/mmlir-print-ir.f90
@@ -0,0 +1,13 @@
+! Verify that --mlir-print-ir-before=<pass> and --mlir-print-ir-after=<pass>
+! work for registered passes.
+
+! RUN: %flang_fc1 -emit-llvm -mmlir --mlir-print-ir-before=cse -o /dev/null %s 2>&1 | FileCheck %s --check-prefix=BEFORE
+! RUN: %flang_fc1 -emit-llvm -mmlir --mlir-print-ir-after=cse -o /dev/null %s 2>&1 | FileCheck %s --check-prefix=AFTER
+
+! BEFORE: IR Dump Before CSE
+! BEFORE: func.func @_QQmain
+
+! AFTER: IR Dump After CSE
+! AFTER: func.func @_QQmain
+
+end program

>From 5e5997b528ca734fcec4347a980d29709e5ac40f Mon Sep 17 00:00:00 2001
From: "Ted M. Johnson" <tedmjohnson at protonmail.com>
Date: Fri, 27 Feb 2026 13:46:50 -0700
Subject: [PATCH 6/7] [flang] Commonize the mmlir dump pass additions with
 fir-opt

Move the setup of the MLIR pipeline passes to initFIR
and share them with fir-opt.
---
 .../include/flang/Optimizer/Support/InitFIR.h | 31 +++++++++++++++++++
 .../ExecuteCompilerInvocation.cpp             | 22 ++-----------
 flang/tools/fir-opt/CMakeLists.txt            |  5 +++
 flang/tools/fir-opt/fir-opt.cpp               |  5 +--
 4 files changed, 39 insertions(+), 24 deletions(-)

diff --git a/flang/include/flang/Optimizer/Support/InitFIR.h b/flang/include/flang/Optimizer/Support/InitFIR.h
index d77d82feddd84..45cf86bdf494f 100644
--- a/flang/include/flang/Optimizer/Support/InitFIR.h
+++ b/flang/include/flang/Optimizer/Support/InitFIR.h
@@ -13,13 +13,17 @@
 #ifndef FORTRAN_OPTIMIZER_SUPPORT_INITFIR_H
 #define FORTRAN_OPTIMIZER_SUPPORT_INITFIR_H
 
+#include "flang/Optimizer/CodeGen/CodeGen.h"
 #include "flang/Optimizer/Dialect/CUF/CUFDialect.h"
 #include "flang/Optimizer/Dialect/CUF/CUFToLLVMIRTranslation.h"
 #include "flang/Optimizer/Dialect/FIRDialect.h"
 #include "flang/Optimizer/Dialect/MIF/MIFDialect.h"
 #include "flang/Optimizer/HLFIR/HLFIRDialect.h"
+#include "flang/Optimizer/HLFIR/Passes.h"
 #include "flang/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.h"
+#include "flang/Optimizer/OpenMP/Passes.h"
 #include "flang/Optimizer/OpenMP/Support/RegisterOpenMPExtensions.h"
+#include "flang/Optimizer/Transforms/Passes.h"
 #include "mlir/Conversion/Passes.h"
 #include "mlir/Dialect/Affine/IR/AffineOps.h"
 #include "mlir/Dialect/Affine/Transforms/Passes.h"
@@ -31,6 +35,7 @@
 #include "mlir/Dialect/Index/IR/IndexDialect.h"
 #include "mlir/Dialect/LLVMIR/NVVMDialect.h"
 #include "mlir/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.h"
+#include "mlir/Dialect/LLVMIR/Transforms/Passes.h"
 #include "mlir/Dialect/Math/IR/Math.h"
 #include "mlir/Dialect/OpenACC/OpenACC.h"
 #include "mlir/Dialect/OpenACC/Transforms/Passes.h"
@@ -133,6 +138,32 @@ inline void registerMLIRPassesForFortranTools() {
   mlir::registerLowerAffinePass();
 }
 
+/// Register the passes used in flang's MLIR pass pipeline so that
+/// --mlir-print-ir-before=<pass> and --mlir-print-ir-after=<pass> work.
+/// This must be called BEFORE mlir::registerPassManagerCLOptions() because
+/// that function creates the PassNameCLParser which snapshots the pass
+/// registry during initialization.
+inline void registerFlangPipelinePasses() {
+  // MLIR core passes used in the pipeline.
+  mlir::registerCSEPass();
+  mlir::registerCanonicalizerPass();
+  mlir::registerInlinerPass();
+
+  // MLIR conversion passes used in the pipeline.
+  mlir::registerSCFToControlFlowPass();
+  mlir::registerConvertMathToFuncs();
+  mlir::registerConvertComplexToStandardPass();
+  mlir::registerConvertMathToLLVMPass();
+  mlir::LLVM::registerLLVMAddComdats();
+  mlir::registerReconcileUnrealizedCastsPass();
+
+  // FIR, HLFIR, and OpenMP passes.
+  fir::registerOptCodeGenPasses();
+  fir::registerOptTransformPasses();
+  hlfir::registerHLFIRPasses();
+  flangomp::registerFlangOpenMPPasses();
+}
+
 /// Register the interfaces needed to lower to LLVM IR.
 void registerLLVMTranslation(mlir::MLIRContext &context);
 
diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 7b6279f6f2629..a73b27b9ff9a6 100644
--- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -18,17 +18,11 @@
 #include "flang/Frontend/CompilerInstance.h"
 #include "flang/Frontend/FrontendActions.h"
 #include "flang/Frontend/FrontendPluginRegistry.h"
-#include "flang/Optimizer/CodeGen/CodeGen.h"
-#include "flang/Optimizer/HLFIR/Passes.h"
-#include "flang/Optimizer/OpenMP/Passes.h"
-#include "flang/Optimizer/Transforms/Passes.h"
+#include "flang/Optimizer/Support/InitFIR.h"
 
-#include "mlir/Conversion/Passes.h"
-#include "mlir/Dialect/LLVMIR/Transforms/Passes.h"
 #include "mlir/IR/AsmState.h"
 #include "mlir/IR/MLIRContext.h"
 #include "mlir/Pass/PassManager.h"
-#include "mlir/Transforms/Passes.h"
 #include "clang/Basic/DiagnosticFrontend.h"
 #include "clang/Options/Options.h"
 #include "llvm/Option/OptTable.h"
@@ -218,19 +212,7 @@ bool executeCompilerInvocation(CompilerInstance *flang) {
     // This must happen BEFORE registerPassManagerCLOptions() because that
     // function creates the PassNameCLParser which snapshots the pass registry
     // during initialization.
-    mlir::registerCSEPass();
-    mlir::registerCanonicalizerPass();
-    mlir::registerInlinerPass();
-    mlir::registerSCFToControlFlowPass();
-    mlir::registerConvertMathToFuncs();
-    mlir::registerConvertComplexToStandardPass();
-    mlir::registerConvertMathToLLVMPass();
-    mlir::LLVM::registerLLVMAddComdats();
-    mlir::registerReconcileUnrealizedCastsPass();
-    fir::registerOptCodeGenPasses();
-    fir::registerOptTransformPasses();
-    hlfir::registerHLFIRPasses();
-    flangomp::registerFlangOpenMPPasses();
+    fir::support::registerFlangPipelinePasses();
     mlir::registerMLIRContextCLOptions();
     mlir::registerPassManagerCLOptions();
     mlir::registerAsmPrinterCLOptions();
diff --git a/flang/tools/fir-opt/CMakeLists.txt b/flang/tools/fir-opt/CMakeLists.txt
index e735c2c2ff1a3..e76f4ba3aed1a 100644
--- a/flang/tools/fir-opt/CMakeLists.txt
+++ b/flang/tools/fir-opt/CMakeLists.txt
@@ -49,4 +49,9 @@ mlir_target_link_libraries(fir-opt PRIVATE
   MLIRSupport
   MLIRVectorToLLVM
   MLIROptLib
+  MLIRComplexToStandard
+  MLIRLLVMIRTransforms
+  MLIRMathToFuncs
+  MLIRMathToLLVM
+  MLIRReconcileUnrealizedCasts
 )
diff --git a/flang/tools/fir-opt/fir-opt.cpp b/flang/tools/fir-opt/fir-opt.cpp
index 67d07eee1f4fc..be55bac9d787f 100644
--- a/flang/tools/fir-opt/fir-opt.cpp
+++ b/flang/tools/fir-opt/fir-opt.cpp
@@ -37,10 +37,7 @@ void registerTestOpenACC();
 
 int main(int argc, char **argv) {
   fir::support::registerMLIRPassesForFortranTools();
-  fir::registerOptCodeGenPasses();
-  fir::registerOptTransformPasses();
-  hlfir::registerHLFIRPasses();
-  flangomp::registerFlangOpenMPPasses();
+  fir::support::registerFlangPipelinePasses();
   fir::acc::registerFIROpenACCPasses();
 #ifdef FLANG_INCLUDE_TESTS
   fir::test::registerTestFIRAliasAnalysisPass();

>From 977be051b54fc06108d3daff46682f7b326f20a5 Mon Sep 17 00:00:00 2001
From: "Ted M. Johnson" <tedmjohnson at protonmail.com>
Date: Tue, 14 Apr 2026 06:47:52 -0600
Subject: [PATCH 7/7] [flang] Move registerFlangPipelinePasses to flangPasses
 library

Address PR comment: move registerFlangPipelinePasses() from InitFIR.h
to flangPasses.

Add a fir-opt LIT test to verify FIR/HLFIR-specific passes are
recognized by --mlir-print-ir-before/after.
---
 .../flang/Optimizer/Passes/Pipelines.h        |  4 +++
 .../include/flang/Optimizer/Support/InitFIR.h | 31 -------------------
 flang/lib/FrontendTool/CMakeLists.txt         | 12 +------
 .../ExecuteCompilerInvocation.cpp             |  9 ++----
 flang/lib/Optimizer/Passes/CMakeLists.txt     |  4 +++
 flang/lib/Optimizer/Passes/Pipelines.cpp      | 28 +++++++++++++++++
 flang/test/Fir/print-ir-pass.fir              | 15 +++++++++
 flang/tools/fir-opt/CMakeLists.txt            |  6 +---
 flang/tools/fir-opt/fir-opt.cpp               |  3 +-
 9 files changed, 58 insertions(+), 54 deletions(-)
 create mode 100644 flang/test/Fir/print-ir-pass.fir

diff --git a/flang/include/flang/Optimizer/Passes/Pipelines.h b/flang/include/flang/Optimizer/Passes/Pipelines.h
index 04eca81daf05e..63fbdc37073b2 100644
--- a/flang/include/flang/Optimizer/Passes/Pipelines.h
+++ b/flang/include/flang/Optimizer/Passes/Pipelines.h
@@ -117,6 +117,10 @@ void addLLVMDialectToLLVMPass(mlir::PassManager &pm, llvm::raw_ostream &output);
 /// Use inliner extension point callback to register the default inliner pass.
 void registerDefaultInlinerPass(MLIRToLLVMPassPipelineConfig &config);
 
+/// Register the passes used in Flang's MLIR pass pipeline
+/// e.g. --mlir-print-ir-before=<pass> and similar.
+void registerFlangPipelinePasses();
+
 /// Create a pass pipeline for running default optimization passes for
 /// incremental conversion of FIR.
 ///
diff --git a/flang/include/flang/Optimizer/Support/InitFIR.h b/flang/include/flang/Optimizer/Support/InitFIR.h
index 45cf86bdf494f..d77d82feddd84 100644
--- a/flang/include/flang/Optimizer/Support/InitFIR.h
+++ b/flang/include/flang/Optimizer/Support/InitFIR.h
@@ -13,17 +13,13 @@
 #ifndef FORTRAN_OPTIMIZER_SUPPORT_INITFIR_H
 #define FORTRAN_OPTIMIZER_SUPPORT_INITFIR_H
 
-#include "flang/Optimizer/CodeGen/CodeGen.h"
 #include "flang/Optimizer/Dialect/CUF/CUFDialect.h"
 #include "flang/Optimizer/Dialect/CUF/CUFToLLVMIRTranslation.h"
 #include "flang/Optimizer/Dialect/FIRDialect.h"
 #include "flang/Optimizer/Dialect/MIF/MIFDialect.h"
 #include "flang/Optimizer/HLFIR/HLFIRDialect.h"
-#include "flang/Optimizer/HLFIR/Passes.h"
 #include "flang/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.h"
-#include "flang/Optimizer/OpenMP/Passes.h"
 #include "flang/Optimizer/OpenMP/Support/RegisterOpenMPExtensions.h"
-#include "flang/Optimizer/Transforms/Passes.h"
 #include "mlir/Conversion/Passes.h"
 #include "mlir/Dialect/Affine/IR/AffineOps.h"
 #include "mlir/Dialect/Affine/Transforms/Passes.h"
@@ -35,7 +31,6 @@
 #include "mlir/Dialect/Index/IR/IndexDialect.h"
 #include "mlir/Dialect/LLVMIR/NVVMDialect.h"
 #include "mlir/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.h"
-#include "mlir/Dialect/LLVMIR/Transforms/Passes.h"
 #include "mlir/Dialect/Math/IR/Math.h"
 #include "mlir/Dialect/OpenACC/OpenACC.h"
 #include "mlir/Dialect/OpenACC/Transforms/Passes.h"
@@ -138,32 +133,6 @@ inline void registerMLIRPassesForFortranTools() {
   mlir::registerLowerAffinePass();
 }
 
-/// Register the passes used in flang's MLIR pass pipeline so that
-/// --mlir-print-ir-before=<pass> and --mlir-print-ir-after=<pass> work.
-/// This must be called BEFORE mlir::registerPassManagerCLOptions() because
-/// that function creates the PassNameCLParser which snapshots the pass
-/// registry during initialization.
-inline void registerFlangPipelinePasses() {
-  // MLIR core passes used in the pipeline.
-  mlir::registerCSEPass();
-  mlir::registerCanonicalizerPass();
-  mlir::registerInlinerPass();
-
-  // MLIR conversion passes used in the pipeline.
-  mlir::registerSCFToControlFlowPass();
-  mlir::registerConvertMathToFuncs();
-  mlir::registerConvertComplexToStandardPass();
-  mlir::registerConvertMathToLLVMPass();
-  mlir::LLVM::registerLLVMAddComdats();
-  mlir::registerReconcileUnrealizedCastsPass();
-
-  // FIR, HLFIR, and OpenMP passes.
-  fir::registerOptCodeGenPasses();
-  fir::registerOptTransformPasses();
-  hlfir::registerHLFIRPasses();
-  flangomp::registerFlangOpenMPPasses();
-}
-
 /// Register the interfaces needed to lower to LLVM IR.
 void registerLLVMTranslation(mlir::MLIRContext &context);
 
diff --git a/flang/lib/FrontendTool/CMakeLists.txt b/flang/lib/FrontendTool/CMakeLists.txt
index 05c740f46e564..323d2e73e9a36 100644
--- a/flang/lib/FrontendTool/CMakeLists.txt
+++ b/flang/lib/FrontendTool/CMakeLists.txt
@@ -8,10 +8,7 @@ add_flang_library(flangFrontendTool
 
   LINK_LIBS
   flangFrontend
-  FIRCodeGen
-  FIRTransforms
-  HLFIRTransforms
-  FlangOpenMPTransforms
+  flangPasses
 
   LINK_COMPONENTS
   Option
@@ -19,14 +16,7 @@ add_flang_library(flangFrontendTool
   Support
 
   MLIR_LIBS
-  MLIRComplexToStandard
-  MLIRLLVMIRTransforms
-  MLIRMathToFuncs
-  MLIRMathToLLVM
   MLIRPass
-  MLIRReconcileUnrealizedCasts
-  MLIRSCFToControlFlow
-  MLIRTransforms
 
   CLANG_LIBS
   clangBasic
diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index a73b27b9ff9a6..a807b86eaaa63 100644
--- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -18,7 +18,7 @@
 #include "flang/Frontend/CompilerInstance.h"
 #include "flang/Frontend/FrontendActions.h"
 #include "flang/Frontend/FrontendPluginRegistry.h"
-#include "flang/Optimizer/Support/InitFIR.h"
+#include "flang/Optimizer/Passes/Pipelines.h"
 
 #include "mlir/IR/AsmState.h"
 #include "mlir/IR/MLIRContext.h"
@@ -208,11 +208,8 @@ bool executeCompilerInvocation(CompilerInstance *flang) {
 
   // Honor -mmlir. This should happen AFTER plugins have been loaded!
   if (!flang->getFrontendOpts().mlirArgs.empty()) {
-    // Register MLIR and FIR passes so that --mlir-print-ir-before=<pass> works.
-    // This must happen BEFORE registerPassManagerCLOptions() because that
-    // function creates the PassNameCLParser which snapshots the pass registry
-    // during initialization.
-    fir::support::registerFlangPipelinePasses();
+    fir::registerFlangPipelinePasses(); // Must be called before
+                                        // mlir::registerPassManagerCLOptions()
     mlir::registerMLIRContextCLOptions();
     mlir::registerPassManagerCLOptions();
     mlir::registerAsmPrinterCLOptions();
diff --git a/flang/lib/Optimizer/Passes/CMakeLists.txt b/flang/lib/Optimizer/Passes/CMakeLists.txt
index 1c19a5765aff1..3b0cbf99fb61f 100644
--- a/flang/lib/Optimizer/Passes/CMakeLists.txt
+++ b/flang/lib/Optimizer/Passes/CMakeLists.txt
@@ -18,6 +18,10 @@ add_flang_library(flangPasses
   MLIR_LIBS
   ${dialect_libs}
   ${extension_libs}
+  MLIRComplexToStandard
+  MLIRLLVMIRTransforms
+  MLIRMathToFuncs
+  MLIRMathToLLVM
   MLIRPass
   MLIRReconcileUnrealizedCasts
   MLIRSCFToControlFlow
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 73e647a1c3956..7d4fb1ed77f93 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -10,6 +10,8 @@
 /// common to flang and the test tools.
 
 #include "flang/Optimizer/Passes/Pipelines.h"
+#include "mlir/Conversion/Passes.h"
+#include "mlir/Dialect/LLVMIR/Transforms/Passes.h"
 #include "llvm/Support/CommandLine.h"
 
 /// Force setting the no-alias attribute on fuction arguments when possible.
@@ -459,4 +461,30 @@ void createMLIRToLLVMPassPipeline(mlir::PassManager &pm,
   });
 }
 
+/// Register the passes used in flang's MLIR pass pipeline so that
+/// --mlir-print-ir-before=<pass> and --mlir-print-ir-after=<pass> work.
+/// Must be called BEFORE mlir::registerPassManagerCLOptions() because
+/// that function creates the PassNameCLParser which snapshots the pass
+/// registry during initialization.
+void registerFlangPipelinePasses() {
+  // MLIR core passes used in the pipeline.
+  mlir::registerCSEPass();
+  mlir::registerCanonicalizerPass();
+  mlir::registerInlinerPass();
+
+  // MLIR conversion passes used in the pipeline.
+  mlir::registerSCFToControlFlowPass();
+  mlir::registerConvertMathToFuncs();
+  mlir::registerConvertComplexToStandardPass();
+  mlir::registerConvertMathToLLVMPass();
+  mlir::LLVM::registerLLVMAddComdats();
+  mlir::registerReconcileUnrealizedCastsPass();
+
+  // FIR, HLFIR, and OpenMP passes.
+  fir::registerOptCodeGenPasses();
+  fir::registerOptTransformPasses();
+  hlfir::registerHLFIRPasses();
+  flangomp::registerFlangOpenMPPasses();
+}
+
 } // namespace fir
diff --git a/flang/test/Fir/print-ir-pass.fir b/flang/test/Fir/print-ir-pass.fir
new file mode 100644
index 0000000000000..6c308570a2935
--- /dev/null
+++ b/flang/test/Fir/print-ir-pass.fir
@@ -0,0 +1,15 @@
+// Verify that --mlir-print-ir-before and --mlir-print-ir-after work in fir-opt
+// for FIR/HLFIR-specific passes registered by registerFlangPipelinePasses().
+
+// RUN: fir-opt --convert-hlfir-to-fir --mlir-print-ir-before=convert-hlfir-to-fir %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=BEFORE
+// RUN: fir-opt --convert-hlfir-to-fir --mlir-print-ir-after=convert-hlfir-to-fir %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=AFTER
+
+// BEFORE: IR Dump Before ConvertHLFIRtoFIR
+// BEFORE: func.func @dummy()
+
+// AFTER: IR Dump After ConvertHLFIRtoFIR
+// AFTER: func.func @dummy()
+
+func.func @dummy() {
+  return
+}
diff --git a/flang/tools/fir-opt/CMakeLists.txt b/flang/tools/fir-opt/CMakeLists.txt
index e76f4ba3aed1a..2697f74c2f0b8 100644
--- a/flang/tools/fir-opt/CMakeLists.txt
+++ b/flang/tools/fir-opt/CMakeLists.txt
@@ -28,6 +28,7 @@ target_link_libraries(fir-opt PRIVATE
   FlangOpenMPTransforms
   FIRAnalysis
   MIFDialect
+  flangPasses
   ${test_libs}
 )
 
@@ -49,9 +50,4 @@ mlir_target_link_libraries(fir-opt PRIVATE
   MLIRSupport
   MLIRVectorToLLVM
   MLIROptLib
-  MLIRComplexToStandard
-  MLIRLLVMIRTransforms
-  MLIRMathToFuncs
-  MLIRMathToLLVM
-  MLIRReconcileUnrealizedCasts
 )
diff --git a/flang/tools/fir-opt/fir-opt.cpp b/flang/tools/fir-opt/fir-opt.cpp
index be55bac9d787f..de959142a5e13 100644
--- a/flang/tools/fir-opt/fir-opt.cpp
+++ b/flang/tools/fir-opt/fir-opt.cpp
@@ -16,6 +16,7 @@
 #include "flang/Optimizer/HLFIR/Passes.h"
 #include "flang/Optimizer/OpenACC/Passes.h"
 #include "flang/Optimizer/OpenMP/Passes.h"
+#include "flang/Optimizer/Passes/Pipelines.h"
 #include "flang/Optimizer/Support/InitFIR.h"
 #include "flang/Optimizer/Transforms/Passes.h"
 
@@ -37,7 +38,7 @@ void registerTestOpenACC();
 
 int main(int argc, char **argv) {
   fir::support::registerMLIRPassesForFortranTools();
-  fir::support::registerFlangPipelinePasses();
+  fir::registerFlangPipelinePasses();
   fir::acc::registerFIROpenACCPasses();
 #ifdef FLANG_INCLUDE_TESTS
   fir::test::registerTestFIRAliasAnalysisPass();



More information about the flang-commits mailing list