Skip to content

Commit 93936da

Browse files
committed
[mlir][Affine][VectorOps] Fix super vectorizer utility (D85869)
Adding missing code that should have been part of "D85869: Utility to vectorize loop nest using strategy." Reviewed By: nicolasvasilache Differential Revision: https://reviews.llvm.org/D88346
1 parent f668a84 commit 93936da

File tree

4 files changed

+76
-17
lines changed

4 files changed

+76
-17
lines changed

mlir/include/mlir/Dialect/Affine/Utils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ void vectorizeAffineLoops(
122122
/// loops = {{%i3}}, to vectorize only the second innermost loop;
123123
/// loops = {{%i1}}, to vectorize only the middle loop.
124124
LogicalResult
125-
vectorizeAffineLoopNest(const std::vector<SmallVector<AffineForOp, 2>> &loops,
125+
vectorizeAffineLoopNest(std::vector<SmallVector<AffineForOp, 2>> &loops,
126126
const VectorizationStrategy &strategy);
127127

128128
/// Normalize a affine.parallel op so that lower bounds are 0 and steps are 1.

mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,7 @@ void Vectorize::runOnFunction() {
13381338
static void
13391339
verifyLoopNesting(const std::vector<SmallVector<AffineForOp, 2>> &loops) {
13401340
assert(!loops.empty() && "Expected at least one loop");
1341-
assert(!loops[0].size() && "Expected only one root loop");
1341+
assert(loops[0].size() == 1 && "Expected only one root loop");
13421342

13431343
// Traverse loops outer-to-inner to check some invariants.
13441344
for (int i = 1, end = loops.size(); i < end; ++i) {

mlir/test/Dialect/Affine/SuperVectorize/vector_utils.mlir

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// RUN: mlir-opt %s -affine-super-vectorizer-test -vector-shape-ratio 4 -vector-shape-ratio 8 2>&1 | FileCheck %s
22
// RUN: mlir-opt %s -affine-super-vectorizer-test -vector-shape-ratio 2 -vector-shape-ratio 5 -vector-shape-ratio 2 2>&1 | FileCheck %s -check-prefix=TEST-3x4x5x8
3+
// RUN: mlir-opt %s -affine-super-vectorizer-test -vectorize-affine-loop-nest 2>&1 | FileCheck %s -check-prefix=VECNEST
34

45
func @vector_add_2d(%arg0: index, %arg1: index) -> f32 {
56
// Nothing should be matched in this first block.
@@ -35,3 +36,27 @@ func @vector_add_2d(%arg0: index, %arg1: index) -> f32 {
3536
%9 = load %2[%c7, %c42] : memref<?x?xf32>
3637
return %9 : f32
3738
}
39+
40+
// VECNEST-LABEL: func @double_loop_nest
41+
func @double_loop_nest(%a: memref<20x30xf32>, %b: memref<20xf32>) {
42+
43+
affine.for %i = 0 to 20 {
44+
%b_ld = affine.load %b[%i] : memref<20xf32>
45+
affine.for %j = 0 to 30 {
46+
%a_ld = affine.load %a[%i, %j] : memref<20x30xf32>
47+
affine.store %a_ld, %a[%i, %j] : memref<20x30xf32>
48+
}
49+
affine.store %b_ld, %b[%i] : memref<20xf32>
50+
}
51+
52+
return
53+
}
54+
55+
// VECNEST: affine.for %{{.*}} = 0 to 20 step 4 {
56+
// VECNEST: vector.transfer_read
57+
// VECNEST-NEXT: affine.for %{{.*}} = 0 to 30 {
58+
// VECNEST: vector.transfer_read
59+
// VECNEST-NEXT: vector.transfer_write
60+
// VECNEST-NEXT: }
61+
// VECNEST-NEXT: vector.transfer_write
62+
// VECNEST: }

mlir/test/lib/Dialect/Affine/TestVectorizationUtils.cpp

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
#include "mlir/Analysis/NestedMatcher.h"
1515
#include "mlir/Analysis/SliceAnalysis.h"
1616
#include "mlir/Dialect/Affine/IR/AffineOps.h"
17+
#include "mlir/Dialect/Affine/Utils.h"
1718
#include "mlir/Dialect/Vector/VectorOps.h"
1819
#include "mlir/Dialect/Vector/VectorUtils.h"
1920
#include "mlir/IR/Builders.h"
2021
#include "mlir/IR/Diagnostics.h"
2122
#include "mlir/IR/StandardTypes.h"
2223
#include "mlir/Pass/Pass.h"
24+
#include "mlir/Transforms/LoopUtils.h"
2325
#include "mlir/Transforms/Passes.h"
2426

2527
#include "llvm/ADT/STLExtras.h"
@@ -67,6 +69,12 @@ static llvm::cl::opt<bool> clTestNormalizeMaps(
6769
"where each AffineAffineApplyOp in the composition is a single output "
6870
"operation."),
6971
llvm::cl::cat(clOptionsCategory));
72+
static llvm::cl::opt<bool> clTestVecAffineLoopNest(
73+
"vectorize-affine-loop-nest",
74+
llvm::cl::desc(
75+
"Enable testing for the 'vectorizeAffineLoopNest' utility by "
76+
"vectorizing the outermost loops found"),
77+
llvm::cl::cat(clOptionsCategory));
7078

7179
namespace {
7280
struct VectorizerTestPass
@@ -84,6 +92,9 @@ struct VectorizerTestPass
8492
void testSlicing(llvm::raw_ostream &outs);
8593
void testComposeMaps(llvm::raw_ostream &outs);
8694
void testNormalizeMaps();
95+
96+
/// Test for 'vectorizeAffineLoopNest' utility.
97+
void testVecAffineLoopNest();
8798
};
8899

89100
} // end anonymous namespace
@@ -246,10 +257,26 @@ void VectorizerTestPass::testNormalizeMaps() {
246257
}
247258
}
248259

249-
void VectorizerTestPass::runOnFunction() {
250-
// Thread-safe RAII local context, BumpPtrAllocator freed on exit.
251-
NestedPatternContext mlContext;
260+
/// Test for 'vectorizeAffineLoopNest' utility.
261+
void VectorizerTestPass::testVecAffineLoopNest() {
262+
std::vector<SmallVector<AffineForOp, 2>> loops;
263+
gatherLoops(getFunction(), loops);
264+
265+
// Expected only one loop nest.
266+
if (loops.empty() || loops[0].size() != 1)
267+
return;
252268

269+
// We vectorize the outermost loop found with VF=4.
270+
AffineForOp outermostLoop = loops[0][0];
271+
VectorizationStrategy strategy;
272+
strategy.vectorSizes.push_back(4 /*vectorization factor*/);
273+
strategy.loopToVectorDim[outermostLoop] = 0;
274+
std::vector<SmallVector<AffineForOp, 2>> loopsToVectorize;
275+
loopsToVectorize.push_back({outermostLoop});
276+
vectorizeAffineLoopNest(loopsToVectorize, strategy);
277+
}
278+
279+
void VectorizerTestPass::runOnFunction() {
253280
// Only support single block functions at this point.
254281
FuncOp f = getFunction();
255282
if (!llvm::hasSingleElement(f))
@@ -258,23 +285,30 @@ void VectorizerTestPass::runOnFunction() {
258285
std::string str;
259286
llvm::raw_string_ostream outs(str);
260287

261-
if (!clTestVectorShapeRatio.empty())
262-
testVectorShapeRatio(outs);
288+
{ // Tests that expect a NestedPatternContext to be allocated externally.
289+
NestedPatternContext mlContext;
263290

264-
if (clTestForwardSlicingAnalysis)
265-
testForwardSlicing(outs);
291+
if (!clTestVectorShapeRatio.empty())
292+
testVectorShapeRatio(outs);
266293

267-
if (clTestBackwardSlicingAnalysis)
268-
testBackwardSlicing(outs);
294+
if (clTestForwardSlicingAnalysis)
295+
testForwardSlicing(outs);
269296

270-
if (clTestSlicingAnalysis)
271-
testSlicing(outs);
297+
if (clTestBackwardSlicingAnalysis)
298+
testBackwardSlicing(outs);
272299

273-
if (clTestComposeMaps)
274-
testComposeMaps(outs);
300+
if (clTestSlicingAnalysis)
301+
testSlicing(outs);
302+
303+
if (clTestComposeMaps)
304+
testComposeMaps(outs);
305+
306+
if (clTestNormalizeMaps)
307+
testNormalizeMaps();
308+
}
275309

276-
if (clTestNormalizeMaps)
277-
testNormalizeMaps();
310+
if (clTestVecAffineLoopNest)
311+
testVecAffineLoopNest();
278312

279313
if (!outs.str().empty()) {
280314
emitRemark(UnknownLoc::get(&getContext()), outs.str());

0 commit comments

Comments
 (0)