Alex Zinenko | 971b8dd | 2019-11-14 18:34:46 | [diff] [blame] | 1 | //===- AffineToStandard.cpp - Lower affine constructs to primitives -------===// |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 2 | // |
Mehdi Amini | 3085710 | 2020-01-26 03:58:30 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
Mehdi Amini | 56222a0 | 2019-12-23 17:35:36 | [diff] [blame] | 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 6 | // |
Mehdi Amini | 56222a0 | 2019-12-23 17:35:36 | [diff] [blame] | 7 | //===----------------------------------------------------------------------===// |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 8 | // |
Alex Zinenko | 0c4ee54 | 2019-01-02 20:52:41 | [diff] [blame] | 9 | // This file lowers affine constructs (If and For statements, AffineApply |
Nicolas Vasilache | cab671d | 2019-07-12 13:48:45 | [diff] [blame] | 10 | // operations) within a function into their standard If and For equivalent ops. |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
Alex Zinenko | 971b8dd | 2019-11-14 18:34:46 | [diff] [blame] | 14 | #include "mlir/Conversion/AffineToStandard/AffineToStandard.h" |
| 15 | |
River Riddle | 1834ad4a | 2020-04-07 20:58:12 | [diff] [blame] | 16 | #include "../PassDetail.h" |
Rob Suderman | e708471 | 2020-03-20 21:18:47 | [diff] [blame] | 17 | #include "mlir/Dialect/Affine/IR/AffineOps.h" |
Uday Bondhugula | 8d12bf4 | 2022-02-10 04:26:10 | [diff] [blame] | 18 | #include "mlir/Dialect/Affine/Utils.h" |
River Riddle | 23aa5a7 | 2022-02-26 22:49:54 | [diff] [blame^] | 19 | #include "mlir/Dialect/Func/IR/FuncOps.h" |
Julian Gross | e231070 | 2021-02-10 12:53:11 | [diff] [blame] | 20 | #include "mlir/Dialect/MemRef/IR/MemRef.h" |
Alex Zinenko | c25b20c | 2020-05-11 13:00:48 | [diff] [blame] | 21 | #include "mlir/Dialect/SCF/SCF.h" |
Matthias Springer | 99ef9ee | 2022-01-31 10:10:51 | [diff] [blame] | 22 | #include "mlir/Dialect/Vector/IR/VectorOps.h" |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 23 | #include "mlir/IR/BlockAndValueMapping.h" |
River Riddle | 5052bd8 | 2019-02-02 00:42:18 | [diff] [blame] | 24 | #include "mlir/IR/IntegerSet.h" |
Alex Zinenko | 0c4ee54 | 2019-01-02 20:52:41 | [diff] [blame] | 25 | #include "mlir/IR/MLIRContext.h" |
River Riddle | 48ccae2 | 2019-02-20 01:17:46 | [diff] [blame] | 26 | #include "mlir/Pass/Pass.h" |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 27 | #include "mlir/Transforms/DialectConversion.h" |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 28 | #include "mlir/Transforms/Passes.h" |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 29 | |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 30 | using namespace mlir; |
Diego Caballero | bc5565f | 2020-05-14 19:05:46 | [diff] [blame] | 31 | using namespace mlir::vector; |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 32 | |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 33 | /// Given a range of values, emit the code that reduces them with "min" or "max" |
| 34 | /// depending on the provided comparison predicate. The predicate defines which |
| 35 | /// comparison to perform, "lt" for "min", "gt" for "max" and is used for the |
| 36 | /// `cmpi` operation followed by the `select` operation: |
| 37 | /// |
Mogball | a54f4ea | 2021-10-12 23:14:57 | [diff] [blame] | 38 | /// %cond = arith.cmpi "predicate" %v0, %v1 |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 39 | /// %result = select %cond, %v0, %v1 |
| 40 | /// |
| 41 | /// Multiple values are scanned in a linear sequence. This creates a data |
| 42 | /// dependences that wouldn't exist in a tree reduction, but is easier to |
| 43 | /// recognize as a reduction by the subsequent passes. |
Mogball | a54f4ea | 2021-10-12 23:14:57 | [diff] [blame] | 44 | static Value buildMinMaxReductionSeq(Location loc, |
| 45 | arith::CmpIPredicate predicate, |
Alex Zinenko | 8ed47b7 | 2020-01-28 10:53:00 | [diff] [blame] | 46 | ValueRange values, OpBuilder &builder) { |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 47 | assert(!llvm::empty(values) && "empty min/max chain"); |
| 48 | |
| 49 | auto valueIt = values.begin(); |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 50 | Value value = *valueIt++; |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 51 | for (; valueIt != values.end(); ++valueIt) { |
Mogball | a54f4ea | 2021-10-12 23:14:57 | [diff] [blame] | 52 | auto cmpOp = builder.create<arith::CmpIOp>(loc, predicate, value, *valueIt); |
River Riddle | dec8af7 | 2022-01-31 20:44:35 | [diff] [blame] | 53 | value = builder.create<arith::SelectOp>(loc, cmpOp.getResult(), value, |
| 54 | *valueIt); |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | return value; |
| 58 | } |
| 59 | |
Kazuaki Ishizaki | e5a8512 | 2020-03-26 18:51:37 | [diff] [blame] | 60 | /// Emit instructions that correspond to computing the maximum value among the |
OuHangKresnik | 5c3b349 | 2020-02-06 09:25:55 | [diff] [blame] | 61 | /// values of a (potentially) multi-output affine map applied to `operands`. |
| 62 | static Value lowerAffineMapMax(OpBuilder &builder, Location loc, AffineMap map, |
| 63 | ValueRange operands) { |
| 64 | if (auto values = expandAffineMap(builder, loc, map, operands)) |
Mogball | a54f4ea | 2021-10-12 23:14:57 | [diff] [blame] | 65 | return buildMinMaxReductionSeq(loc, arith::CmpIPredicate::sgt, *values, |
| 66 | builder); |
OuHangKresnik | 5c3b349 | 2020-02-06 09:25:55 | [diff] [blame] | 67 | return nullptr; |
Alex Zinenko | ee6f84a | 2019-06-14 08:56:19 | [diff] [blame] | 68 | } |
| 69 | |
Kazuaki Ishizaki | e5a8512 | 2020-03-26 18:51:37 | [diff] [blame] | 70 | /// Emit instructions that correspond to computing the minimum value among the |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 71 | /// values of a (potentially) multi-output affine map applied to `operands`. |
Alex Zinenko | 51ba5b5 | 2020-01-27 16:14:56 | [diff] [blame] | 72 | static Value lowerAffineMapMin(OpBuilder &builder, Location loc, AffineMap map, |
| 73 | ValueRange operands) { |
Alex Zinenko | 8ed47b7 | 2020-01-28 10:53:00 | [diff] [blame] | 74 | if (auto values = expandAffineMap(builder, loc, map, operands)) |
Mogball | a54f4ea | 2021-10-12 23:14:57 | [diff] [blame] | 75 | return buildMinMaxReductionSeq(loc, arith::CmpIPredicate::slt, *values, |
| 76 | builder); |
Alex Zinenko | 51ba5b5 | 2020-01-27 16:14:56 | [diff] [blame] | 77 | return nullptr; |
| 78 | } |
| 79 | |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 80 | /// Emit instructions that correspond to the affine map in the upper bound |
| 81 | /// applied to the respective operands, and compute the minimum value across |
| 82 | /// the results. |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 83 | Value mlir::lowerAffineUpperBound(AffineForOp op, OpBuilder &builder) { |
Alex Zinenko | 51ba5b5 | 2020-01-27 16:14:56 | [diff] [blame] | 84 | return lowerAffineMapMin(builder, op.getLoc(), op.getUpperBoundMap(), |
| 85 | op.getUpperBoundOperands()); |
Alex Zinenko | ee6f84a | 2019-06-14 08:56:19 | [diff] [blame] | 86 | } |
| 87 | |
OuHangKresnik | 5c3b349 | 2020-02-06 09:25:55 | [diff] [blame] | 88 | /// Emit instructions that correspond to the affine map in the lower bound |
| 89 | /// applied to the respective operands, and compute the maximum value across |
| 90 | /// the results. |
| 91 | Value mlir::lowerAffineLowerBound(AffineForOp op, OpBuilder &builder) { |
| 92 | return lowerAffineMapMax(builder, op.getLoc(), op.getLowerBoundMap(), |
| 93 | op.getLowerBoundOperands()); |
| 94 | } |
| 95 | |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 96 | namespace { |
Alex Zinenko | 51ba5b5 | 2020-01-27 16:14:56 | [diff] [blame] | 97 | class AffineMinLowering : public OpRewritePattern<AffineMinOp> { |
| 98 | public: |
| 99 | using OpRewritePattern<AffineMinOp>::OpRewritePattern; |
| 100 | |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 101 | LogicalResult matchAndRewrite(AffineMinOp op, |
| 102 | PatternRewriter &rewriter) const override { |
Alex Zinenko | 51ba5b5 | 2020-01-27 16:14:56 | [diff] [blame] | 103 | Value reduced = |
| 104 | lowerAffineMapMin(rewriter, op.getLoc(), op.map(), op.operands()); |
| 105 | if (!reduced) |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 106 | return failure(); |
Alex Zinenko | 51ba5b5 | 2020-01-27 16:14:56 | [diff] [blame] | 107 | |
| 108 | rewriter.replaceOp(op, reduced); |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 109 | return success(); |
Alex Zinenko | 51ba5b5 | 2020-01-27 16:14:56 | [diff] [blame] | 110 | } |
| 111 | }; |
| 112 | |
OuHangKresnik | 5c3b349 | 2020-02-06 09:25:55 | [diff] [blame] | 113 | class AffineMaxLowering : public OpRewritePattern<AffineMaxOp> { |
| 114 | public: |
| 115 | using OpRewritePattern<AffineMaxOp>::OpRewritePattern; |
| 116 | |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 117 | LogicalResult matchAndRewrite(AffineMaxOp op, |
| 118 | PatternRewriter &rewriter) const override { |
OuHangKresnik | 5c3b349 | 2020-02-06 09:25:55 | [diff] [blame] | 119 | Value reduced = |
| 120 | lowerAffineMapMax(rewriter, op.getLoc(), op.map(), op.operands()); |
| 121 | if (!reduced) |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 122 | return failure(); |
OuHangKresnik | 5c3b349 | 2020-02-06 09:25:55 | [diff] [blame] | 123 | |
| 124 | rewriter.replaceOp(op, reduced); |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 125 | return success(); |
OuHangKresnik | 5c3b349 | 2020-02-06 09:25:55 | [diff] [blame] | 126 | } |
| 127 | }; |
| 128 | |
Jeremy Bruestle | 2ede891 | 2020-07-09 19:02:20 | [diff] [blame] | 129 | /// Affine yields ops are removed. |
| 130 | class AffineYieldOpLowering : public OpRewritePattern<AffineYieldOp> { |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 131 | public: |
Jeremy Bruestle | 2ede891 | 2020-07-09 19:02:20 | [diff] [blame] | 132 | using OpRewritePattern<AffineYieldOp>::OpRewritePattern; |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 133 | |
Jeremy Bruestle | 2ede891 | 2020-07-09 19:02:20 | [diff] [blame] | 134 | LogicalResult matchAndRewrite(AffineYieldOp op, |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 135 | PatternRewriter &rewriter) const override { |
Christian Sigg | badc760 | 2021-01-06 20:26:59 | [diff] [blame] | 136 | if (isa<scf::ParallelOp>(op->getParentOp())) { |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 137 | // scf.parallel does not yield any values via its terminator scf.yield but |
| 138 | // models reductions differently using additional ops in its region. |
| 139 | rewriter.replaceOpWithNewOp<scf::YieldOp>(op); |
| 140 | return success(); |
| 141 | } |
| 142 | rewriter.replaceOpWithNewOp<scf::YieldOp>(op, op.operands()); |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 143 | return success(); |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 144 | } |
| 145 | }; |
| 146 | |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 147 | class AffineForLowering : public OpRewritePattern<AffineForOp> { |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 148 | public: |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 149 | using OpRewritePattern<AffineForOp>::OpRewritePattern; |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 150 | |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 151 | LogicalResult matchAndRewrite(AffineForOp op, |
| 152 | PatternRewriter &rewriter) const override { |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 153 | Location loc = op.getLoc(); |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 154 | Value lowerBound = lowerAffineLowerBound(op, rewriter); |
| 155 | Value upperBound = lowerAffineUpperBound(op, rewriter); |
Mogball | a54f4ea | 2021-10-12 23:14:57 | [diff] [blame] | 156 | Value step = rewriter.create<arith::ConstantIndexOp>(loc, op.getStep()); |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 157 | auto scfForOp = rewriter.create<scf::ForOp>(loc, lowerBound, upperBound, |
| 158 | step, op.getIterOperands()); |
| 159 | rewriter.eraseBlock(scfForOp.getBody()); |
Jacques Pienaar | c0342a2 | 2021-12-20 16:03:43 | [diff] [blame] | 160 | rewriter.inlineRegionBefore(op.region(), scfForOp.getRegion(), |
| 161 | scfForOp.getRegion().end()); |
| 162 | rewriter.replaceOp(op, scfForOp.getResults()); |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 163 | return success(); |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 164 | } |
| 165 | }; |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 166 | |
Yash Jain | 3382b71 | 2020-07-18 07:39:30 | [diff] [blame] | 167 | /// Convert an `affine.parallel` (loop nest) operation into a `scf.parallel` |
| 168 | /// operation. |
| 169 | class AffineParallelLowering : public OpRewritePattern<AffineParallelOp> { |
| 170 | public: |
| 171 | using OpRewritePattern<AffineParallelOp>::OpRewritePattern; |
| 172 | |
| 173 | LogicalResult matchAndRewrite(AffineParallelOp op, |
| 174 | PatternRewriter &rewriter) const override { |
| 175 | Location loc = op.getLoc(); |
| 176 | SmallVector<Value, 8> steps; |
| 177 | SmallVector<Value, 8> upperBoundTuple; |
| 178 | SmallVector<Value, 8> lowerBoundTuple; |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 179 | SmallVector<Value, 8> identityVals; |
Alex Zinenko | 6841e6a | 2021-04-29 11:15:21 | [diff] [blame] | 180 | // Emit IR computing the lower and upper bound by expanding the map |
| 181 | // expression. |
| 182 | lowerBoundTuple.reserve(op.getNumDims()); |
| 183 | upperBoundTuple.reserve(op.getNumDims()); |
| 184 | for (unsigned i = 0, e = op.getNumDims(); i < e; ++i) { |
| 185 | Value lower = lowerAffineMapMax(rewriter, loc, op.getLowerBoundMap(i), |
| 186 | op.getLowerBoundsOperands()); |
| 187 | if (!lower) |
| 188 | return rewriter.notifyMatchFailure(op, "couldn't convert lower bounds"); |
| 189 | lowerBoundTuple.push_back(lower); |
| 190 | |
| 191 | Value upper = lowerAffineMapMin(rewriter, loc, op.getUpperBoundMap(i), |
| 192 | op.getUpperBoundsOperands()); |
| 193 | if (!upper) |
| 194 | return rewriter.notifyMatchFailure(op, "couldn't convert upper bounds"); |
| 195 | upperBoundTuple.push_back(upper); |
| 196 | } |
Yash Jain | 3382b71 | 2020-07-18 07:39:30 | [diff] [blame] | 197 | steps.reserve(op.steps().size()); |
| 198 | for (Attribute step : op.steps()) |
Mogball | a54f4ea | 2021-10-12 23:14:57 | [diff] [blame] | 199 | steps.push_back(rewriter.create<arith::ConstantIndexOp>( |
Yash Jain | 3382b71 | 2020-07-18 07:39:30 | [diff] [blame] | 200 | loc, step.cast<IntegerAttr>().getInt())); |
Alex Zinenko | 6841e6a | 2021-04-29 11:15:21 | [diff] [blame] | 201 | |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 202 | // Get the terminator op. |
| 203 | Operation *affineParOpTerminator = op.getBody()->getTerminator(); |
| 204 | scf::ParallelOp parOp; |
| 205 | if (op.results().empty()) { |
| 206 | // Case with no reduction operations/return values. |
| 207 | parOp = rewriter.create<scf::ParallelOp>(loc, lowerBoundTuple, |
| 208 | upperBoundTuple, steps, |
| 209 | /*bodyBuilderFn=*/nullptr); |
| 210 | rewriter.eraseBlock(parOp.getBody()); |
Jacques Pienaar | c0342a2 | 2021-12-20 16:03:43 | [diff] [blame] | 211 | rewriter.inlineRegionBefore(op.region(), parOp.getRegion(), |
| 212 | parOp.getRegion().end()); |
| 213 | rewriter.replaceOp(op, parOp.getResults()); |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 214 | return success(); |
| 215 | } |
| 216 | // Case with affine.parallel with reduction operations/return values. |
| 217 | // scf.parallel handles the reduction operation differently unlike |
| 218 | // affine.parallel. |
| 219 | ArrayRef<Attribute> reductions = op.reductions().getValue(); |
Alex Zinenko | 7dc7790 | 2021-04-06 10:53:04 | [diff] [blame] | 220 | for (auto pair : llvm::zip(reductions, op.getResultTypes())) { |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 221 | // For each of the reduction operations get the identity values for |
| 222 | // initialization of the result values. |
Alex Zinenko | 7dc7790 | 2021-04-06 10:53:04 | [diff] [blame] | 223 | Attribute reduction = std::get<0>(pair); |
| 224 | Type resultType = std::get<1>(pair); |
William S. Moses | a6a583d | 2021-12-30 05:59:58 | [diff] [blame] | 225 | Optional<arith::AtomicRMWKind> reductionOp = |
| 226 | arith::symbolizeAtomicRMWKind( |
| 227 | static_cast<uint64_t>(reduction.cast<IntegerAttr>().getInt())); |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 228 | assert(reductionOp.hasValue() && |
| 229 | "Reduction operation cannot be of None Type"); |
William S. Moses | a6a583d | 2021-12-30 05:59:58 | [diff] [blame] | 230 | arith::AtomicRMWKind reductionOpValue = reductionOp.getValue(); |
Alex Zinenko | 7dc7790 | 2021-04-06 10:53:04 | [diff] [blame] | 231 | identityVals.push_back( |
William S. Moses | a6a583d | 2021-12-30 05:59:58 | [diff] [blame] | 232 | arith::getIdentityValue(reductionOpValue, resultType, rewriter, loc)); |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 233 | } |
| 234 | parOp = rewriter.create<scf::ParallelOp>( |
| 235 | loc, lowerBoundTuple, upperBoundTuple, steps, identityVals, |
| 236 | /*bodyBuilderFn=*/nullptr); |
| 237 | |
| 238 | // Copy the body of the affine.parallel op. |
| 239 | rewriter.eraseBlock(parOp.getBody()); |
Jacques Pienaar | c0342a2 | 2021-12-20 16:03:43 | [diff] [blame] | 240 | rewriter.inlineRegionBefore(op.region(), parOp.getRegion(), |
| 241 | parOp.getRegion().end()); |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 242 | assert(reductions.size() == affineParOpTerminator->getNumOperands() && |
| 243 | "Unequal number of reductions and operands."); |
| 244 | for (unsigned i = 0, end = reductions.size(); i < end; i++) { |
| 245 | // For each of the reduction operations get the respective mlir::Value. |
William S. Moses | a6a583d | 2021-12-30 05:59:58 | [diff] [blame] | 246 | Optional<arith::AtomicRMWKind> reductionOp = |
| 247 | arith::symbolizeAtomicRMWKind( |
| 248 | reductions[i].cast<IntegerAttr>().getInt()); |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 249 | assert(reductionOp.hasValue() && |
| 250 | "Reduction Operation cannot be of None Type"); |
William S. Moses | a6a583d | 2021-12-30 05:59:58 | [diff] [blame] | 251 | arith::AtomicRMWKind reductionOpValue = reductionOp.getValue(); |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 252 | rewriter.setInsertionPoint(&parOp.getBody()->back()); |
| 253 | auto reduceOp = rewriter.create<scf::ReduceOp>( |
| 254 | loc, affineParOpTerminator->getOperand(i)); |
Jacques Pienaar | c0342a2 | 2021-12-20 16:03:43 | [diff] [blame] | 255 | rewriter.setInsertionPointToEnd(&reduceOp.getReductionOperator().front()); |
William S. Moses | a6a583d | 2021-12-30 05:59:58 | [diff] [blame] | 256 | Value reductionResult = arith::getReductionOp( |
Jacques Pienaar | c0342a2 | 2021-12-20 16:03:43 | [diff] [blame] | 257 | reductionOpValue, rewriter, loc, |
| 258 | reduceOp.getReductionOperator().front().getArgument(0), |
| 259 | reduceOp.getReductionOperator().front().getArgument(1)); |
Prateek Gupta | 3e07b0b | 2020-12-22 16:10:17 | [diff] [blame] | 260 | rewriter.create<scf::ReduceReturnOp>(loc, reductionResult); |
| 261 | } |
Jacques Pienaar | c0342a2 | 2021-12-20 16:03:43 | [diff] [blame] | 262 | rewriter.replaceOp(op, parOp.getResults()); |
Yash Jain | 3382b71 | 2020-07-18 07:39:30 | [diff] [blame] | 263 | return success(); |
| 264 | } |
| 265 | }; |
| 266 | |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 267 | class AffineIfLowering : public OpRewritePattern<AffineIfOp> { |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 268 | public: |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 269 | using OpRewritePattern<AffineIfOp>::OpRewritePattern; |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 270 | |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 271 | LogicalResult matchAndRewrite(AffineIfOp op, |
| 272 | PatternRewriter &rewriter) const override { |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 273 | auto loc = op.getLoc(); |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 274 | |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 275 | // Now we just have to handle the condition logic. |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 276 | auto integerSet = op.getIntegerSet(); |
Mogball | a54f4ea | 2021-10-12 23:14:57 | [diff] [blame] | 277 | Value zeroConstant = rewriter.create<arith::ConstantIndexOp>(loc, 0); |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 278 | SmallVector<Value, 8> operands(op.getOperands()); |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 279 | auto operandsRef = llvm::makeArrayRef(operands); |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 280 | |
Nicolas Vasilache | cab671d | 2019-07-12 13:48:45 | [diff] [blame] | 281 | // Calculate cond as a conjunction without short-circuiting. |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 282 | Value cond = nullptr; |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 283 | for (unsigned i = 0, e = integerSet.getNumConstraints(); i < e; ++i) { |
| 284 | AffineExpr constraintExpr = integerSet.getConstraint(i); |
| 285 | bool isEquality = integerSet.isEq(i); |
| 286 | |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 287 | // Build and apply an affine expression |
| 288 | auto numDims = integerSet.getNumDims(); |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 289 | Value affResult = expandAffineExpr(rewriter, loc, constraintExpr, |
| 290 | operandsRef.take_front(numDims), |
| 291 | operandsRef.drop_front(numDims)); |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 292 | if (!affResult) |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 293 | return failure(); |
Mogball | a54f4ea | 2021-10-12 23:14:57 | [diff] [blame] | 294 | auto pred = |
| 295 | isEquality ? arith::CmpIPredicate::eq : arith::CmpIPredicate::sge; |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 296 | Value cmpVal = |
Mogball | a54f4ea | 2021-10-12 23:14:57 | [diff] [blame] | 297 | rewriter.create<arith::CmpIOp>(loc, pred, affResult, zeroConstant); |
| 298 | cond = cond |
| 299 | ? rewriter.create<arith::AndIOp>(loc, cond, cmpVal).getResult() |
| 300 | : cmpVal; |
Nicolas Vasilache | cab671d | 2019-07-12 13:48:45 | [diff] [blame] | 301 | } |
| 302 | cond = cond ? cond |
Mogball | a54f4ea | 2021-10-12 23:14:57 | [diff] [blame] | 303 | : rewriter.create<arith::ConstantIntOp>(loc, /*value=*/1, |
| 304 | /*width=*/1); |
Nicolas Vasilache | cab671d | 2019-07-12 13:48:45 | [diff] [blame] | 305 | |
Nicolas Vasilache | 0002e29 | 2019-07-16 19:20:15 | [diff] [blame] | 306 | bool hasElseRegion = !op.elseRegion().empty(); |
Gaurav Shukla | 8e3075c | 2021-03-17 10:18:33 | [diff] [blame] | 307 | auto ifOp = rewriter.create<scf::IfOp>(loc, op.getResultTypes(), cond, |
| 308 | hasElseRegion); |
Jacques Pienaar | c0342a2 | 2021-12-20 16:03:43 | [diff] [blame] | 309 | rewriter.inlineRegionBefore(op.thenRegion(), &ifOp.getThenRegion().back()); |
| 310 | rewriter.eraseBlock(&ifOp.getThenRegion().back()); |
Nicolas Vasilache | cab671d | 2019-07-12 13:48:45 | [diff] [blame] | 311 | if (hasElseRegion) { |
Jacques Pienaar | c0342a2 | 2021-12-20 16:03:43 | [diff] [blame] | 312 | rewriter.inlineRegionBefore(op.elseRegion(), |
| 313 | &ifOp.getElseRegion().back()); |
| 314 | rewriter.eraseBlock(&ifOp.getElseRegion().back()); |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 315 | } |
| 316 | |
Gaurav Shukla | 8e3075c | 2021-03-17 10:18:33 | [diff] [blame] | 317 | // Replace the Affine IfOp finally. |
Jacques Pienaar | c0342a2 | 2021-12-20 16:03:43 | [diff] [blame] | 318 | rewriter.replaceOp(op, ifOp.getResults()); |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 319 | return success(); |
River Riddle | 7555383 | 2019-01-29 05:23:53 | [diff] [blame] | 320 | } |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 321 | }; |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 322 | |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 323 | /// Convert an "affine.apply" operation into a sequence of arithmetic |
| 324 | /// operations using the StandardOps dialect. |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 325 | class AffineApplyLowering : public OpRewritePattern<AffineApplyOp> { |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 326 | public: |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 327 | using OpRewritePattern<AffineApplyOp>::OpRewritePattern; |
Chris Lattner | b42bea2 | 2019-01-27 17:33:19 | [diff] [blame] | 328 | |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 329 | LogicalResult matchAndRewrite(AffineApplyOp op, |
| 330 | PatternRewriter &rewriter) const override { |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 331 | auto maybeExpandedMap = |
| 332 | expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), |
| 333 | llvm::to_vector<8>(op.getOperands())); |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 334 | if (!maybeExpandedMap) |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 335 | return failure(); |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 336 | rewriter.replaceOp(op, *maybeExpandedMap); |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 337 | return success(); |
River Riddle | 5052bd8 | 2019-02-02 00:42:18 | [diff] [blame] | 338 | } |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 339 | }; |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 340 | |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 341 | /// Apply the affine map from an 'affine.load' operation to its operands, and |
Julian Gross | e231070 | 2021-02-10 12:53:11 | [diff] [blame] | 342 | /// feed the results to a newly created 'memref.load' operation (which replaces |
| 343 | /// the original 'affine.load'). |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 344 | class AffineLoadLowering : public OpRewritePattern<AffineLoadOp> { |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 345 | public: |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 346 | using OpRewritePattern<AffineLoadOp>::OpRewritePattern; |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 347 | |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 348 | LogicalResult matchAndRewrite(AffineLoadOp op, |
| 349 | PatternRewriter &rewriter) const override { |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 350 | // Expand affine map from 'affineLoadOp'. |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 351 | SmallVector<Value, 8> indices(op.getMapOperands()); |
Uday Bondhugula | 47034c4 | 2019-12-18 17:59:37 | [diff] [blame] | 352 | auto resultOperands = |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 353 | expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices); |
Uday Bondhugula | 47034c4 | 2019-12-18 17:59:37 | [diff] [blame] | 354 | if (!resultOperands) |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 355 | return failure(); |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 356 | |
Diego Caballero | ee66e43 | 2021-02-12 17:41:46 | [diff] [blame] | 357 | // Build vector.load memref[expandedMap.results]. |
Julian Gross | e231070 | 2021-02-10 12:53:11 | [diff] [blame] | 358 | rewriter.replaceOpWithNewOp<memref::LoadOp>(op, op.getMemRef(), |
| 359 | *resultOperands); |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 360 | return success(); |
Uday Bondhugula | 47034c4 | 2019-12-18 17:59:37 | [diff] [blame] | 361 | } |
| 362 | }; |
| 363 | |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 364 | /// Apply the affine map from an 'affine.prefetch' operation to its operands, |
Julian Gross | e231070 | 2021-02-10 12:53:11 | [diff] [blame] | 365 | /// and feed the results to a newly created 'memref.prefetch' operation (which |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 366 | /// replaces the original 'affine.prefetch'). |
Uday Bondhugula | 47034c4 | 2019-12-18 17:59:37 | [diff] [blame] | 367 | class AffinePrefetchLowering : public OpRewritePattern<AffinePrefetchOp> { |
| 368 | public: |
| 369 | using OpRewritePattern<AffinePrefetchOp>::OpRewritePattern; |
| 370 | |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 371 | LogicalResult matchAndRewrite(AffinePrefetchOp op, |
| 372 | PatternRewriter &rewriter) const override { |
Uday Bondhugula | 47034c4 | 2019-12-18 17:59:37 | [diff] [blame] | 373 | // Expand affine map from 'affinePrefetchOp'. |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 374 | SmallVector<Value, 8> indices(op.getMapOperands()); |
Uday Bondhugula | 47034c4 | 2019-12-18 17:59:37 | [diff] [blame] | 375 | auto resultOperands = |
| 376 | expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices); |
| 377 | if (!resultOperands) |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 378 | return failure(); |
Uday Bondhugula | 47034c4 | 2019-12-18 17:59:37 | [diff] [blame] | 379 | |
Julian Gross | e231070 | 2021-02-10 12:53:11 | [diff] [blame] | 380 | // Build memref.prefetch memref[expandedMap.results]. |
| 381 | rewriter.replaceOpWithNewOp<memref::PrefetchOp>( |
| 382 | op, op.memref(), *resultOperands, op.isWrite(), op.localityHint(), |
| 383 | op.isDataCache()); |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 384 | return success(); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 385 | } |
| 386 | }; |
| 387 | |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 388 | /// Apply the affine map from an 'affine.store' operation to its operands, and |
Julian Gross | e231070 | 2021-02-10 12:53:11 | [diff] [blame] | 389 | /// feed the results to a newly created 'memref.store' operation (which replaces |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 390 | /// the original 'affine.store'). |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 391 | class AffineStoreLowering : public OpRewritePattern<AffineStoreOp> { |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 392 | public: |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 393 | using OpRewritePattern<AffineStoreOp>::OpRewritePattern; |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 394 | |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 395 | LogicalResult matchAndRewrite(AffineStoreOp op, |
| 396 | PatternRewriter &rewriter) const override { |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 397 | // Expand affine map from 'affineStoreOp'. |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 398 | SmallVector<Value, 8> indices(op.getMapOperands()); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 399 | auto maybeExpandedMap = |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 400 | expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 401 | if (!maybeExpandedMap) |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 402 | return failure(); |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 403 | |
Julian Gross | e231070 | 2021-02-10 12:53:11 | [diff] [blame] | 404 | // Build memref.store valueToStore, memref[expandedMap.results]. |
| 405 | rewriter.replaceOpWithNewOp<memref::StoreOp>( |
Diego Caballero | ee66e43 | 2021-02-12 17:41:46 | [diff] [blame] | 406 | op, op.getValueToStore(), op.getMemRef(), *maybeExpandedMap); |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 407 | return success(); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 408 | } |
| 409 | }; |
| 410 | |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 411 | /// Apply the affine maps from an 'affine.dma_start' operation to each of their |
| 412 | /// respective map operands, and feed the results to a newly created |
Julian Gross | e231070 | 2021-02-10 12:53:11 | [diff] [blame] | 413 | /// 'memref.dma_start' operation (which replaces the original |
| 414 | /// 'affine.dma_start'). |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 415 | class AffineDmaStartLowering : public OpRewritePattern<AffineDmaStartOp> { |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 416 | public: |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 417 | using OpRewritePattern<AffineDmaStartOp>::OpRewritePattern; |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 418 | |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 419 | LogicalResult matchAndRewrite(AffineDmaStartOp op, |
| 420 | PatternRewriter &rewriter) const override { |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 421 | SmallVector<Value, 8> operands(op.getOperands()); |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 422 | auto operandsRef = llvm::makeArrayRef(operands); |
| 423 | |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 424 | // Expand affine map for DMA source memref. |
| 425 | auto maybeExpandedSrcMap = expandAffineMap( |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 426 | rewriter, op.getLoc(), op.getSrcMap(), |
| 427 | operandsRef.drop_front(op.getSrcMemRefOperandIndex() + 1)); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 428 | if (!maybeExpandedSrcMap) |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 429 | return failure(); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 430 | // Expand affine map for DMA destination memref. |
| 431 | auto maybeExpandedDstMap = expandAffineMap( |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 432 | rewriter, op.getLoc(), op.getDstMap(), |
| 433 | operandsRef.drop_front(op.getDstMemRefOperandIndex() + 1)); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 434 | if (!maybeExpandedDstMap) |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 435 | return failure(); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 436 | // Expand affine map for DMA tag memref. |
| 437 | auto maybeExpandedTagMap = expandAffineMap( |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 438 | rewriter, op.getLoc(), op.getTagMap(), |
| 439 | operandsRef.drop_front(op.getTagMemRefOperandIndex() + 1)); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 440 | if (!maybeExpandedTagMap) |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 441 | return failure(); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 442 | |
Julian Gross | e231070 | 2021-02-10 12:53:11 | [diff] [blame] | 443 | // Build memref.dma_start operation with affine map results. |
| 444 | rewriter.replaceOpWithNewOp<memref::DmaStartOp>( |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 445 | op, op.getSrcMemRef(), *maybeExpandedSrcMap, op.getDstMemRef(), |
| 446 | *maybeExpandedDstMap, op.getNumElements(), op.getTagMemRef(), |
| 447 | *maybeExpandedTagMap, op.getStride(), op.getNumElementsPerStride()); |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 448 | return success(); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 449 | } |
| 450 | }; |
| 451 | |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 452 | /// Apply the affine map from an 'affine.dma_wait' operation tag memref, |
Julian Gross | e231070 | 2021-02-10 12:53:11 | [diff] [blame] | 453 | /// and feed the results to a newly created 'memref.dma_wait' operation (which |
Alex Zinenko | 6895a1c | 2020-01-28 09:21:12 | [diff] [blame] | 454 | /// replaces the original 'affine.dma_wait'). |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 455 | class AffineDmaWaitLowering : public OpRewritePattern<AffineDmaWaitOp> { |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 456 | public: |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 457 | using OpRewritePattern<AffineDmaWaitOp>::OpRewritePattern; |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 458 | |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 459 | LogicalResult matchAndRewrite(AffineDmaWaitOp op, |
| 460 | PatternRewriter &rewriter) const override { |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 461 | // Expand affine map for DMA tag memref. |
River Riddle | e62a695 | 2019-12-23 22:45:01 | [diff] [blame] | 462 | SmallVector<Value, 8> indices(op.getTagIndices()); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 463 | auto maybeExpandedTagMap = |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 464 | expandAffineMap(rewriter, op.getLoc(), op.getTagMap(), indices); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 465 | if (!maybeExpandedTagMap) |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 466 | return failure(); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 467 | |
Julian Gross | e231070 | 2021-02-10 12:53:11 | [diff] [blame] | 468 | // Build memref.dma_wait operation with affine map results. |
| 469 | rewriter.replaceOpWithNewOp<memref::DmaWaitOp>( |
River Riddle | 4071578 | 2019-07-15 14:35:00 | [diff] [blame] | 470 | op, op.getTagMemRef(), *maybeExpandedTagMap, op.getNumElements()); |
River Riddle | 3145427 | 2020-03-18 03:07:55 | [diff] [blame] | 471 | return success(); |
Andy Davis | f487d20 | 2019-07-01 15:32:44 | [diff] [blame] | 472 | } |
| 473 | }; |
| 474 | |
Diego Caballero | bc5565f | 2020-05-14 19:05:46 | [diff] [blame] | 475 | /// Apply the affine map from an 'affine.vector_load' operation to its operands, |
Diego Caballero | ee66e43 | 2021-02-12 17:41:46 | [diff] [blame] | 476 | /// and feed the results to a newly created 'vector.load' operation (which |
| 477 | /// replaces the original 'affine.vector_load'). |
Diego Caballero | bc5565f | 2020-05-14 19:05:46 | [diff] [blame] | 478 | class AffineVectorLoadLowering : public OpRewritePattern<AffineVectorLoadOp> { |
| 479 | public: |
| 480 | using OpRewritePattern<AffineVectorLoadOp>::OpRewritePattern; |
| 481 | |
| 482 | LogicalResult matchAndRewrite(AffineVectorLoadOp op, |
| 483 | PatternRewriter &rewriter) const override { |
| 484 | // Expand affine map from 'affineVectorLoadOp'. |
| 485 | SmallVector<Value, 8> indices(op.getMapOperands()); |
| 486 | auto resultOperands = |
| 487 | expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices); |
| 488 | if (!resultOperands) |
| 489 | return failure(); |
| 490 | |
Diego Caballero | ee66e43 | 2021-02-12 17:41:46 | [diff] [blame] | 491 | // Build vector.load memref[expandedMap.results]. |
| 492 | rewriter.replaceOpWithNewOp<vector::LoadOp>( |
Diego Caballero | bc5565f | 2020-05-14 19:05:46 | [diff] [blame] | 493 | op, op.getVectorType(), op.getMemRef(), *resultOperands); |
| 494 | return success(); |
| 495 | } |
| 496 | }; |
| 497 | |
| 498 | /// Apply the affine map from an 'affine.vector_store' operation to its |
Diego Caballero | ee66e43 | 2021-02-12 17:41:46 | [diff] [blame] | 499 | /// operands, and feed the results to a newly created 'vector.store' operation |
| 500 | /// (which replaces the original 'affine.vector_store'). |
Diego Caballero | bc5565f | 2020-05-14 19:05:46 | [diff] [blame] | 501 | class AffineVectorStoreLowering : public OpRewritePattern<AffineVectorStoreOp> { |
| 502 | public: |
| 503 | using OpRewritePattern<AffineVectorStoreOp>::OpRewritePattern; |
| 504 | |
| 505 | LogicalResult matchAndRewrite(AffineVectorStoreOp op, |
| 506 | PatternRewriter &rewriter) const override { |
| 507 | // Expand affine map from 'affineVectorStoreOp'. |
| 508 | SmallVector<Value, 8> indices(op.getMapOperands()); |
| 509 | auto maybeExpandedMap = |
| 510 | expandAffineMap(rewriter, op.getLoc(), op.getAffineMap(), indices); |
| 511 | if (!maybeExpandedMap) |
| 512 | return failure(); |
| 513 | |
Diego Caballero | ee66e43 | 2021-02-12 17:41:46 | [diff] [blame] | 514 | rewriter.replaceOpWithNewOp<vector::StoreOp>( |
Diego Caballero | bc5565f | 2020-05-14 19:05:46 | [diff] [blame] | 515 | op, op.getValueToStore(), op.getMemRef(), *maybeExpandedMap); |
| 516 | return success(); |
| 517 | } |
| 518 | }; |
| 519 | |
Mehdi Amini | be0a7e9 | 2021-12-07 18:27:58 | [diff] [blame] | 520 | } // namespace |
Alex Zinenko | d4c071c | 2019-05-28 07:49:23 | [diff] [blame] | 521 | |
Chris Lattner | dc4e913 | 2021-03-22 23:58:34 | [diff] [blame] | 522 | void mlir::populateAffineToStdConversionPatterns(RewritePatternSet &patterns) { |
Alex Zinenko | 51ba5b5 | 2020-01-27 16:14:56 | [diff] [blame] | 523 | // clang-format off |
Chris Lattner | dc4e913 | 2021-03-22 23:58:34 | [diff] [blame] | 524 | patterns.add< |
Alex Zinenko | 51ba5b5 | 2020-01-27 16:14:56 | [diff] [blame] | 525 | AffineApplyLowering, |
| 526 | AffineDmaStartLowering, |
| 527 | AffineDmaWaitLowering, |
| 528 | AffineLoadLowering, |
| 529 | AffineMinLowering, |
OuHangKresnik | 5c3b349 | 2020-02-06 09:25:55 | [diff] [blame] | 530 | AffineMaxLowering, |
Yash Jain | 3382b71 | 2020-07-18 07:39:30 | [diff] [blame] | 531 | AffineParallelLowering, |
Alex Zinenko | 51ba5b5 | 2020-01-27 16:14:56 | [diff] [blame] | 532 | AffinePrefetchLowering, |
| 533 | AffineStoreLowering, |
| 534 | AffineForLowering, |
| 535 | AffineIfLowering, |
Chris Lattner | 3a506b3 | 2021-03-20 23:29:41 | [diff] [blame] | 536 | AffineYieldOpLowering>(patterns.getContext()); |
Alex Zinenko | 51ba5b5 | 2020-01-27 16:14:56 | [diff] [blame] | 537 | // clang-format on |
Alex Zinenko | d4c071c | 2019-05-28 07:49:23 | [diff] [blame] | 538 | } |
| 539 | |
Diego Caballero | bc5565f | 2020-05-14 19:05:46 | [diff] [blame] | 540 | void mlir::populateAffineToVectorConversionPatterns( |
Chris Lattner | dc4e913 | 2021-03-22 23:58:34 | [diff] [blame] | 541 | RewritePatternSet &patterns) { |
Diego Caballero | bc5565f | 2020-05-14 19:05:46 | [diff] [blame] | 542 | // clang-format off |
Chris Lattner | dc4e913 | 2021-03-22 23:58:34 | [diff] [blame] | 543 | patterns.add< |
Diego Caballero | bc5565f | 2020-05-14 19:05:46 | [diff] [blame] | 544 | AffineVectorLoadLowering, |
Chris Lattner | 3a506b3 | 2021-03-20 23:29:41 | [diff] [blame] | 545 | AffineVectorStoreLowering>(patterns.getContext()); |
Diego Caballero | bc5565f | 2020-05-14 19:05:46 | [diff] [blame] | 546 | // clang-format on |
| 547 | } |
| 548 | |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 549 | namespace { |
River Riddle | 1834ad4a | 2020-04-07 20:58:12 | [diff] [blame] | 550 | class LowerAffinePass : public ConvertAffineToStandardBase<LowerAffinePass> { |
MaheshRavishankar | fbe911e | 2020-07-27 19:13:08 | [diff] [blame] | 551 | void runOnOperation() override { |
Chris Lattner | dc4e913 | 2021-03-22 23:58:34 | [diff] [blame] | 552 | RewritePatternSet patterns(&getContext()); |
Chris Lattner | 3a506b3 | 2021-03-20 23:29:41 | [diff] [blame] | 553 | populateAffineToStdConversionPatterns(patterns); |
| 554 | populateAffineToVectorConversionPatterns(patterns); |
River Riddle | 2087bf6 | 2019-07-15 19:52:44 | [diff] [blame] | 555 | ConversionTarget target(getContext()); |
River Riddle | 23aa5a7 | 2022-02-26 22:49:54 | [diff] [blame^] | 556 | target.addLegalDialect<arith::ArithmeticDialect, func::FuncDialect, |
| 557 | memref::MemRefDialect, scf::SCFDialect, |
| 558 | VectorDialect>(); |
River Riddle | 3fffffa8 | 2020-10-27 00:25:01 | [diff] [blame] | 559 | if (failed(applyPartialConversion(getOperation(), target, |
| 560 | std::move(patterns)))) |
River Riddle | 2087bf6 | 2019-07-15 19:52:44 | [diff] [blame] | 561 | signalPassFailure(); |
| 562 | } |
Alex Zinenko | 8ad35b9 | 2019-06-11 15:33:18 | [diff] [blame] | 563 | }; |
| 564 | } // namespace |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 565 | |
River Riddle | 99b87c9 | 2019-03-27 21:02:02 | [diff] [blame] | 566 | /// Lowers If and For operations within a function into their lower level CFG |
Chris Lattner | ae61842 | 2018-12-31 00:22:50 | [diff] [blame] | 567 | /// equivalent blocks. |
MaheshRavishankar | fbe911e | 2020-07-27 19:13:08 | [diff] [blame] | 568 | std::unique_ptr<Pass> mlir::createLowerAffinePass() { |
Jacques Pienaar | 79f53b0 | 2019-08-17 18:05:35 | [diff] [blame] | 569 | return std::make_unique<LowerAffinePass>(); |
River Riddle | c6c5344 | 2019-02-27 18:59:29 | [diff] [blame] | 570 | } |