Skip to content

[flang][fir] Add affine optimization pass pipeline. #138627

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flang/include/flang/Optimizer/Passes/CommandLineOpts.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ extern llvm::cl::opt<bool> disableCfgConversion;
extern llvm::cl::opt<bool> disableFirAvc;
extern llvm::cl::opt<bool> disableFirMao;

extern llvm::cl::opt<bool> enableAffineOpt;
extern llvm::cl::opt<bool> disableFirAliasTags;
extern llvm::cl::opt<bool> useOldAliasTags;

Expand Down
3 changes: 3 additions & 0 deletions flang/include/flang/Optimizer/Passes/Pipelines.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
#include "flang/Optimizer/Passes/CommandLineOpts.h"
#include "flang/Optimizer/Transforms/Passes.h"
#include "flang/Tools/CrossToolHelpers.h"
#include "mlir/Conversion/AffineToStandard/AffineToStandard.h"
#include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h"
#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
#include "mlir/Conversion/SCFToOpenMP/SCFToOpenMP.h"
#include "mlir/Dialect/Affine/Passes.h"
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/Pass/PassManager.h"
Expand Down
1 change: 1 addition & 0 deletions flang/lib/Optimizer/Passes/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ add_flang_library(flangPasses
MLIRPass
MLIRReconcileUnrealizedCasts
MLIRSCFToControlFlow
MLIRSCFToOpenMP
MLIRSupport
MLIRTransforms
)
1 change: 1 addition & 0 deletions flang/lib/Optimizer/Passes/CommandLineOpts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ cl::opt<bool> useOldAliasTags(
cl::desc("Use a single TBAA tree for all functions and do not use "
"the FIR alias tags pass"),
cl::init(false), cl::Hidden);
EnableOption(AffineOpt, "affine-opt", "affine optimization");

/// CodeGen Passes
DisableOption(CodeGenRewrite, "codegen-rewrite", "rewrite FIR for codegen");
Expand Down
20 changes: 20 additions & 0 deletions flang/lib/Optimizer/Passes/Pipelines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,26 @@ void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm,
if (pc.AliasAnalysis && !disableFirAliasTags && !useOldAliasTags)
pm.addPass(fir::createAddAliasTags());

// We can first convert the FIR dialect to the Affine dialect, perform
// optimizations on top of it, and then lower it to the FIR dialect.
// TODO: These optimization passes (e.g., PromoteToAffinePass) are currently
// experimental, so it's important to actively identify and address issues.
if (enableAffineOpt && pc.OptLevel.isOptimizingForSpeed()) {
pm.addPass(fir::createPromoteToAffinePass());
pm.addPass(mlir::createCSEPass());
pm.addPass(mlir::affine::createAffineLoopInvariantCodeMotionPass());
pm.addPass(mlir::affine::createAffineLoopNormalizePass());
pm.addPass(mlir::affine::createSimplifyAffineStructuresPass());
pm.addPass(mlir::affine::createAffineParallelize(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is AffineParallelize specific for parallelizing to multiple threads or is it also applicable for single-thread transformations as well?

mlir::affine::AffineParallelizeOptions{1, false}));
pm.addPass(fir::createAffineDemotionPass());
pm.addPass(mlir::createLowerAffinePass());
if (pc.EnableOpenMP) {
pm.addPass(mlir::createConvertSCFToOpenMPPass());
pm.addPass(mlir::createCanonicalizerPass());
}
}

addNestedPassToAllTopLevelOperations<PassConstructor>(
pm, fir::createStackReclaim);
// convert control flow to CFG form
Expand Down
14 changes: 14 additions & 0 deletions flang/test/Driver/mlir-pass-pipeline.f90
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
! -O0 is the default:
! RUN: %flang_fc1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -O0 -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL %s
! RUN: %flang_fc1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -O2 -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,O2 %s
! RUN: %flang_fc1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline -mllvm --enable-affine-opt %s -O2 -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,O2,AFFINE %s

! REQUIRES: asserts

Expand Down Expand Up @@ -105,6 +106,19 @@
! ALL-NEXT: SimplifyFIROperations
! O2-NEXT: AddAliasTags

! AFFINE-NEXT: 'func.func' Pipeline
! AFFINE-NEXT: AffineDialectPromotion
! AFFINE-NEXT: CSE
! AFFINE-NEXT: (S) 0 num-cse'd - Number of operations CSE'd
! AFFINE-NEXT: (S) 0 num-dce'd - Number of operations DCE'd
! AFFINE-NEXT: 'func.func' Pipeline
! AFFINE-NEXT: AffineLoopInvariantCodeMotion
! AFFINE-NEXT: AffineLoopNormalize
! AFFINE-NEXT: SimplifyAffineStructures
! AFFINE-NEXT: AffineParallelize
! AFFINE-NEXT: AffineDialectDemotion
! AFFINE-NEXT: LowerAffinePass

! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private']
! ALL-NEXT: 'fir.global' Pipeline
! ALL-NEXT: StackReclaim
Expand Down
10 changes: 10 additions & 0 deletions flang/test/Integration/OpenMP/auto-omp.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
! RUN: %flang_fc1 -O1 -mllvm --enable-affine-opt -emit-llvm -fopenmp -o - %s \
! RUN: | FileCheck %s

!CHECK-LABEL: define void @foo_(ptr captures(none) %0) {{.*}} {
!CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_1:.*]])

subroutine foo(a)
integer, dimension(100, 100), intent(out) :: a
a = 1
end subroutine foo
Loading