diff --git a/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp b/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp --- a/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp +++ b/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp @@ -1037,9 +1037,13 @@ annotateFn(i, clonedOp, builder); } - // Update yielded values. + // Update yielded values. If yielded value is getting updated in this block + // then update it with it's new value else yielded value remains unchanged. for (unsigned i = 0, e = lastYielded.size(); i < e; i++) - lastYielded[i] = operandMap.lookup(yieldedValues[i]); + if (yieldedValues[i].getDefiningOp()->getBlock() == loopBodyBlock) + lastYielded[i] = operandMap.lookup(yieldedValues[i]); + else + lastYielded[i] = yieldedValues[i]; } // Make sure we annotate the Ops in the original body. We do this last so that diff --git a/mlir/test/Dialect/SCF/loop-unroll.mlir b/mlir/test/Dialect/SCF/loop-unroll.mlir --- a/mlir/test/Dialect/SCF/loop-unroll.mlir +++ b/mlir/test/Dialect/SCF/loop-unroll.mlir @@ -5,6 +5,7 @@ // RUN: mlir-opt %s -test-loop-unrolling='unroll-factor=2 annotate=true' | FileCheck %s --check-prefix UNROLL-BY-2-ANNOTATE // RUN: mlir-opt %s --affine-loop-unroll='unroll-factor=6 unroll-up-to-factor=true' | FileCheck %s --check-prefix UNROLL-UP-TO // RUN: mlir-opt %s --affine-loop-unroll='unroll-factor=5 cleanup-unroll=true' | FileCheck %s --check-prefix CLEANUP-UNROLL-BY-5 +// RUN: mlir-opt %s --affine-loop-unroll | FileCheck %s func.func @dynamic_loop_unroll(%arg0 : index, %arg1 : index, %arg2 : index, %arg3: memref) { @@ -339,4 +340,27 @@ // CLEANUP-UNROLL-BY-5-NEXT: memref.store %{{.*}}, %[[MEM]][%[[V1]]] : memref // CLEANUP-UNROLL-BY-5-NEXT: %[[V2:.*]] = affine.apply {{.*}} // CLEANUP-UNROLL-BY-5-NEXT: memref.store %{{.*}}, %[[MEM]][%[[V2]]] : memref -// CLEANUP-UNROLL-BY-5-NEXT: return \ No newline at end of file +// CLEANUP-UNROLL-BY-5-NEXT: return + +// Test loop unrolling when the yielded value remains unchanged. +// CHECK: [[$MAP:#map]] = affine_map<(d0) -> (-d0 + 64, (d0 floordiv 8) ceildiv 64, -d0 - 16, d0 * -64)> +// CHECK-LABEL: func @loop_unroll_static_yield_value +func.func @loop_unroll_static_yield_value() { + %true_4 = arith.constant true + %c1 = arith.constant 1 : index + %103 = affine.for %arg2 = 0 to 40 iter_args(%arg3 = %true_4) -> (i1) { + %324 = affine.max affine_map<(d0) -> (-d0 + 64, (d0 floordiv 8) ceildiv 64, -d0 - 16, d0 * -64)>(%c1) + affine.yield %true_4 : i1 + } + return +} +// CHECK: %[[TRUE:.*]] = arith.constant true +// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index +// CHECK-NEXT: %{{.*}} = affine.for %{{.*}} = 0 to 40 step 4 iter_args(%{{.*}} = %[[TRUE]]) -> (i1) { +// CHECK-NEXT: %{{.*}} = affine.max [[$MAP]](%[[C1]]) +// CHECK-NEXT: %{{.*}} = affine.max [[$MAP]](%[[C1]]) +// CHECK-NEXT: %{{.*}} = affine.max [[$MAP]](%[[C1]]) +// CHECK-NEXT: %{{.*}} = affine.max [[$MAP]](%[[C1]]) +// CHECK-NEXT: affine.yield %[[TRUE]] : i1 +// CHECK-NEXT: } +// CHECK-NEXT: return