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

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.
This commit is contained in:
tedj 2026-04-23 08:19:22 -06:00 committed by GitHub
parent a88516baa7
commit c32d2d1f29
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 84 additions and 8 deletions

View file

@ -180,8 +180,15 @@ 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
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

View file

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

View file

@ -8,6 +8,7 @@ add_flang_library(flangFrontendTool
LINK_LIBS
flangFrontend
flangPasses
LINK_COMPONENTS
Option

View file

@ -18,6 +18,7 @@
#include "flang/Frontend/CompilerInstance.h"
#include "flang/Frontend/FrontendActions.h"
#include "flang/Frontend/FrontendPluginRegistry.h"
#include "flang/Optimizer/Passes/Pipelines.h"
#include "mlir/IR/AsmState.h"
#include "mlir/IR/MLIRContext.h"
@ -207,6 +208,8 @@ bool executeCompilerInvocation(CompilerInstance *flang) {
// Honor -mmlir. This should happen AFTER plugins have been loaded!
if (!flang->getFrontendOpts().mlirArgs.empty()) {
fir::registerFlangPipelinePasses(); // Must be called before
// mlir::registerPassManagerCLOptions()
mlir::registerMLIRContextCLOptions();
mlir::registerPassManagerCLOptions();
mlir::registerAsmPrinterCLOptions();

View file

@ -7,6 +7,7 @@ add_flang_library(flangPasses
LINK_LIBS
FIRCodeGen
FIROpenACCTransforms
FIRTransforms
FlangOpenMPTransforms
FortranSupport
@ -18,6 +19,10 @@ add_flang_library(flangPasses
MLIR_LIBS
${dialect_libs}
${extension_libs}
MLIRComplexToStandard
MLIRLLVMIRTransforms
MLIRMathToFuncs
MLIRMathToLLVM
MLIRPass
MLIRReconcileUnrealizedCasts
MLIRSCFToControlFlow

View file

@ -10,6 +10,9 @@
/// common to flang and the test tools.
#include "flang/Optimizer/Passes/Pipelines.h"
#include "flang/Optimizer/OpenACC/Passes.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 +462,31 @@ 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();
fir::acc::registerFIROpenACCPasses();
}
} // namespace fir

View file

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

View file

@ -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
}

View file

@ -28,6 +28,7 @@ target_link_libraries(fir-opt PRIVATE
FlangOpenMPTransforms
FIRAnalysis
MIFDialect
flangPasses
${test_libs}
)

View file

@ -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,11 +38,7 @@ void registerTestOpenACC();
int main(int argc, char **argv) {
fir::support::registerMLIRPassesForFortranTools();
fir::registerOptCodeGenPasses();
fir::registerOptTransformPasses();
hlfir::registerHLFIRPasses();
flangomp::registerFlangOpenMPPasses();
fir::acc::registerFIROpenACCPasses();
fir::registerFlangPipelinePasses();
#ifdef FLANG_INCLUDE_TESTS
fir::test::registerTestFIRAliasAnalysisPass();
fir::test::registerTestFIROpenACCInterfacesPass();
@ -52,6 +49,6 @@ int main(int argc, char **argv) {
fir::support::registerDialects(registry);
registry.insert<mlir::memref::MemRefDialect>();
fir::support::addFIRExtensions(registry);
return failed(MlirOptMain(argc, argv, "FIR modular optimizer driver\n",
registry));
return failed(
MlirOptMain(argc, argv, "FIR modular optimizer driver\n", registry));
}