Skip to content

Commit c3440e2

Browse files
committed
[flang][hlfir] disable region simplification in HLFIR pipeline
Block merging is disabled with FIR: some FIR value should not be promoted to block arguments, and the region simplification block merging is promoting all SSA value types to block argument when two blocks are similar except for the usage these values. Differential Revision: https://reviews.llvm.org/D147130
1 parent 8ff4832 commit c3440e2

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

flang/include/flang/Tools/CLOptions.inc

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,17 @@ void addNestedPassConditionally(
9999

100100
namespace fir {
101101

102-
static void defaultFlangInlinerOptPipeline(mlir::OpPassManager &pm) {
102+
/// Add MLIR Canonicalizer pass with region simplification disabled.
103+
/// FIR does not support the promotion of some SSA value to block arguments (or
104+
/// into arith.select operands) that may be done by mlir block merging in the
105+
/// region simplification (e.g., !fir.shape<> SSA values are not supported as
106+
/// block arguments).
107+
/// Aside from the fir.shape issue, moving some abstract SSA value into block
108+
/// arguments may have a heavy cost since it forces their code generation that
109+
/// may be expensive (array temporary). The MLIR pass does not take these
110+
/// extra costs into account when doing block merging.
111+
static void addCanonicalizerPassWithoutRegionSimplification(
112+
mlir::OpPassManager &pm) {
103113
mlir::GreedyRewriteConfig config;
104114
config.enableRegionSimplification = false;
105115
pm.addPass(mlir::createCanonicalizerPass(config));
@@ -200,8 +210,8 @@ inline void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm,
200210
// The default inliner pass adds the canonicalizer pass with the default
201211
// configuration. Create the inliner pass with tco config.
202212
llvm::StringMap<mlir::OpPassManager> pipelines;
203-
pm.addPass(
204-
mlir::createInlinerPass(pipelines, defaultFlangInlinerOptPipeline));
213+
pm.addPass(mlir::createInlinerPass(
214+
pipelines, addCanonicalizerPassWithoutRegionSimplification));
205215
pm.addPass(fir::createSimplifyRegionLitePass());
206216
pm.addPass(mlir::createCSEPass());
207217

@@ -225,7 +235,7 @@ inline void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm,
225235
inline void createHLFIRToFIRPassPipeline(
226236
mlir::PassManager &pm, llvm::OptimizationLevel optLevel = defaultOptLevel) {
227237
if (optLevel.isOptimizingForSpeed())
228-
pm.addPass(mlir::createCanonicalizerPass());
238+
addCanonicalizerPassWithoutRegionSimplification(pm);
229239
pm.addPass(hlfir::createLowerHLFIRIntrinsicsPass());
230240
pm.addPass(hlfir::createBufferizeHLFIRPass());
231241
pm.addPass(hlfir::createConvertHLFIRtoFIRPass());
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Test that the HLFIR pipeline does not call MLIR canonicalizer with block
2+
// merging enabled (moving fir.shape to block argument would cause failures
3+
// when translating the FIR to LLVM).
4+
// RUN: %flang_fc1 %s -flang-experimental-hlfir -emit-llvm -O2 -o - | FileCheck %s
5+
6+
func.func @no_shape_merge(%cdt: i1, %from: !fir.ref<!fir.array<?xf64>>, %to : !fir.ref<f64>) {
7+
%c10 = arith.constant 10 : index
8+
%c20 = arith.constant 20 : index
9+
%c5 = arith.constant 5 : index
10+
%shape1 = fir.shape %c10 : (index) -> !fir.shape<1>
11+
%shape2 = fir.shape %c20 : (index) -> !fir.shape<1>
12+
cf.cond_br %cdt, ^bb1, ^bb2
13+
^bb1: // pred: ^bb0
14+
%coor1 = fir.array_coor %from(%shape1) %c5 : (!fir.ref<!fir.array<?xf64>>, !fir.shape<1>, index) -> !fir.ref<f64>
15+
%load1 = fir.load %coor1 : !fir.ref<f64>
16+
fir.store %load1 to %to : !fir.ref<f64>
17+
cf.br ^bb3
18+
^bb2: // pred: ^bb0
19+
%coor2 = fir.array_coor %from(%shape2) %c5 : (!fir.ref<!fir.array<?xf64>>, !fir.shape<1>, index) -> !fir.ref<f64>
20+
%load2 = fir.load %coor2 : !fir.ref<f64>
21+
fir.store %load2 to %to : !fir.ref<f64>
22+
cf.br ^bb3
23+
^bb3: // pred: ^bb1, ^bb2
24+
return
25+
}
26+
27+
// Note: block merging happens in the output below, but after FIR codegen.
28+
29+
// CHECK-LABEL: define void @no_shape_merge(
30+
// CHECK: %[[GEP:.*]] = getelementptr double, ptr %{{.*}}
31+
// CHECK: %[[LOAD:.*]] = load double, ptr %[[GEP]]
32+
// CHECK: store double %[[LOAD]], ptr %{{.*}}
33+
// CHECK: ret void

0 commit comments

Comments
 (0)