[flang-commits] [flang] [flang] Fixed LoopVersioning for array slices. (PR #65703)
Slava Zakharin via flang-commits
flang-commits at lists.llvm.org
Thu Oct 5 19:29:51 PDT 2023
================
@@ -224,58 +280,137 @@ void LoopVersioningPass::runOnOperation() {
}
}
- if (argsOfInterest.empty())
+ if (argsOfInterest.empty()) {
+ LLVM_DEBUG(llvm::dbgs()
+ << "No suitable arguments.\n=== End " DEBUG_TYPE " ===\n");
return;
+ }
- struct OpsWithArgs {
- mlir::Operation *op;
- mlir::SmallVector<ArgInfo, 4> argsAndDims;
- };
- // Now see if those arguments are used inside any loop.
- mlir::SmallVector<OpsWithArgs, 4> loopsOfInterest;
+ // A list of all loops in the function in post-order.
+ mlir::SmallVector<fir::DoLoopOp> originalLoops;
+ // Information about the arguments usage by the instructions
+ // immediately nested in a loop.
+ llvm::DenseMap<fir::DoLoopOp, ArgsUsageInLoop> argsInLoops;
+ // Traverse the loops in post-order and see
+ // if those arguments are used inside any loop.
func.walk([&](fir::DoLoopOp loop) {
mlir::Block &body = *loop.getBody();
- mlir::SmallVector<ArgInfo, 4> argsInLoop;
+ auto &argsInLoop = argsInLoops[loop];
+ originalLoops.push_back(loop);
body.walk([&](mlir::Operation *op) {
- // support either fir.array_coor or fir.coordinate_of
- if (auto arrayCoor = mlir::dyn_cast<fir::ArrayCoorOp>(op)) {
- // no support currently for sliced arrays
- if (arrayCoor.getSlice())
- return;
- } else if (!mlir::isa<fir::CoordinateOp>(op)) {
+ // Support either fir.array_coor or fir.coordinate_of.
+ if (!mlir::isa<fir::ArrayCoorOp, fir::CoordinateOp>(op))
return;
- }
-
- // The current operation could be inside another loop than
- // the one we're currently processing. Skip it, we'll get
- // to it later.
+ // Process only operations immediately nested in the current loop.
if (op->getParentOfType<fir::DoLoopOp>() != loop)
return;
mlir::Value operand = op->getOperand(0);
for (auto a : argsOfInterest) {
if (a.arg == normaliseVal(operand)) {
- // use the reboxed value, not the block arg when re-creating the loop:
+ // Use the reboxed value, not the block arg when re-creating the loop.
+ // TODO: should we check that the operand dominates the loop?
----------------
vzakhari wrote:
I think this may still be a problem. I just hand-modified the first case from `loop-versioning.fir`:
```
module {
func.func @sum1d(%arg0: !fir.box<!fir.array<?xf64>> {fir.bindc_name = "a"}, %arg1: !fir.ref<i32> {fir.bindc_name = "n"}) {
%decl = fir.declare %arg0 {uniq_name = "a"} : (!fir.box<!fir.array<?xf64>>) -> !fir.box<!fir.array<?xf64>>
%0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMmoduleFsum1dEi"}
%1 = fir.alloca f64 {bindc_name = "sum", uniq_name = "_QMmoduleFsum1dEsum"}
%cst = arith.constant 0.000000e+00 : f64
fir.store %cst to %1 : !fir.ref<f64>
%c1_i32 = arith.constant 1 : i32
%2 = fir.convert %c1_i32 : (i32) -> index
%3 = fir.load %arg1 : !fir.ref<i32>
%4 = fir.convert %3 : (i32) -> index
%c1 = arith.constant 1 : index
%5 = fir.convert %2 : (index) -> i32
%6:2 = fir.do_loop %arg2 = %2 to %4 step %c1 iter_args(%arg3 = %5) -> (index, i32) {
%rebox = fir.rebox %decl : (!fir.box<!fir.array<?xf64>>) -> !fir.box<!fir.array<?xf64>>
fir.store %arg3 to %0 : !fir.ref<i32>
%7 = fir.load %1 : !fir.ref<f64>
%8 = fir.load %0 : !fir.ref<i32>
%9 = fir.convert %8 : (i32) -> i64
%c1_i64 = arith.constant 1 : i64
%10 = arith.subi %9, %c1_i64 : i64
%11 = fir.coordinate_of %rebox, %10 : (!fir.box<!fir.array<?xf64>>, i64) -> !fir.ref<f64>
%12 = fir.load %11 : !fir.ref<f64>
%13 = arith.addf %7, %12 fastmath<contract> : f64
fir.store %13 to %1 : !fir.ref<f64>
%14 = arith.addi %arg2, %c1 : index
%15 = fir.convert %c1 : (index) -> i32
%16 = fir.load %0 : !fir.ref<i32>
%17 = arith.addi %16, %15 : i32
fir.result %14, %17 : index, i32
}
fir.store %6#1 to %0 : !fir.ref<i32>
return
}
}
```
It fails with an assertion: `Assertion `changed && "Expected operations to have changed"' failed.`, but I am not sure what it means exactly.
If I understand it correctly, as soon as the loop is proven to be safe to multiversion, we will transform it and we will use `%rebox` for generating the contiguity check **before** the loop, while it is defined inside the loop.
https://github.com/llvm/llvm-project/pull/65703
More information about the flang-commits
mailing list