[Mlir-commits] [mlir] [mlir][vectorize] Support affine.apply in SuperVectorize (PR #77968)
Hsiangkai Wang
llvmlistbot at llvm.org
Fri Jan 12 11:36:29 PST 2024
https://github.com/Hsiangkai created https://github.com/llvm/llvm-project/pull/77968
We have no need to vectorize affine.apply inside the vectorizing loop. However, we still need to generate it in the original scalar form. We have to replace all its operands with the generated scalar operands in the vectorizing loop, e.g., induction variables.
>From 999d52529aa818202ec827a9f85d6d17ec04e6bd Mon Sep 17 00:00:00 2001
From: Hsiangkai Wang <hsiangkai.wang at arm.com>
Date: Fri, 12 Jan 2024 18:04:44 +0000
Subject: [PATCH] [mlir][vectorize] Support affine.apply in SuperVectorize
We have no need to vectorize affine.apply inside the vectorizing loop.
However, we still need to generate it in the original scalar form.
We have to replace all its operands with the generated scalar operands
in the vectorizing loop, e.g., induction variables.
---
.../Affine/Transforms/SuperVectorize.cpp | 31 ++++++++++++++++---
.../vectorize_affine_apply.mlir | 23 ++++++++++++++
2 files changed, 50 insertions(+), 4 deletions(-)
create mode 100644 mlir/test/Dialect/Affine/SuperVectorize/vectorize_affine_apply.mlir
diff --git a/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp b/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp
index 6b7a157925fae1..3b70618fe151c5 100644
--- a/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp
@@ -721,8 +721,7 @@ struct VectorizationState {
/// Example:
/// * 'replaced': induction variable of a loop to be vectorized.
/// * 'replacement': new induction variable in the new vector loop.
- void registerValueScalarReplacement(BlockArgument replaced,
- BlockArgument replacement);
+ void registerValueScalarReplacement(Value replaced, Value replacement);
/// Registers the scalar replacement of a scalar result returned from a
/// reduction loop. 'replacement' must be scalar.
@@ -854,8 +853,8 @@ void VectorizationState::registerValueVectorReplacementImpl(Value replaced,
/// Example:
/// * 'replaced': induction variable of a loop to be vectorized.
/// * 'replacement': new induction variable in the new vector loop.
-void VectorizationState::registerValueScalarReplacement(
- BlockArgument replaced, BlockArgument replacement) {
+void VectorizationState::registerValueScalarReplacement(Value replaced,
+ Value replacement) {
registerValueScalarReplacementImpl(replaced, replacement);
}
@@ -978,6 +977,28 @@ static arith::ConstantOp vectorizeConstant(arith::ConstantOp constOp,
return newConstOp;
}
+/// We have no need to vectorize affine.apply. However, we still need to
+/// generate it and replace the operands with values in valueScalarReplacement.
+static Operation *vectorizeAffineApplyOp(AffineApplyOp applyOp,
+ VectorizationState &state) {
+ SmallVector<Value, 8> updatedOperands;
+ for (Value operand : applyOp.getOperands()) {
+ Value updatedOperand = operand;
+ if (state.valueScalarReplacement.contains(operand)) {
+ updatedOperand = state.valueScalarReplacement.lookupOrDefault(operand);
+ }
+ updatedOperands.push_back(updatedOperand);
+ }
+
+ auto newApplyOp = state.builder.create<AffineApplyOp>(
+ applyOp.getLoc(), applyOp.getAffineMap(), updatedOperands);
+
+ // Register the new affine.apply result.
+ state.registerValueScalarReplacement(applyOp.getResult(),
+ newApplyOp.getResult());
+ return newApplyOp;
+}
+
/// Creates a constant vector filled with the neutral elements of the given
/// reduction. The scalar type of vector elements will be taken from
/// `oldOperand`.
@@ -1493,6 +1514,8 @@ static Operation *vectorizeOneOperation(Operation *op,
return vectorizeAffineYieldOp(yieldOp, state);
if (auto constant = dyn_cast<arith::ConstantOp>(op))
return vectorizeConstant(constant, state);
+ if (auto applyOp = dyn_cast<AffineApplyOp>(op))
+ return vectorizeAffineApplyOp(applyOp, state);
// Other ops with regions are not supported.
if (op->getNumRegions() != 0)
diff --git a/mlir/test/Dialect/Affine/SuperVectorize/vectorize_affine_apply.mlir b/mlir/test/Dialect/Affine/SuperVectorize/vectorize_affine_apply.mlir
new file mode 100644
index 00000000000000..588663e1f97b61
--- /dev/null
+++ b/mlir/test/Dialect/Affine/SuperVectorize/vectorize_affine_apply.mlir
@@ -0,0 +1,23 @@
+// RUN: mlir-opt %s -affine-super-vectorize="virtual-vector-size=8 test-fastest-varying=0" -split-input-file | FileCheck %s
+
+// CHECK-DAG: #[[$map_id0:map[0-9a-zA-Z_]*]] = affine_map<(d0) -> (d0 mod 12)>
+// CHECK-DAG: #[[$map_id1:map[0-9a-zA-Z_]*]] = affine_map<(d0) -> (d0 mod 16)>
+
+// CHECK-LABEL: func @vec_affine_apply
+func.func @vec_affine_apply(%arg0: memref<8x12x16xf32>, %arg1: memref<8x24x48xf32>) {
+ affine.for %arg2 = 0 to 8 {
+// CHECK: affine.for %[[S0:.*]] = 0 to 24 {
+// CHECK-NEXT: affine.for %[[S1:.*]] = 0 to 48 step 8 {
+ affine.for %arg3 = 0 to 24 {
+ affine.for %arg4 = 0 to 48 {
+// CHECK-NEXT: affine.apply #[[$map_id0]](%[[S0]])
+// CHECK-NEXT: affine.apply #[[$map_id1]](%[[S1]])
+ %0 = affine.apply affine_map<(d0) -> (d0 mod 12)>(%arg3)
+ %1 = affine.apply affine_map<(d0) -> (d0 mod 16)>(%arg4)
+ %2 = affine.load %arg0[%arg2, %0, %1] : memref<8x12x16xf32>
+ affine.store %2, %arg1[%arg2, %arg3, %arg4] : memref<8x24x48xf32>
+ }
+ }
+ }
+ return
+}
More information about the Mlir-commits
mailing list