MLIR 24.0.0git
LowerVectorMultiReduction.cpp
Go to the documentation of this file.
1//===- LowerVectorMultiReduction.cpp - Lower `vector.multi_reduction` op --===//
2//
3/// Part of the LLVM Project, under the Apache License v2.0 with LLVM
4/// Exceptions. See https://llvm.org/LICENSE.txt for license information.
5/// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements target-independent rewrites and utilities to lower the
10// 'vector.multi_reduction' operation.
11//
12//===----------------------------------------------------------------------===//
13
18#include "mlir/IR/Builders.h"
21
22namespace mlir {
23namespace vector {
24#define GEN_PASS_DEF_LOWERVECTORMULTIREDUCTION
25#include "mlir/Dialect/Vector/Transforms/Passes.h.inc"
26} // namespace vector
27} // namespace mlir
28
29#define DEBUG_TYPE "vector-multi-reduction"
30
31using namespace mlir;
32
33namespace {
34/// This file implements the following transformations as composable atomic
35/// patterns.
36
37/// Converts vector.multi_reduction into inner-most/outer-most reduction form
38/// by using vector.transpose
39class InnerOuterDimReductionConversion
40 : public OpRewritePattern<vector::MultiDimReductionOp> {
41public:
42 using Base::Base;
43
44 explicit InnerOuterDimReductionConversion(
45 MLIRContext *context, vector::VectorMultiReductionLowering options,
46 PatternBenefit benefit = 1)
48 useInnerDimsForReduction(
49 options == vector::VectorMultiReductionLowering::InnerReduction) {}
50
51 LogicalResult matchAndRewrite(vector::MultiDimReductionOp multiReductionOp,
52 PatternRewriter &rewriter) const override {
53 // Vector mask setup.
54 OpBuilder::InsertionGuard guard(rewriter);
55 auto maskableOp =
56 cast<vector::MaskableOpInterface>(multiReductionOp.getOperation());
57 Operation *rootOp;
58 if (maskableOp.isMasked()) {
59 rewriter.setInsertionPoint(maskableOp.getMaskingOp());
60 rootOp = maskableOp.getMaskingOp();
61 } else {
62 rootOp = multiReductionOp;
63 }
64
65 auto src = multiReductionOp.getSource();
66 auto loc = multiReductionOp.getLoc();
67 auto srcRank = multiReductionOp.getSourceVectorType().getRank();
68
69 // Separate reduction and parallel dims
70 ArrayRef<int64_t> reductionDims = multiReductionOp.getReductionDims();
71 llvm::SmallDenseSet<int64_t> reductionDimsSet(reductionDims.begin(),
72 reductionDims.end());
73 int64_t reductionSize = reductionDims.size();
74 SmallVector<int64_t, 4> parallelDims;
75 for (int64_t i = 0; i < srcRank; ++i)
76 if (!reductionDimsSet.contains(i))
77 parallelDims.push_back(i);
78
79 // Add transpose only if inner-most/outer-most dimensions are not parallel
80 // and there are parallel dims.
81 if (parallelDims.empty())
82 return failure();
83 if (useInnerDimsForReduction &&
84 (parallelDims ==
85 llvm::to_vector<4>(llvm::seq<int64_t>(0, parallelDims.size()))))
86 return failure();
87
88 if (!useInnerDimsForReduction &&
89 (parallelDims == llvm::to_vector<4>(llvm::seq<int64_t>(
90 reductionDims.size(),
91 parallelDims.size() + reductionDims.size()))))
92 return failure();
93
95 if (useInnerDimsForReduction) {
96 indices.append(parallelDims.begin(), parallelDims.end());
97 indices.append(reductionDims.begin(), reductionDims.end());
98 } else {
99 indices.append(reductionDims.begin(), reductionDims.end());
100 indices.append(parallelDims.begin(), parallelDims.end());
101 }
102
103 // If masked, transpose the original mask.
104 Value transposedMask;
105 if (maskableOp.isMasked()) {
106 transposedMask = vector::TransposeOp::create(
107 rewriter, loc, maskableOp.getMaskingOp().getMask(), indices);
108 }
109
110 // Transpose reduction source.
111 auto transposeOp = vector::TransposeOp::create(rewriter, loc, src, indices);
112 SmallVector<bool> reductionMask(srcRank, false);
113 for (int i = 0; i < reductionSize; ++i) {
114 if (useInnerDimsForReduction)
115 reductionMask[srcRank - i - 1] = true;
116 else
117 reductionMask[i] = true;
118 }
119
120 Operation *newMultiRedOp = vector::MultiDimReductionOp::create(
121 rewriter, multiReductionOp.getLoc(), transposeOp.getResult(),
122 multiReductionOp.getAcc(), reductionMask, multiReductionOp.getKind(),
123 multiReductionOp.getFastmath());
124 newMultiRedOp =
125 mlir::vector::maskOperation(rewriter, newMultiRedOp, transposedMask);
126
127 rewriter.replaceOp(rootOp, newMultiRedOp->getResult(0));
128 return success();
129 }
130
131private:
132 const bool useInnerDimsForReduction;
133};
134
135/// Flattens vector.multi_reduction to 2D
136///
137/// Given all reduction dimensions are either inner most or outer most,
138/// flattens all reduction and parallel dimensions so that there are only 2Ds.
139///
140/// BEFORE
141/// vector.multi_reduction <add>, %vec, %acc [2, 3] : vector<2x3x4x5xi32> to
142/// vector<2x3xi32>
143/// AFTER
144/// %vec_sc = vector.shape_cast %vec
145/// %acc_sc = vector.shape_cast %acc
146/// %res = vector.multi_reduction <add>, %vec_sc, %acc_cs [1] :
147/// vector<6x20xi32> to vector<6xi32> %res_sc = vector.shape_cast %res
148class FlattenMultiReduction
149 : public OpRewritePattern<vector::MultiDimReductionOp> {
150public:
151 using Base::Base;
152
153 explicit FlattenMultiReduction(MLIRContext *context,
154 vector::VectorMultiReductionLowering options,
155 PatternBenefit benefit = 1)
157 useInnerDimsForReduction(
158 options == vector::VectorMultiReductionLowering::InnerReduction) {}
159
160 LogicalResult matchAndRewrite(vector::MultiDimReductionOp multiReductionOp,
161 PatternRewriter &rewriter) const override {
162 // Vector mask setup.
163 OpBuilder::InsertionGuard guard(rewriter);
164 auto maskableOp =
165 cast<vector::MaskableOpInterface>(multiReductionOp.getOperation());
166 Operation *rootOp;
167 if (maskableOp.isMasked()) {
168 rewriter.setInsertionPoint(maskableOp.getMaskingOp());
169 rootOp = maskableOp.getMaskingOp();
170 } else {
171 rootOp = multiReductionOp;
172 }
173
174 auto srcRank = multiReductionOp.getSourceVectorType().getRank();
175 auto srcShape = multiReductionOp.getSourceVectorType().getShape();
176 auto srcScalableDims =
177 multiReductionOp.getSourceVectorType().getScalableDims();
178 auto loc = multiReductionOp.getLoc();
179
180 // If rank less than 2, nothing to do.
181 if (srcRank < 2)
182 return failure();
183
184 // Allow only 1 scalable dimensions. Otherwise we could end-up with e.g.
185 // `vscale * vscale` that's currently not modelled.
186 if (llvm::count(srcScalableDims, true) > 1)
187 return failure();
189 // If already rank-2 ["parallel", "reduce"] or ["reduce", "parallel"] bail.
190 SmallVector<bool> reductionMask = multiReductionOp.getReductionMask();
191 if (srcRank == 2 && reductionMask.front() != reductionMask.back())
192 return failure();
194 // 1. Separate reduction and parallel dims.
195 SmallVector<int64_t, 4> parallelDims, parallelShapes;
196 SmallVector<bool, 4> parallelScalableDims;
197 SmallVector<int64_t, 4> reductionDims, reductionShapes;
198 bool isReductionDimScalable = false;
199 for (const auto &it : llvm::enumerate(reductionMask)) {
200 int64_t i = it.index();
201 bool isReduction = it.value();
202 if (isReduction) {
203 reductionDims.push_back(i);
204 reductionShapes.push_back(srcShape[i]);
205 isReductionDimScalable |= srcScalableDims[i];
206 } else {
207 parallelDims.push_back(i);
208 parallelShapes.push_back(srcShape[i]);
209 parallelScalableDims.push_back(srcScalableDims[i]);
210 }
211 }
213 // 2. Compute flattened parallel and reduction sizes.
214 int flattenedParallelDim = 0;
215 int flattenedReductionDim = 0;
216 if (!parallelShapes.empty()) {
217 flattenedParallelDim = 1;
218 for (auto d : parallelShapes)
219 flattenedParallelDim *= d;
220 }
221 if (!reductionShapes.empty()) {
222 flattenedReductionDim = 1;
223 for (auto d : reductionShapes)
224 flattenedReductionDim *= d;
225 }
226 // We must at least have some parallel or some reduction.
227 assert((flattenedParallelDim || flattenedReductionDim) &&
228 "expected at least one parallel or reduction dim");
229
230 // 3. Fail if reduction/parallel dims are not contiguous.
231 // Check parallelDims are exactly [0 .. size).
232 int64_t counter = 0;
233 if (useInnerDimsForReduction &&
234 llvm::any_of(parallelDims, [&](int64_t i) { return i != counter++; }))
235 return failure();
236 // Check parallelDims are exactly {reductionDims.size()} + [0 .. size).
237 counter = reductionDims.size();
238 if (!useInnerDimsForReduction &&
239 llvm::any_of(parallelDims, [&](int64_t i) { return i != counter++; }))
240 return failure();
241
242 // 4. Shape cast to collapse consecutive parallel (resp. reduction dim) into
243 // a single parallel (resp. reduction) dim.
245 SmallVector<bool, 2> scalableDims;
247 bool isParallelDimScalable = llvm::is_contained(parallelScalableDims, true);
248 if (flattenedParallelDim) {
249 mask.push_back(false);
250 vectorShape.push_back(flattenedParallelDim);
251 scalableDims.push_back(isParallelDimScalable);
252 }
253 if (flattenedReductionDim) {
254 mask.push_back(true);
255 vectorShape.push_back(flattenedReductionDim);
256 scalableDims.push_back(isReductionDimScalable);
257 }
258 if (!useInnerDimsForReduction && vectorShape.size() == 2) {
259 std::swap(mask.front(), mask.back());
260 std::swap(vectorShape.front(), vectorShape.back());
261 std::swap(scalableDims.front(), scalableDims.back());
262 }
263
264 Value newVectorMask;
265 if (maskableOp.isMasked()) {
266 Value vectorMask = maskableOp.getMaskingOp().getMask();
267 auto maskCastedType = VectorType::get(
269 llvm::cast<VectorType>(vectorMask.getType()).getElementType());
270 newVectorMask = vector::ShapeCastOp::create(rewriter, loc, maskCastedType,
271 vectorMask);
272 }
273
274 auto castedType = VectorType::get(
275 vectorShape, multiReductionOp.getSourceVectorType().getElementType(),
276 scalableDims);
277 Value cast = vector::ShapeCastOp::create(rewriter, loc, castedType,
278 multiReductionOp.getSource());
279
280 Value acc = multiReductionOp.getAcc();
281 if (flattenedParallelDim) {
282 auto accType = VectorType::get(
283 {flattenedParallelDim},
284 multiReductionOp.getSourceVectorType().getElementType(),
285 /*scalableDims=*/{isParallelDimScalable});
286 acc = vector::ShapeCastOp::create(rewriter, loc, accType, acc);
287 }
288 // 6. Creates the flattened form of vector.multi_reduction with inner/outer
289 // most dim as reduction.
290 Operation *newMultiDimRedOp = vector::MultiDimReductionOp::create(
291 rewriter, loc, cast, acc, mask, multiReductionOp.getKind(),
292 multiReductionOp.getFastmath());
293 newMultiDimRedOp =
294 mlir::vector::maskOperation(rewriter, newMultiDimRedOp, newVectorMask);
295
296 // 7. If there are no parallel shapes, the result is a scalar.
297 // TODO: support 0-d vectors when available.
298 if (parallelShapes.empty()) {
299 rewriter.replaceOp(rootOp, newMultiDimRedOp->getResult(0));
300 return success();
301 }
302
303 // 8. Shape cast the flattened result back to the original n-D parallel
304 // shape.
305 VectorType outputCastedType = VectorType::get(
306 parallelShapes, multiReductionOp.getSourceVectorType().getElementType(),
307 parallelScalableDims);
308 rewriter.replaceOpWithNewOp<vector::ShapeCastOp>(
309 rootOp, outputCastedType, newMultiDimRedOp->getResult(0));
310 return success();
311 }
312
313private:
314 const bool useInnerDimsForReduction;
315};
316
317/// Lowers 2D vector.multi_reduction to a squence of Arith Ops
318///
319/// The reduction dimension must be the outer-most dimension.
320///
321/// BEFORE:
322///
323/// %1 = vector.multi_reduction <mul>, %src, %acc [0] : vector<4x2xf32> to
324/// vector<2xf32>
325///
326/// AFTER:
327///
328/// // Prod 1.
329/// %vec_0 = vector.extract %src[0] : vector<2xf32> from vector<4x2xf32>
330/// %mul_0 = arith.mulf %vec_0, %acc : vector<2xf32>
331///
332/// // Prod 2.
333/// %vec_1 = vector.extract %src[1] : vector<2xf32> from vector<4x2xf32>
334/// %mul_2 = arith.mulf %vec_1, %mul_0 : vector<2xf32>
335///
336/// // Prod 3.
337/// %vec_3 = vector.extract %src[2] : vector<2xf32> from vector<4x2xf32>
338/// %mul_3 = arith.mulf %vec_3, %mul_2 : vector<2xf32>
339///
340/// // Prod 4.
341/// %vec_4 = vector.extract %src[3] : vector<2xf32> from vector<4x2xf32>
342/// %res = arith.mulf %vec_4, %mul_3 : vector<2xf32>
343struct TwoDimMultiReductionToElementWise
344 : public vector::MaskableOpRewritePattern<vector::MultiDimReductionOp> {
345 using MaskableOpRewritePattern::MaskableOpRewritePattern;
346
347 FailureOr<Value>
348 matchAndRewriteMaskableOp(vector::MultiDimReductionOp multiReductionOp,
349 vector::MaskingOpInterface maskingOp,
350 PatternRewriter &rewriter) const override {
351 auto srcRank = multiReductionOp.getSourceVectorType().getRank();
352 // Rank-2 ["parallel", "reduce"] or bail.
353 if (srcRank != 2)
354 return failure();
355
356 if (multiReductionOp.isReducedDim(1) || !multiReductionOp.isReducedDim(0))
357 return failure();
358
359 Value mask = maskingOp ? maskingOp.getMask() : Value();
360
361 auto loc = multiReductionOp.getLoc();
362 Value source = multiReductionOp.getSource();
363 ArrayRef<int64_t> srcShape =
364 multiReductionOp.getSourceVectorType().getShape();
365 int outerDim = srcShape[0];
366
367 Value result = multiReductionOp.getAcc();
368 for (int64_t i = 0; i < outerDim; i++) {
369 auto v = vector::ExtractOp::create(rewriter, loc, source, i);
370 Value m = mask ? Value(vector::ExtractOp::create(rewriter, loc, mask, i))
371 : nullptr;
372 result =
373 makeArithReduction(rewriter, loc, multiReductionOp.getKind(), v,
374 result, multiReductionOp.getFastmathAttr(), m);
375 }
376
377 return result;
378 }
379};
380
381/// Lowers 2D vector.multi_reduction to a sequence of vector.reduction Ops.
382///
383/// The reduction dimension must be the inner-most dimension.
384///
385/// BEFORE:
386/// vector.multi_reduction <mul>, %src, %acc [1] : vector<2x4xf32> to
387/// vector<2xf32>
388///
389/// AFTER:
390/// // 1st reduction
391/// %v_0 = vector.extract %src[0] : vector<4xf32> from vector<2x4xf32>
392/// %a_0 = vector.extract %acc[0] : f32 from vector<2xf32>
393/// %red_1 = vector.reduction <mul>, %v_0, %a_1 : vector<4xf32> into f32
394/// %res_tmp = vector.insert %red_1, %res [0] : f32 into vector<2xf32>
395///
396/// // 2nd reduction
397/// %v_1 = vector.extract %src[1] : vector<4xf32> from vector<2x4xf32>
398/// %a_1 = vector.extract %acc[1] : f32 from vector<2xf32>
399/// %red_2 = vector.reduction <mul>, %v_1, %a_1 : vector<4xf32> into f32
400/// %res_final = vector.insert %red_2, %res_tmp [1] : f32 into vector<2xf32>
401struct TwoDimMultiReductionToReduction
402 : public vector::MaskableOpRewritePattern<vector::MultiDimReductionOp> {
403 using MaskableOpRewritePattern::MaskableOpRewritePattern;
404
405 FailureOr<Value>
406 matchAndRewriteMaskableOp(vector::MultiDimReductionOp multiReductionOp,
407 vector::MaskingOpInterface maskingOp,
408 PatternRewriter &rewriter) const override {
409 auto srcRank = multiReductionOp.getSourceVectorType().getRank();
410 // Rank-2 ["reduce", "parallel"] or bail.
411 if (srcRank != 2)
412 return failure();
413
414 if (multiReductionOp.isReducedDim(0) || !multiReductionOp.isReducedDim(1))
415 return failure();
416
417 Value mask = maskingOp ? maskingOp.getMask() : nullptr;
418
419 auto loc = multiReductionOp.getLoc();
420 Value source = multiReductionOp.getSource();
421 Value acc = multiReductionOp.getAcc();
422 int outerDim = multiReductionOp.getSourceVectorType().getShape()[0];
423
424 Value result = arith::ConstantOp::create(
425 rewriter, loc, multiReductionOp.getDestType(),
426 rewriter.getZeroAttr(multiReductionOp.getDestType()));
427
428 SmallVector<Value> vectors(outerDim);
429 for (int64_t i = 0; i < outerDim; ++i) {
430 Value v = vector::ExtractOp::create(rewriter, loc, source, i);
431 Value a = vector::ExtractOp::create(rewriter, loc, acc, i);
432
433 Operation *reductionOp =
434 vector::ReductionOp::create(rewriter, loc, multiReductionOp.getKind(),
435 v, a, multiReductionOp.getFastmath());
436
437 if (mask) {
438 Value m = vector::ExtractOp::create(rewriter, loc, mask, i);
439 reductionOp = mlir::vector::maskOperation(rewriter, reductionOp, m);
440 }
441
442 result = vector::InsertOp::create(rewriter, loc,
443 reductionOp->getResult(0), result, i);
444 }
445
446 return result;
447 }
448};
449
450/// Converts 1D vector.multi_reduction directly to vector.reduction.
451///
452/// Example:
453/// ```mlir
454/// // Before
455/// %r = vector.multi_reduction <add>, %v, %acc [0] : vector<Nxf32> to f32
456///
457/// // After
458/// %r = vector.reduction <add>, %v, %acc : vector<Nxf32> into f32
459/// ```
460struct OneDimMultiReductionToReduction
461 : public vector::MaskableOpRewritePattern<vector::MultiDimReductionOp> {
462 using MaskableOpRewritePattern::MaskableOpRewritePattern;
463
464 FailureOr<Value>
465 matchAndRewriteMaskableOp(vector::MultiDimReductionOp multiReductionOp,
466 vector::MaskingOpInterface maskingOp,
467 PatternRewriter &rewriter) const override {
468 auto srcRank = multiReductionOp.getSourceVectorType().getRank();
469 if (srcRank != 1)
470 return failure();
471
472 if (!multiReductionOp.isReducedDim(0))
473 return failure();
474
475 auto loc = multiReductionOp.getLoc();
476 Value mask = maskingOp ? maskingOp.getMask() : Value();
477
478 Operation *reductionOp = vector::ReductionOp::create(
479 rewriter, loc, multiReductionOp.getKind(), multiReductionOp.getSource(),
480 multiReductionOp.getAcc(), multiReductionOp.getFastmath());
481
482 if (mask)
483 reductionOp = mlir::vector::maskOperation(rewriter, reductionOp, mask);
484
485 return reductionOp->getResult(0);
486 }
487};
488
489struct LowerVectorMultiReductionPass
491 LowerVectorMultiReductionPass> {
492 LowerVectorMultiReductionPass(vector::VectorMultiReductionLowering option) {
493 this->loweringStrategy = option;
494 }
495
496 void runOnOperation() override {
497 Operation *op = getOperation();
498 MLIRContext *context = op->getContext();
499
500 RewritePatternSet patterns(context);
502 patterns, this->loweringStrategy);
503 if (failed(applyPatternsGreedily(op, std::move(patterns))))
504 signalPassFailure();
505
506 RewritePatternSet flatteningPatterns(context);
508 flatteningPatterns, this->loweringStrategy);
509 if (failed(applyPatternsGreedily(op, std::move(flatteningPatterns))))
510 signalPassFailure();
511
512 RewritePatternSet unrollingPatterns(context);
514 unrollingPatterns, this->loweringStrategy);
515 if (failed(applyPatternsGreedily(op, std::move(unrollingPatterns))))
516 signalPassFailure();
517 }
518
519 void getDependentDialects(DialectRegistry &registry) const override {
520 registry.insert<vector::VectorDialect>();
521 }
522};
523
524} // namespace
525
527 RewritePatternSet &patterns, VectorMultiReductionLowering options,
528 PatternBenefit benefit) {
529 patterns.add<InnerOuterDimReductionConversion>(patterns.getContext(), options,
530 benefit);
531}
532
534 RewritePatternSet &patterns, VectorMultiReductionLowering options,
535 PatternBenefit benefit) {
536 patterns.add<FlattenMultiReduction>(patterns.getContext(), options, benefit);
537}
538
540 RewritePatternSet &patterns, VectorMultiReductionLowering options,
541 PatternBenefit benefit) {
542 patterns.add<OneDimMultiReductionToReduction>(patterns.getContext(), benefit);
543 if (options == VectorMultiReductionLowering ::InnerReduction)
544 patterns.add<TwoDimMultiReductionToReduction>(patterns.getContext(),
545 benefit);
546 else
547 patterns.add<TwoDimMultiReductionToElementWise>(patterns.getContext(),
548 benefit);
549}
550
552 vector::VectorMultiReductionLowering option) {
553 return std::make_unique<LowerVectorMultiReductionPass>(option);
554}
return success()
static llvm::ManagedStatic< PassManagerOptions > options
static std::optional< VectorShape > vectorShape(Type type)
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
Definition SPIRVOps.cpp:229
TypedAttr getZeroAttr(Type type)
Definition Builders.cpp:333
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:71
RAII guard to reset the insertion point of the builder when destroyed.
Definition Builders.h:351
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Definition Builders.h:401
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition Operation.h:434
Location getLoc()
The source location the operation was defined or derived from.
Definition Operation.h:240
MLIRContext * getContext()
Return the context this operation is associated with.
Definition Operation.h:233
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Type getType() const
Return the type of this value.
Definition Value.h:105
Location getLoc() const
Return the location of this value.
Definition Value.cpp:24
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:853
Value makeArithReduction(OpBuilder &b, Location loc, CombiningKind kind, Value v1, Value acc, arith::FastMathFlagsAttr fastmath=nullptr, Value mask=nullptr)
Returns the result value of reducing two scalar/vector values with the corresponding arith operation.
Operation * maskOperation(OpBuilder &builder, Operation *maskableOp, Value mask, Value passthru=Value())
Creates a vector.mask operation around a maskable operation.
std::unique_ptr< Pass > createLowerVectorMultiReductionPass(VectorMultiReductionLowering option=VectorMultiReductionLowering::InnerParallel)
Creates an instance of the vector.multi_reduction lowering pass.
void populateVectorMultiReductionUnrollingPatterns(RewritePatternSet &patterns, VectorMultiReductionLowering options, PatternBenefit benefit=1)
Populate the pattern set with the following patterns:
void populateVectorMultiReductionFlatteningPatterns(RewritePatternSet &patterns, VectorMultiReductionLowering options, PatternBenefit benefit=1)
Populate the pattern set with the following patterns:
void populateVectorMultiReductionReorderPatterns(RewritePatternSet &patterns, VectorMultiReductionLowering options, PatternBenefit benefit=1)
Populate the pattern set with the following patterns:
Include the generated interface declarations.
LogicalResult applyPatternsGreedily(Region &region, const FrozenRewritePatternSet &patterns, GreedyRewriteConfig config=GreedyRewriteConfig(), bool *changed=nullptr)
Rewrite ops in the given region, which must be isolated from above, by repeatedly applying the highes...
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
A pattern for ops that implement MaskableOpInterface and that might be masked (i.e.