diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/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"> ]; } diff --git a/flang/lib/Optimizer/Transforms/RewriteLoop.cpp b/flang/lib/Optimizer/Transforms/RewriteLoop.cpp --- a/flang/lib/Optimizer/Transforms/RewriteLoop.cpp +++ b/flang/lib/Optimizer/Transforms/RewriteLoop.cpp @@ -297,14 +297,27 @@ 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)))) { diff --git a/flang/test/Fir/cfg-options.fir b/flang/test/Fir/cfg-options.fir new file mode 100644 --- /dev/null +++ b/flang/test/Fir/cfg-options.fir @@ -0,0 +1,114 @@ +// RUN: rm -rf %t && mkdir %t +// RUN: %split-file %s %t +// RUN: fir-opt %t/all.fir --cfg-conversion | FileCheck %t/all.fir +// RUN: fir-opt %t/loop.fir --cfg-conversion="transform-if=0 transform-iterate-while=0" | FileCheck %t/loop.fir +// RUN: fir-opt %t/if.fir --cfg-conversion="transform-iterate-while=0" | FileCheck %t/if.fir +// RUN: fir-opt %t/while.fir --cfg-conversion="transform-do-loop=0 transform-if=0" | FileCheck %t/while.fir + +//--- all.fir +// CHECK-LABEL: @x +// CHECK-NOT: fir.if +// CHECK-NOT: fir.do_loop +// CHECK-NOT: fir.iterate_while +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 +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 +} + +//--- loop.fir +// 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 +} + +//--- if.fir +// 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 +} + +//--- while.fir +// 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 +} diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py --- a/flang/test/lit.cfg.py +++ b/flang/test/lit.cfg.py @@ -74,7 +74,9 @@ tools = [ ToolSubst('%flang', command=FindTool('flang-new'), unresolved='fatal'), ToolSubst('%flang_fc1', command=FindTool('flang-new'), extra_args=['-fc1'], - unresolved='fatal')] + unresolved='fatal'), + ToolSubst('%split-file', FindTool('split-file')) +] # Flang has several unimplemented features. TODO messages are used to mark and fail if these # features are exercised. TODOs exit with an error in non-assert builds but in assert builds