Index: flang/include/flang/Optimizer/Transforms/Passes.h =================================================================== --- flang/include/flang/Optimizer/Transforms/Passes.h +++ flang/include/flang/Optimizer/Transforms/Passes.h @@ -30,6 +30,9 @@ std::unique_ptr createAffineDemotionPass(); std::unique_ptr createArrayValueCopyPass(); std::unique_ptr createFirToCfgPass(); +std::unique_ptr createFirToCfgPass(bool transformDoLoop, + bool transformIf, + bool transformIterateWhile); std::unique_ptr createCharacterConversionPass(); std::unique_ptr createExternalNameConversionPass(); std::unique_ptr createMemDataFlowOptPass(); Index: flang/include/flang/Optimizer/Transforms/Passes.td =================================================================== --- flang/include/flang/Optimizer/Transforms/Passes.td +++ flang/include/flang/Optimizer/Transforms/Passes.td @@ -127,7 +127,16 @@ let options = [ Option<"forceLoopToExecuteOnce", "always-execute-loop-body", "bool", /*default=*/"false", - "force the body of a loop to execute at least once"> + "force the body of a loop to execute at least once">, + Option<"transformDoLoop", "transform-do-loop", "bool", + /*default=*/"true", + "apply the transformation the do loops">, + Option<"transformIf", "transform-if", "bool", + /*default=*/"true", + "apply transformation on if statments">, + Option<"transformIterateWhile", "transform-iterate-while", "bool", + /*default=*/"true", + "apply transformation on iterate while"> ]; } Index: flang/include/flang/Tools/CLOptions.inc =================================================================== --- flang/include/flang/Tools/CLOptions.inc +++ flang/include/flang/Tools/CLOptions.inc @@ -79,7 +79,7 @@ inline void addCfgConversionPass(mlir::PassManager &pm) { addNestedPassConditionally( - pm, disableCfgConversion, fir::createFirToCfgPass); + pm, disableCfgConversion, []() {return fir::createFirToCfgPass();}); } inline void addAVC(mlir::PassManager &pm) { Index: flang/lib/Optimizer/Transforms/RewriteLoop.cpp =================================================================== --- flang/lib/Optimizer/Transforms/RewriteLoop.cpp +++ flang/lib/Optimizer/Transforms/RewriteLoop.cpp @@ -294,17 +294,38 @@ /// Convert FIR structured control flow ops to CFG ops. class CfgConversion : public CFGConversionBase { public: + CfgConversion() = default; + CfgConversion(bool transformDoLoop, bool transformIf, + bool transformIterateWhile) { + this->transformDoLoop = transformDoLoop; + this->transformIf = transformIf; + this->transformIterateWhile = transformIterateWhile; + } + void runOnOperation() override { auto *context = &getContext(); mlir::RewritePatternSet patterns(context); - patterns.insert( - context, forceLoopToExecuteOnce); mlir::ConversionTarget target(*context); target.addLegalDialect(); // apply the patterns - target.addIllegalOp(); + if (transformIterateWhile) { + patterns.insert(context, forceLoopToExecuteOnce); + target.addIllegalOp(); + } + if (transformDoLoop) { + patterns.insert(context, forceLoopToExecuteOnce); + target.addIllegalOp(); + } + if (transformIf) { + patterns.insert(context, forceLoopToExecuteOnce); + target.addIllegalOp(); + } + bool transformAll = transformIterateWhile && transformDoLoop && transformIf; + if (transformAll) { + target.addIllegalOp(); + } target.markUnknownOpDynamicallyLegal([](Operation *) { return true; }); if (mlir::failed(mlir::applyPartialConversion(getOperation(), target, std::move(patterns)))) { @@ -319,6 +340,13 @@ /// Convert FIR's structured control flow ops to CFG ops. This /// conversion enables the `createLowerToCFGPass` to transform these to CFG /// form. +std::unique_ptr +fir::createFirToCfgPass(bool transformDoLoop, bool transformIf, + bool transformIterateWhile) { + return std::make_unique(transformDoLoop, transformIf, + transformIterateWhile); +} +/// Overload utilizing pass options for initialization. std::unique_ptr fir::createFirToCfgPass() { return std::make_unique(); } Index: flang/test/Fir/cfg-options1.fir =================================================================== --- /dev/null +++ flang/test/Fir/cfg-options1.fir @@ -0,0 +1,27 @@ +// RUN: fir-opt %s --cfg-conversion | FileCheck %s + +// CHECK-LABEL: @x +// CHECK-NOT: fir.if +// CHECK-NOT: fir.do_loop +func @x(%lb : index, %ub : index, %step : index, %b : i1, %addr : !fir.ref) { + fir.do_loop %iv = %lb to %ub step %step unordered { + fir.if %b { + fir.store %iv to %addr : !fir.ref + } else { + %zero = arith.constant 0 : index + fir.store %zero to %addr : !fir.ref + } + } + return +} + +// CHECK-LABEL: @x2 +// CHECK-NOT: fir.iterate_while +func @x2(%lo : index, %up : index, %ok : i1) { + %c1 = arith.constant 1 : index + %unused = fir.iterate_while (%i = %lo to %up step %c1) and (%ok1 = %ok) { + %ok2 = fir.call @f2() : () -> i1 + fir.result %ok2 : i1 + } + return +} Index: flang/test/Fir/cfg-options2.fir =================================================================== --- /dev/null +++ flang/test/Fir/cfg-options2.fir @@ -0,0 +1,27 @@ +// RUN: fir-opt %s --cfg-conversion="transform-if=0 transform-iterate-while=0" | FileCheck %s + +// CHECK-LABEL: @x +// CHECK: fir.if +// CHECK-NOT: fir.do_loop +func @x(%lb : index, %ub : index, %step : index, %b : i1, %addr : !fir.ref) { + fir.do_loop %iv = %lb to %ub step %step unordered { + fir.if %b { + fir.store %iv to %addr : !fir.ref + } else { + %zero = arith.constant 0 : index + fir.store %zero to %addr : !fir.ref + } + } + return +} + +// CHECK-LABEL: @x2 +// CHECK: fir.iterate_while +func @x2(%lo : index, %up : index, %ok : i1) { + %c1 = arith.constant 1 : index + %unused = fir.iterate_while (%i = %lo to %up step %c1) and (%ok1 = %ok) { + %ok2 = fir.call @f2() : () -> i1 + fir.result %ok2 : i1 + } + return +} Index: flang/test/Fir/cfg-options3.fir =================================================================== --- /dev/null +++ flang/test/Fir/cfg-options3.fir @@ -0,0 +1,28 @@ +// RUN: fir-opt %s --cfg-conversion="transform-iterate-while=0" | FileCheck %s + + +// CHECK-LABEL: @x +// CHECK-NOT: fir.if +// CHECK-NOT: fir.do_loop +func @x(%lb : index, %ub : index, %step : index, %b : i1, %addr : !fir.ref) { + fir.do_loop %iv = %lb to %ub step %step unordered { + fir.if %b { + fir.store %iv to %addr : !fir.ref + } else { + %zero = arith.constant 0 : index + fir.store %zero to %addr : !fir.ref + } + } + return +} + +// CHECK-LABEL: @x2 +// CHECK: fir.iterate_while +func @x2(%lo : index, %up : index, %ok : i1) { + %c1 = arith.constant 1 : index + %unused = fir.iterate_while (%i = %lo to %up step %c1) and (%ok1 = %ok) { + %ok2 = fir.call @f2() : () -> i1 + fir.result %ok2 : i1 + } + return +} Index: flang/test/Fir/cfg-options4.fir =================================================================== --- /dev/null +++ flang/test/Fir/cfg-options4.fir @@ -0,0 +1,27 @@ +// RUN: fir-opt %s --cfg-conversion="transform-do-loop=0 transform-if=0" | FileCheck %s + +// CHECK-LABEL: @x +// CHECK: fir.do_loop +// CHECK: fir.if +func @x(%lb : index, %ub : index, %step : index, %b : i1, %addr : !fir.ref) { + fir.do_loop %iv = %lb to %ub step %step unordered { + fir.if %b { + fir.store %iv to %addr : !fir.ref + } else { + %zero = arith.constant 0 : index + fir.store %zero to %addr : !fir.ref + } + } + return +} + +// CHECK-LABEL: @x2 +// CHECK-NOT: fir.iterate_while +func @x2(%lo : index, %up : index, %ok : i1) { + %c1 = arith.constant 1 : index + %unused = fir.iterate_while (%i = %lo to %up step %c1) and (%ok1 = %ok) { + %ok2 = fir.call @f2() : () -> i1 + fir.result %ok2 : i1 + } + return +}