annotate mlir/lib/Analysis/AffineAnalysis.cpp @ 201:a96fbbdf2d0f

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 04 Jun 2021 21:07:06 +0900
parents 0572611fdcc8
children 2e18cbf3894f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===- AffineAnalysis.cpp - Affine structures analysis routines -----------===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8 //
anatofuz
parents:
diff changeset
9 // This file implements miscellaneous analysis routines for affine structures
anatofuz
parents:
diff changeset
10 // (expressions, maps, sets), and other utilities relying on such analysis.
anatofuz
parents:
diff changeset
11 //
anatofuz
parents:
diff changeset
12 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
13
anatofuz
parents:
diff changeset
14 #include "mlir/Analysis/AffineAnalysis.h"
anatofuz
parents:
diff changeset
15 #include "mlir/Analysis/Utils.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
16 #include "mlir/Dialect/Affine/IR/AffineOps.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
17 #include "mlir/Dialect/Affine/IR/AffineValueMap.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
18 #include "mlir/Dialect/StandardOps/IR/Ops.h"
150
anatofuz
parents:
diff changeset
19 #include "mlir/IR/AffineExprVisitor.h"
anatofuz
parents:
diff changeset
20 #include "mlir/IR/Function.h"
anatofuz
parents:
diff changeset
21 #include "mlir/IR/IntegerSet.h"
anatofuz
parents:
diff changeset
22 #include "mlir/Support/MathExtras.h"
anatofuz
parents:
diff changeset
23 #include "llvm/ADT/DenseMap.h"
anatofuz
parents:
diff changeset
24 #include "llvm/Support/Debug.h"
anatofuz
parents:
diff changeset
25 #include "llvm/Support/raw_ostream.h"
anatofuz
parents:
diff changeset
26
anatofuz
parents:
diff changeset
27 #define DEBUG_TYPE "affine-analysis"
anatofuz
parents:
diff changeset
28
anatofuz
parents:
diff changeset
29 using namespace mlir;
anatofuz
parents:
diff changeset
30
anatofuz
parents:
diff changeset
31 using llvm::dbgs;
anatofuz
parents:
diff changeset
32
anatofuz
parents:
diff changeset
33 /// Returns the sequence of AffineApplyOp Operations operation in
anatofuz
parents:
diff changeset
34 /// 'affineApplyOps', which are reachable via a search starting from 'operands',
anatofuz
parents:
diff changeset
35 /// and ending at operands which are not defined by AffineApplyOps.
anatofuz
parents:
diff changeset
36 // TODO(andydavis) Add a method to AffineApplyOp which forward substitutes
anatofuz
parents:
diff changeset
37 // the AffineApplyOp into any user AffineApplyOps.
anatofuz
parents:
diff changeset
38 void mlir::getReachableAffineApplyOps(
anatofuz
parents:
diff changeset
39 ArrayRef<Value> operands, SmallVectorImpl<Operation *> &affineApplyOps) {
anatofuz
parents:
diff changeset
40 struct State {
anatofuz
parents:
diff changeset
41 // The ssa value for this node in the DFS traversal.
anatofuz
parents:
diff changeset
42 Value value;
anatofuz
parents:
diff changeset
43 // The operand index of 'value' to explore next during DFS traversal.
anatofuz
parents:
diff changeset
44 unsigned operandIndex;
anatofuz
parents:
diff changeset
45 };
anatofuz
parents:
diff changeset
46 SmallVector<State, 4> worklist;
anatofuz
parents:
diff changeset
47 for (auto operand : operands) {
anatofuz
parents:
diff changeset
48 worklist.push_back({operand, 0});
anatofuz
parents:
diff changeset
49 }
anatofuz
parents:
diff changeset
50
anatofuz
parents:
diff changeset
51 while (!worklist.empty()) {
anatofuz
parents:
diff changeset
52 State &state = worklist.back();
anatofuz
parents:
diff changeset
53 auto *opInst = state.value.getDefiningOp();
anatofuz
parents:
diff changeset
54 // Note: getDefiningOp will return nullptr if the operand is not an
anatofuz
parents:
diff changeset
55 // Operation (i.e. block argument), which is a terminator for the search.
anatofuz
parents:
diff changeset
56 if (!isa_and_nonnull<AffineApplyOp>(opInst)) {
anatofuz
parents:
diff changeset
57 worklist.pop_back();
anatofuz
parents:
diff changeset
58 continue;
anatofuz
parents:
diff changeset
59 }
anatofuz
parents:
diff changeset
60
anatofuz
parents:
diff changeset
61 if (state.operandIndex == 0) {
anatofuz
parents:
diff changeset
62 // Pre-Visit: Add 'opInst' to reachable sequence.
anatofuz
parents:
diff changeset
63 affineApplyOps.push_back(opInst);
anatofuz
parents:
diff changeset
64 }
anatofuz
parents:
diff changeset
65 if (state.operandIndex < opInst->getNumOperands()) {
anatofuz
parents:
diff changeset
66 // Visit: Add next 'affineApplyOp' operand to worklist.
anatofuz
parents:
diff changeset
67 // Get next operand to visit at 'operandIndex'.
anatofuz
parents:
diff changeset
68 auto nextOperand = opInst->getOperand(state.operandIndex);
anatofuz
parents:
diff changeset
69 // Increment 'operandIndex' in 'state'.
anatofuz
parents:
diff changeset
70 ++state.operandIndex;
anatofuz
parents:
diff changeset
71 // Add 'nextOperand' to worklist.
anatofuz
parents:
diff changeset
72 worklist.push_back({nextOperand, 0});
anatofuz
parents:
diff changeset
73 } else {
anatofuz
parents:
diff changeset
74 // Post-visit: done visiting operands AffineApplyOp, pop off stack.
anatofuz
parents:
diff changeset
75 worklist.pop_back();
anatofuz
parents:
diff changeset
76 }
anatofuz
parents:
diff changeset
77 }
anatofuz
parents:
diff changeset
78 }
anatofuz
parents:
diff changeset
79
anatofuz
parents:
diff changeset
80 // Builds a system of constraints with dimensional identifiers corresponding to
anatofuz
parents:
diff changeset
81 // the loop IVs of the forOps appearing in that order. Any symbols founds in
anatofuz
parents:
diff changeset
82 // the bound operands are added as symbols in the system. Returns failure for
anatofuz
parents:
diff changeset
83 // the yet unimplemented cases.
anatofuz
parents:
diff changeset
84 // TODO(andydavis,bondhugula) Handle non-unit steps through local variables or
anatofuz
parents:
diff changeset
85 // stride information in FlatAffineConstraints. (For eg., by using iv - lb %
anatofuz
parents:
diff changeset
86 // step = 0 and/or by introducing a method in FlatAffineConstraints
anatofuz
parents:
diff changeset
87 // setExprStride(ArrayRef<int64_t> expr, int64_t stride)
anatofuz
parents:
diff changeset
88 LogicalResult mlir::getIndexSet(MutableArrayRef<AffineForOp> forOps,
anatofuz
parents:
diff changeset
89 FlatAffineConstraints *domain) {
anatofuz
parents:
diff changeset
90 SmallVector<Value, 4> indices;
anatofuz
parents:
diff changeset
91 extractForInductionVars(forOps, &indices);
anatofuz
parents:
diff changeset
92 // Reset while associated Values in 'indices' to the domain.
anatofuz
parents:
diff changeset
93 domain->reset(forOps.size(), /*numSymbols=*/0, /*numLocals=*/0, indices);
anatofuz
parents:
diff changeset
94 for (auto forOp : forOps) {
anatofuz
parents:
diff changeset
95 // Add constraints from forOp's bounds.
anatofuz
parents:
diff changeset
96 if (failed(domain->addAffineForOpDomain(forOp)))
anatofuz
parents:
diff changeset
97 return failure();
anatofuz
parents:
diff changeset
98 }
anatofuz
parents:
diff changeset
99 return success();
anatofuz
parents:
diff changeset
100 }
anatofuz
parents:
diff changeset
101
anatofuz
parents:
diff changeset
102 // Computes the iteration domain for 'opInst' and populates 'indexSet', which
anatofuz
parents:
diff changeset
103 // encapsulates the constraints involving loops surrounding 'opInst' and
anatofuz
parents:
diff changeset
104 // potentially involving any Function symbols. The dimensional identifiers in
anatofuz
parents:
diff changeset
105 // 'indexSet' correspond to the loops surrounding 'op' from outermost to
anatofuz
parents:
diff changeset
106 // innermost.
anatofuz
parents:
diff changeset
107 // TODO(andydavis) Add support to handle IfInsts surrounding 'op'.
anatofuz
parents:
diff changeset
108 static LogicalResult getInstIndexSet(Operation *op,
anatofuz
parents:
diff changeset
109 FlatAffineConstraints *indexSet) {
anatofuz
parents:
diff changeset
110 // TODO(andydavis) Extend this to gather enclosing IfInsts and consider
anatofuz
parents:
diff changeset
111 // factoring it out into a utility function.
anatofuz
parents:
diff changeset
112 SmallVector<AffineForOp, 4> loops;
anatofuz
parents:
diff changeset
113 getLoopIVs(*op, &loops);
anatofuz
parents:
diff changeset
114 return getIndexSet(loops, indexSet);
anatofuz
parents:
diff changeset
115 }
anatofuz
parents:
diff changeset
116
anatofuz
parents:
diff changeset
117 namespace {
anatofuz
parents:
diff changeset
118 // ValuePositionMap manages the mapping from Values which represent dimension
anatofuz
parents:
diff changeset
119 // and symbol identifiers from 'src' and 'dst' access functions to positions
anatofuz
parents:
diff changeset
120 // in new space where some Values are kept separate (using addSrc/DstValue)
anatofuz
parents:
diff changeset
121 // and some Values are merged (addSymbolValue).
anatofuz
parents:
diff changeset
122 // Position lookups return the absolute position in the new space which
anatofuz
parents:
diff changeset
123 // has the following format:
anatofuz
parents:
diff changeset
124 //
anatofuz
parents:
diff changeset
125 // [src-dim-identifiers] [dst-dim-identifiers] [symbol-identifiers]
anatofuz
parents:
diff changeset
126 //
anatofuz
parents:
diff changeset
127 // Note: access function non-IV dimension identifiers (that have 'dimension'
anatofuz
parents:
diff changeset
128 // positions in the access function position space) are assigned as symbols
anatofuz
parents:
diff changeset
129 // in the output position space. Convenience access functions which lookup
anatofuz
parents:
diff changeset
130 // an Value in multiple maps are provided (i.e. getSrcDimOrSymPos) to handle
anatofuz
parents:
diff changeset
131 // the common case of resolving positions for all access function operands.
anatofuz
parents:
diff changeset
132 //
anatofuz
parents:
diff changeset
133 // TODO(andydavis) Generalize this: could take a template parameter for
anatofuz
parents:
diff changeset
134 // the number of maps (3 in the current case), and lookups could take indices
anatofuz
parents:
diff changeset
135 // of maps to check. So getSrcDimOrSymPos would be "getPos(value, {0, 2})".
anatofuz
parents:
diff changeset
136 class ValuePositionMap {
anatofuz
parents:
diff changeset
137 public:
anatofuz
parents:
diff changeset
138 void addSrcValue(Value value) {
anatofuz
parents:
diff changeset
139 if (addValueAt(value, &srcDimPosMap, numSrcDims))
anatofuz
parents:
diff changeset
140 ++numSrcDims;
anatofuz
parents:
diff changeset
141 }
anatofuz
parents:
diff changeset
142 void addDstValue(Value value) {
anatofuz
parents:
diff changeset
143 if (addValueAt(value, &dstDimPosMap, numDstDims))
anatofuz
parents:
diff changeset
144 ++numDstDims;
anatofuz
parents:
diff changeset
145 }
anatofuz
parents:
diff changeset
146 void addSymbolValue(Value value) {
anatofuz
parents:
diff changeset
147 if (addValueAt(value, &symbolPosMap, numSymbols))
anatofuz
parents:
diff changeset
148 ++numSymbols;
anatofuz
parents:
diff changeset
149 }
anatofuz
parents:
diff changeset
150 unsigned getSrcDimOrSymPos(Value value) const {
anatofuz
parents:
diff changeset
151 return getDimOrSymPos(value, srcDimPosMap, 0);
anatofuz
parents:
diff changeset
152 }
anatofuz
parents:
diff changeset
153 unsigned getDstDimOrSymPos(Value value) const {
anatofuz
parents:
diff changeset
154 return getDimOrSymPos(value, dstDimPosMap, numSrcDims);
anatofuz
parents:
diff changeset
155 }
anatofuz
parents:
diff changeset
156 unsigned getSymPos(Value value) const {
anatofuz
parents:
diff changeset
157 auto it = symbolPosMap.find(value);
anatofuz
parents:
diff changeset
158 assert(it != symbolPosMap.end());
anatofuz
parents:
diff changeset
159 return numSrcDims + numDstDims + it->second;
anatofuz
parents:
diff changeset
160 }
anatofuz
parents:
diff changeset
161
anatofuz
parents:
diff changeset
162 unsigned getNumSrcDims() const { return numSrcDims; }
anatofuz
parents:
diff changeset
163 unsigned getNumDstDims() const { return numDstDims; }
anatofuz
parents:
diff changeset
164 unsigned getNumDims() const { return numSrcDims + numDstDims; }
anatofuz
parents:
diff changeset
165 unsigned getNumSymbols() const { return numSymbols; }
anatofuz
parents:
diff changeset
166
anatofuz
parents:
diff changeset
167 private:
anatofuz
parents:
diff changeset
168 bool addValueAt(Value value, DenseMap<Value, unsigned> *posMap,
anatofuz
parents:
diff changeset
169 unsigned position) {
anatofuz
parents:
diff changeset
170 auto it = posMap->find(value);
anatofuz
parents:
diff changeset
171 if (it == posMap->end()) {
anatofuz
parents:
diff changeset
172 (*posMap)[value] = position;
anatofuz
parents:
diff changeset
173 return true;
anatofuz
parents:
diff changeset
174 }
anatofuz
parents:
diff changeset
175 return false;
anatofuz
parents:
diff changeset
176 }
anatofuz
parents:
diff changeset
177 unsigned getDimOrSymPos(Value value,
anatofuz
parents:
diff changeset
178 const DenseMap<Value, unsigned> &dimPosMap,
anatofuz
parents:
diff changeset
179 unsigned dimPosOffset) const {
anatofuz
parents:
diff changeset
180 auto it = dimPosMap.find(value);
anatofuz
parents:
diff changeset
181 if (it != dimPosMap.end()) {
anatofuz
parents:
diff changeset
182 return dimPosOffset + it->second;
anatofuz
parents:
diff changeset
183 }
anatofuz
parents:
diff changeset
184 it = symbolPosMap.find(value);
anatofuz
parents:
diff changeset
185 assert(it != symbolPosMap.end());
anatofuz
parents:
diff changeset
186 return numSrcDims + numDstDims + it->second;
anatofuz
parents:
diff changeset
187 }
anatofuz
parents:
diff changeset
188
anatofuz
parents:
diff changeset
189 unsigned numSrcDims = 0;
anatofuz
parents:
diff changeset
190 unsigned numDstDims = 0;
anatofuz
parents:
diff changeset
191 unsigned numSymbols = 0;
anatofuz
parents:
diff changeset
192 DenseMap<Value, unsigned> srcDimPosMap;
anatofuz
parents:
diff changeset
193 DenseMap<Value, unsigned> dstDimPosMap;
anatofuz
parents:
diff changeset
194 DenseMap<Value, unsigned> symbolPosMap;
anatofuz
parents:
diff changeset
195 };
anatofuz
parents:
diff changeset
196 } // namespace
anatofuz
parents:
diff changeset
197
anatofuz
parents:
diff changeset
198 // Builds a map from Value to identifier position in a new merged identifier
anatofuz
parents:
diff changeset
199 // list, which is the result of merging dim/symbol lists from src/dst
anatofuz
parents:
diff changeset
200 // iteration domains, the format of which is as follows:
anatofuz
parents:
diff changeset
201 //
anatofuz
parents:
diff changeset
202 // [src-dim-identifiers, dst-dim-identifiers, symbol-identifiers, const_term]
anatofuz
parents:
diff changeset
203 //
anatofuz
parents:
diff changeset
204 // This method populates 'valuePosMap' with mappings from operand Values in
anatofuz
parents:
diff changeset
205 // 'srcAccessMap'/'dstAccessMap' (as well as those in 'srcDomain'/'dstDomain')
anatofuz
parents:
diff changeset
206 // to the position of these values in the merged list.
anatofuz
parents:
diff changeset
207 static void buildDimAndSymbolPositionMaps(
anatofuz
parents:
diff changeset
208 const FlatAffineConstraints &srcDomain,
anatofuz
parents:
diff changeset
209 const FlatAffineConstraints &dstDomain, const AffineValueMap &srcAccessMap,
anatofuz
parents:
diff changeset
210 const AffineValueMap &dstAccessMap, ValuePositionMap *valuePosMap,
anatofuz
parents:
diff changeset
211 FlatAffineConstraints *dependenceConstraints) {
anatofuz
parents:
diff changeset
212 auto updateValuePosMap = [&](ArrayRef<Value> values, bool isSrc) {
anatofuz
parents:
diff changeset
213 for (unsigned i = 0, e = values.size(); i < e; ++i) {
anatofuz
parents:
diff changeset
214 auto value = values[i];
anatofuz
parents:
diff changeset
215 if (!isForInductionVar(values[i])) {
anatofuz
parents:
diff changeset
216 assert(isValidSymbol(values[i]) &&
anatofuz
parents:
diff changeset
217 "access operand has to be either a loop IV or a symbol");
anatofuz
parents:
diff changeset
218 valuePosMap->addSymbolValue(value);
anatofuz
parents:
diff changeset
219 } else if (isSrc) {
anatofuz
parents:
diff changeset
220 valuePosMap->addSrcValue(value);
anatofuz
parents:
diff changeset
221 } else {
anatofuz
parents:
diff changeset
222 valuePosMap->addDstValue(value);
anatofuz
parents:
diff changeset
223 }
anatofuz
parents:
diff changeset
224 }
anatofuz
parents:
diff changeset
225 };
anatofuz
parents:
diff changeset
226
anatofuz
parents:
diff changeset
227 SmallVector<Value, 4> srcValues, destValues;
anatofuz
parents:
diff changeset
228 srcDomain.getIdValues(0, srcDomain.getNumDimAndSymbolIds(), &srcValues);
anatofuz
parents:
diff changeset
229 dstDomain.getIdValues(0, dstDomain.getNumDimAndSymbolIds(), &destValues);
anatofuz
parents:
diff changeset
230 // Update value position map with identifiers from src iteration domain.
anatofuz
parents:
diff changeset
231 updateValuePosMap(srcValues, /*isSrc=*/true);
anatofuz
parents:
diff changeset
232 // Update value position map with identifiers from dst iteration domain.
anatofuz
parents:
diff changeset
233 updateValuePosMap(destValues, /*isSrc=*/false);
anatofuz
parents:
diff changeset
234 // Update value position map with identifiers from src access function.
anatofuz
parents:
diff changeset
235 updateValuePosMap(srcAccessMap.getOperands(), /*isSrc=*/true);
anatofuz
parents:
diff changeset
236 // Update value position map with identifiers from dst access function.
anatofuz
parents:
diff changeset
237 updateValuePosMap(dstAccessMap.getOperands(), /*isSrc=*/false);
anatofuz
parents:
diff changeset
238 }
anatofuz
parents:
diff changeset
239
anatofuz
parents:
diff changeset
240 // Sets up dependence constraints columns appropriately, in the format:
anatofuz
parents:
diff changeset
241 // [src-dim-ids, dst-dim-ids, symbol-ids, local-ids, const_term]
anatofuz
parents:
diff changeset
242 static void initDependenceConstraints(
anatofuz
parents:
diff changeset
243 const FlatAffineConstraints &srcDomain,
anatofuz
parents:
diff changeset
244 const FlatAffineConstraints &dstDomain, const AffineValueMap &srcAccessMap,
anatofuz
parents:
diff changeset
245 const AffineValueMap &dstAccessMap, const ValuePositionMap &valuePosMap,
anatofuz
parents:
diff changeset
246 FlatAffineConstraints *dependenceConstraints) {
anatofuz
parents:
diff changeset
247 // Calculate number of equalities/inequalities and columns required to
anatofuz
parents:
diff changeset
248 // initialize FlatAffineConstraints for 'dependenceDomain'.
anatofuz
parents:
diff changeset
249 unsigned numIneq =
anatofuz
parents:
diff changeset
250 srcDomain.getNumInequalities() + dstDomain.getNumInequalities();
anatofuz
parents:
diff changeset
251 AffineMap srcMap = srcAccessMap.getAffineMap();
anatofuz
parents:
diff changeset
252 assert(srcMap.getNumResults() == dstAccessMap.getAffineMap().getNumResults());
anatofuz
parents:
diff changeset
253 unsigned numEq = srcMap.getNumResults();
anatofuz
parents:
diff changeset
254 unsigned numDims = srcDomain.getNumDimIds() + dstDomain.getNumDimIds();
anatofuz
parents:
diff changeset
255 unsigned numSymbols = valuePosMap.getNumSymbols();
anatofuz
parents:
diff changeset
256 unsigned numLocals = srcDomain.getNumLocalIds() + dstDomain.getNumLocalIds();
anatofuz
parents:
diff changeset
257 unsigned numIds = numDims + numSymbols + numLocals;
anatofuz
parents:
diff changeset
258 unsigned numCols = numIds + 1;
anatofuz
parents:
diff changeset
259
anatofuz
parents:
diff changeset
260 // Set flat affine constraints sizes and reserving space for constraints.
anatofuz
parents:
diff changeset
261 dependenceConstraints->reset(numIneq, numEq, numCols, numDims, numSymbols,
anatofuz
parents:
diff changeset
262 numLocals);
anatofuz
parents:
diff changeset
263
anatofuz
parents:
diff changeset
264 // Set values corresponding to dependence constraint identifiers.
anatofuz
parents:
diff changeset
265 SmallVector<Value, 4> srcLoopIVs, dstLoopIVs;
anatofuz
parents:
diff changeset
266 srcDomain.getIdValues(0, srcDomain.getNumDimIds(), &srcLoopIVs);
anatofuz
parents:
diff changeset
267 dstDomain.getIdValues(0, dstDomain.getNumDimIds(), &dstLoopIVs);
anatofuz
parents:
diff changeset
268
anatofuz
parents:
diff changeset
269 dependenceConstraints->setIdValues(0, srcLoopIVs.size(), srcLoopIVs);
anatofuz
parents:
diff changeset
270 dependenceConstraints->setIdValues(
anatofuz
parents:
diff changeset
271 srcLoopIVs.size(), srcLoopIVs.size() + dstLoopIVs.size(), dstLoopIVs);
anatofuz
parents:
diff changeset
272
anatofuz
parents:
diff changeset
273 // Set values for the symbolic identifier dimensions.
anatofuz
parents:
diff changeset
274 auto setSymbolIds = [&](ArrayRef<Value> values) {
anatofuz
parents:
diff changeset
275 for (auto value : values) {
anatofuz
parents:
diff changeset
276 if (!isForInductionVar(value)) {
anatofuz
parents:
diff changeset
277 assert(isValidSymbol(value) && "expected symbol");
anatofuz
parents:
diff changeset
278 dependenceConstraints->setIdValue(valuePosMap.getSymPos(value), value);
anatofuz
parents:
diff changeset
279 }
anatofuz
parents:
diff changeset
280 }
anatofuz
parents:
diff changeset
281 };
anatofuz
parents:
diff changeset
282
anatofuz
parents:
diff changeset
283 setSymbolIds(srcAccessMap.getOperands());
anatofuz
parents:
diff changeset
284 setSymbolIds(dstAccessMap.getOperands());
anatofuz
parents:
diff changeset
285
anatofuz
parents:
diff changeset
286 SmallVector<Value, 8> srcSymbolValues, dstSymbolValues;
anatofuz
parents:
diff changeset
287 srcDomain.getIdValues(srcDomain.getNumDimIds(),
anatofuz
parents:
diff changeset
288 srcDomain.getNumDimAndSymbolIds(), &srcSymbolValues);
anatofuz
parents:
diff changeset
289 dstDomain.getIdValues(dstDomain.getNumDimIds(),
anatofuz
parents:
diff changeset
290 dstDomain.getNumDimAndSymbolIds(), &dstSymbolValues);
anatofuz
parents:
diff changeset
291 setSymbolIds(srcSymbolValues);
anatofuz
parents:
diff changeset
292 setSymbolIds(dstSymbolValues);
anatofuz
parents:
diff changeset
293
anatofuz
parents:
diff changeset
294 for (unsigned i = 0, e = dependenceConstraints->getNumDimAndSymbolIds();
anatofuz
parents:
diff changeset
295 i < e; i++)
anatofuz
parents:
diff changeset
296 assert(dependenceConstraints->getIds()[i].hasValue());
anatofuz
parents:
diff changeset
297 }
anatofuz
parents:
diff changeset
298
anatofuz
parents:
diff changeset
299 // Adds iteration domain constraints from 'srcDomain' and 'dstDomain' into
anatofuz
parents:
diff changeset
300 // 'dependenceDomain'.
anatofuz
parents:
diff changeset
301 // Uses 'valuePosMap' to determine the position in 'dependenceDomain' to which a
anatofuz
parents:
diff changeset
302 // srcDomain/dstDomain Value maps.
anatofuz
parents:
diff changeset
303 static void addDomainConstraints(const FlatAffineConstraints &srcDomain,
anatofuz
parents:
diff changeset
304 const FlatAffineConstraints &dstDomain,
anatofuz
parents:
diff changeset
305 const ValuePositionMap &valuePosMap,
anatofuz
parents:
diff changeset
306 FlatAffineConstraints *dependenceDomain) {
anatofuz
parents:
diff changeset
307 unsigned depNumDimsAndSymbolIds = dependenceDomain->getNumDimAndSymbolIds();
anatofuz
parents:
diff changeset
308
anatofuz
parents:
diff changeset
309 SmallVector<int64_t, 4> cst(dependenceDomain->getNumCols());
anatofuz
parents:
diff changeset
310
anatofuz
parents:
diff changeset
311 auto addDomain = [&](bool isSrc, bool isEq, unsigned localOffset) {
anatofuz
parents:
diff changeset
312 const FlatAffineConstraints &domain = isSrc ? srcDomain : dstDomain;
anatofuz
parents:
diff changeset
313 unsigned numCsts =
anatofuz
parents:
diff changeset
314 isEq ? domain.getNumEqualities() : domain.getNumInequalities();
anatofuz
parents:
diff changeset
315 unsigned numDimAndSymbolIds = domain.getNumDimAndSymbolIds();
anatofuz
parents:
diff changeset
316 auto at = [&](unsigned i, unsigned j) -> int64_t {
anatofuz
parents:
diff changeset
317 return isEq ? domain.atEq(i, j) : domain.atIneq(i, j);
anatofuz
parents:
diff changeset
318 };
anatofuz
parents:
diff changeset
319 auto map = [&](unsigned i) -> int64_t {
anatofuz
parents:
diff changeset
320 return isSrc ? valuePosMap.getSrcDimOrSymPos(domain.getIdValue(i))
anatofuz
parents:
diff changeset
321 : valuePosMap.getDstDimOrSymPos(domain.getIdValue(i));
anatofuz
parents:
diff changeset
322 };
anatofuz
parents:
diff changeset
323
anatofuz
parents:
diff changeset
324 for (unsigned i = 0; i < numCsts; ++i) {
anatofuz
parents:
diff changeset
325 // Zero fill.
anatofuz
parents:
diff changeset
326 std::fill(cst.begin(), cst.end(), 0);
anatofuz
parents:
diff changeset
327 // Set coefficients for identifiers corresponding to domain.
anatofuz
parents:
diff changeset
328 for (unsigned j = 0; j < numDimAndSymbolIds; ++j)
anatofuz
parents:
diff changeset
329 cst[map(j)] = at(i, j);
anatofuz
parents:
diff changeset
330 // Local terms.
anatofuz
parents:
diff changeset
331 for (unsigned j = 0, e = domain.getNumLocalIds(); j < e; j++)
anatofuz
parents:
diff changeset
332 cst[depNumDimsAndSymbolIds + localOffset + j] =
anatofuz
parents:
diff changeset
333 at(i, numDimAndSymbolIds + j);
anatofuz
parents:
diff changeset
334 // Set constant term.
anatofuz
parents:
diff changeset
335 cst[cst.size() - 1] = at(i, domain.getNumCols() - 1);
anatofuz
parents:
diff changeset
336 // Add constraint.
anatofuz
parents:
diff changeset
337 if (isEq)
anatofuz
parents:
diff changeset
338 dependenceDomain->addEquality(cst);
anatofuz
parents:
diff changeset
339 else
anatofuz
parents:
diff changeset
340 dependenceDomain->addInequality(cst);
anatofuz
parents:
diff changeset
341 }
anatofuz
parents:
diff changeset
342 };
anatofuz
parents:
diff changeset
343
anatofuz
parents:
diff changeset
344 // Add equalities from src domain.
anatofuz
parents:
diff changeset
345 addDomain(/*isSrc=*/true, /*isEq=*/true, /*localOffset=*/0);
anatofuz
parents:
diff changeset
346 // Add inequalities from src domain.
anatofuz
parents:
diff changeset
347 addDomain(/*isSrc=*/true, /*isEq=*/false, /*localOffset=*/0);
anatofuz
parents:
diff changeset
348 // Add equalities from dst domain.
anatofuz
parents:
diff changeset
349 addDomain(/*isSrc=*/false, /*isEq=*/true,
anatofuz
parents:
diff changeset
350 /*localOffset=*/srcDomain.getNumLocalIds());
anatofuz
parents:
diff changeset
351 // Add inequalities from dst domain.
anatofuz
parents:
diff changeset
352 addDomain(/*isSrc=*/false, /*isEq=*/false,
anatofuz
parents:
diff changeset
353 /*localOffset=*/srcDomain.getNumLocalIds());
anatofuz
parents:
diff changeset
354 }
anatofuz
parents:
diff changeset
355
anatofuz
parents:
diff changeset
356 // Adds equality constraints that equate src and dst access functions
anatofuz
parents:
diff changeset
357 // represented by 'srcAccessMap' and 'dstAccessMap' for each result.
anatofuz
parents:
diff changeset
358 // Requires that 'srcAccessMap' and 'dstAccessMap' have the same results count.
anatofuz
parents:
diff changeset
359 // For example, given the following two accesses functions to a 2D memref:
anatofuz
parents:
diff changeset
360 //
anatofuz
parents:
diff changeset
361 // Source access function:
anatofuz
parents:
diff changeset
362 // (a0 * d0 + a1 * s0 + a2, b0 * d0 + b1 * s0 + b2)
anatofuz
parents:
diff changeset
363 //
anatofuz
parents:
diff changeset
364 // Destination access function:
anatofuz
parents:
diff changeset
365 // (c0 * d0 + c1 * s0 + c2, f0 * d0 + f1 * s0 + f2)
anatofuz
parents:
diff changeset
366 //
anatofuz
parents:
diff changeset
367 // This method constructs the following equality constraints in
anatofuz
parents:
diff changeset
368 // 'dependenceDomain', by equating the access functions for each result
anatofuz
parents:
diff changeset
369 // (i.e. each memref dim). Notice that 'd0' for the destination access function
anatofuz
parents:
diff changeset
370 // is mapped into 'd0' in the equality constraint:
anatofuz
parents:
diff changeset
371 //
anatofuz
parents:
diff changeset
372 // d0 d1 s0 c
anatofuz
parents:
diff changeset
373 // -- -- -- --
anatofuz
parents:
diff changeset
374 // a0 -c0 (a1 - c1) (a1 - c2) = 0
anatofuz
parents:
diff changeset
375 // b0 -f0 (b1 - f1) (b1 - f2) = 0
anatofuz
parents:
diff changeset
376 //
anatofuz
parents:
diff changeset
377 // Returns failure if any AffineExpr cannot be flattened (due to it being
anatofuz
parents:
diff changeset
378 // semi-affine). Returns success otherwise.
anatofuz
parents:
diff changeset
379 static LogicalResult
anatofuz
parents:
diff changeset
380 addMemRefAccessConstraints(const AffineValueMap &srcAccessMap,
anatofuz
parents:
diff changeset
381 const AffineValueMap &dstAccessMap,
anatofuz
parents:
diff changeset
382 const ValuePositionMap &valuePosMap,
anatofuz
parents:
diff changeset
383 FlatAffineConstraints *dependenceDomain) {
anatofuz
parents:
diff changeset
384 AffineMap srcMap = srcAccessMap.getAffineMap();
anatofuz
parents:
diff changeset
385 AffineMap dstMap = dstAccessMap.getAffineMap();
anatofuz
parents:
diff changeset
386 assert(srcMap.getNumResults() == dstMap.getNumResults());
anatofuz
parents:
diff changeset
387 unsigned numResults = srcMap.getNumResults();
anatofuz
parents:
diff changeset
388
anatofuz
parents:
diff changeset
389 unsigned srcNumIds = srcMap.getNumDims() + srcMap.getNumSymbols();
anatofuz
parents:
diff changeset
390 ArrayRef<Value> srcOperands = srcAccessMap.getOperands();
anatofuz
parents:
diff changeset
391
anatofuz
parents:
diff changeset
392 unsigned dstNumIds = dstMap.getNumDims() + dstMap.getNumSymbols();
anatofuz
parents:
diff changeset
393 ArrayRef<Value> dstOperands = dstAccessMap.getOperands();
anatofuz
parents:
diff changeset
394
anatofuz
parents:
diff changeset
395 std::vector<SmallVector<int64_t, 8>> srcFlatExprs;
anatofuz
parents:
diff changeset
396 std::vector<SmallVector<int64_t, 8>> destFlatExprs;
anatofuz
parents:
diff changeset
397 FlatAffineConstraints srcLocalVarCst, destLocalVarCst;
anatofuz
parents:
diff changeset
398 // Get flattened expressions for the source destination maps.
anatofuz
parents:
diff changeset
399 if (failed(getFlattenedAffineExprs(srcMap, &srcFlatExprs, &srcLocalVarCst)) ||
anatofuz
parents:
diff changeset
400 failed(getFlattenedAffineExprs(dstMap, &destFlatExprs, &destLocalVarCst)))
anatofuz
parents:
diff changeset
401 return failure();
anatofuz
parents:
diff changeset
402
anatofuz
parents:
diff changeset
403 unsigned domNumLocalIds = dependenceDomain->getNumLocalIds();
anatofuz
parents:
diff changeset
404 unsigned srcNumLocalIds = srcLocalVarCst.getNumLocalIds();
anatofuz
parents:
diff changeset
405 unsigned dstNumLocalIds = destLocalVarCst.getNumLocalIds();
anatofuz
parents:
diff changeset
406 unsigned numLocalIdsToAdd = srcNumLocalIds + dstNumLocalIds;
anatofuz
parents:
diff changeset
407 for (unsigned i = 0; i < numLocalIdsToAdd; i++) {
anatofuz
parents:
diff changeset
408 dependenceDomain->addLocalId(dependenceDomain->getNumLocalIds());
anatofuz
parents:
diff changeset
409 }
anatofuz
parents:
diff changeset
410
anatofuz
parents:
diff changeset
411 unsigned numDims = dependenceDomain->getNumDimIds();
anatofuz
parents:
diff changeset
412 unsigned numSymbols = dependenceDomain->getNumSymbolIds();
anatofuz
parents:
diff changeset
413 unsigned numSrcLocalIds = srcLocalVarCst.getNumLocalIds();
anatofuz
parents:
diff changeset
414 unsigned newLocalIdOffset = numDims + numSymbols + domNumLocalIds;
anatofuz
parents:
diff changeset
415
anatofuz
parents:
diff changeset
416 // Equality to add.
anatofuz
parents:
diff changeset
417 SmallVector<int64_t, 8> eq(dependenceDomain->getNumCols());
anatofuz
parents:
diff changeset
418 for (unsigned i = 0; i < numResults; ++i) {
anatofuz
parents:
diff changeset
419 // Zero fill.
anatofuz
parents:
diff changeset
420 std::fill(eq.begin(), eq.end(), 0);
anatofuz
parents:
diff changeset
421
anatofuz
parents:
diff changeset
422 // Flattened AffineExpr for src result 'i'.
anatofuz
parents:
diff changeset
423 const auto &srcFlatExpr = srcFlatExprs[i];
anatofuz
parents:
diff changeset
424 // Set identifier coefficients from src access function.
anatofuz
parents:
diff changeset
425 for (unsigned j = 0, e = srcOperands.size(); j < e; ++j)
anatofuz
parents:
diff changeset
426 eq[valuePosMap.getSrcDimOrSymPos(srcOperands[j])] = srcFlatExpr[j];
anatofuz
parents:
diff changeset
427 // Local terms.
anatofuz
parents:
diff changeset
428 for (unsigned j = 0, e = srcNumLocalIds; j < e; j++)
anatofuz
parents:
diff changeset
429 eq[newLocalIdOffset + j] = srcFlatExpr[srcNumIds + j];
anatofuz
parents:
diff changeset
430 // Set constant term.
anatofuz
parents:
diff changeset
431 eq[eq.size() - 1] = srcFlatExpr[srcFlatExpr.size() - 1];
anatofuz
parents:
diff changeset
432
anatofuz
parents:
diff changeset
433 // Flattened AffineExpr for dest result 'i'.
anatofuz
parents:
diff changeset
434 const auto &destFlatExpr = destFlatExprs[i];
anatofuz
parents:
diff changeset
435 // Set identifier coefficients from dst access function.
anatofuz
parents:
diff changeset
436 for (unsigned j = 0, e = dstOperands.size(); j < e; ++j)
anatofuz
parents:
diff changeset
437 eq[valuePosMap.getDstDimOrSymPos(dstOperands[j])] -= destFlatExpr[j];
anatofuz
parents:
diff changeset
438 // Local terms.
anatofuz
parents:
diff changeset
439 for (unsigned j = 0, e = dstNumLocalIds; j < e; j++)
anatofuz
parents:
diff changeset
440 eq[newLocalIdOffset + numSrcLocalIds + j] = -destFlatExpr[dstNumIds + j];
anatofuz
parents:
diff changeset
441 // Set constant term.
anatofuz
parents:
diff changeset
442 eq[eq.size() - 1] -= destFlatExpr[destFlatExpr.size() - 1];
anatofuz
parents:
diff changeset
443
anatofuz
parents:
diff changeset
444 // Add equality constraint.
anatofuz
parents:
diff changeset
445 dependenceDomain->addEquality(eq);
anatofuz
parents:
diff changeset
446 }
anatofuz
parents:
diff changeset
447
anatofuz
parents:
diff changeset
448 // Add equality constraints for any operands that are defined by constant ops.
anatofuz
parents:
diff changeset
449 auto addEqForConstOperands = [&](ArrayRef<Value> operands) {
anatofuz
parents:
diff changeset
450 for (unsigned i = 0, e = operands.size(); i < e; ++i) {
anatofuz
parents:
diff changeset
451 if (isForInductionVar(operands[i]))
anatofuz
parents:
diff changeset
452 continue;
anatofuz
parents:
diff changeset
453 auto symbol = operands[i];
anatofuz
parents:
diff changeset
454 assert(isValidSymbol(symbol));
anatofuz
parents:
diff changeset
455 // Check if the symbol is a constant.
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
456 if (auto cOp = symbol.getDefiningOp<ConstantIndexOp>())
150
anatofuz
parents:
diff changeset
457 dependenceDomain->setIdToConstant(valuePosMap.getSymPos(symbol),
anatofuz
parents:
diff changeset
458 cOp.getValue());
anatofuz
parents:
diff changeset
459 }
anatofuz
parents:
diff changeset
460 };
anatofuz
parents:
diff changeset
461
anatofuz
parents:
diff changeset
462 // Add equality constraints for any src symbols defined by constant ops.
anatofuz
parents:
diff changeset
463 addEqForConstOperands(srcOperands);
anatofuz
parents:
diff changeset
464 // Add equality constraints for any dst symbols defined by constant ops.
anatofuz
parents:
diff changeset
465 addEqForConstOperands(dstOperands);
anatofuz
parents:
diff changeset
466
anatofuz
parents:
diff changeset
467 // By construction (see flattener), local var constraints will not have any
anatofuz
parents:
diff changeset
468 // equalities.
anatofuz
parents:
diff changeset
469 assert(srcLocalVarCst.getNumEqualities() == 0 &&
anatofuz
parents:
diff changeset
470 destLocalVarCst.getNumEqualities() == 0);
anatofuz
parents:
diff changeset
471 // Add inequalities from srcLocalVarCst and destLocalVarCst into the
anatofuz
parents:
diff changeset
472 // dependence domain.
anatofuz
parents:
diff changeset
473 SmallVector<int64_t, 8> ineq(dependenceDomain->getNumCols());
anatofuz
parents:
diff changeset
474 for (unsigned r = 0, e = srcLocalVarCst.getNumInequalities(); r < e; r++) {
anatofuz
parents:
diff changeset
475 std::fill(ineq.begin(), ineq.end(), 0);
anatofuz
parents:
diff changeset
476
anatofuz
parents:
diff changeset
477 // Set identifier coefficients from src local var constraints.
anatofuz
parents:
diff changeset
478 for (unsigned j = 0, e = srcOperands.size(); j < e; ++j)
anatofuz
parents:
diff changeset
479 ineq[valuePosMap.getSrcDimOrSymPos(srcOperands[j])] =
anatofuz
parents:
diff changeset
480 srcLocalVarCst.atIneq(r, j);
anatofuz
parents:
diff changeset
481 // Local terms.
anatofuz
parents:
diff changeset
482 for (unsigned j = 0, e = srcNumLocalIds; j < e; j++)
anatofuz
parents:
diff changeset
483 ineq[newLocalIdOffset + j] = srcLocalVarCst.atIneq(r, srcNumIds + j);
anatofuz
parents:
diff changeset
484 // Set constant term.
anatofuz
parents:
diff changeset
485 ineq[ineq.size() - 1] =
anatofuz
parents:
diff changeset
486 srcLocalVarCst.atIneq(r, srcLocalVarCst.getNumCols() - 1);
anatofuz
parents:
diff changeset
487 dependenceDomain->addInequality(ineq);
anatofuz
parents:
diff changeset
488 }
anatofuz
parents:
diff changeset
489
anatofuz
parents:
diff changeset
490 for (unsigned r = 0, e = destLocalVarCst.getNumInequalities(); r < e; r++) {
anatofuz
parents:
diff changeset
491 std::fill(ineq.begin(), ineq.end(), 0);
anatofuz
parents:
diff changeset
492 // Set identifier coefficients from dest local var constraints.
anatofuz
parents:
diff changeset
493 for (unsigned j = 0, e = dstOperands.size(); j < e; ++j)
anatofuz
parents:
diff changeset
494 ineq[valuePosMap.getDstDimOrSymPos(dstOperands[j])] =
anatofuz
parents:
diff changeset
495 destLocalVarCst.atIneq(r, j);
anatofuz
parents:
diff changeset
496 // Local terms.
anatofuz
parents:
diff changeset
497 for (unsigned j = 0, e = dstNumLocalIds; j < e; j++)
anatofuz
parents:
diff changeset
498 ineq[newLocalIdOffset + numSrcLocalIds + j] =
anatofuz
parents:
diff changeset
499 destLocalVarCst.atIneq(r, dstNumIds + j);
anatofuz
parents:
diff changeset
500 // Set constant term.
anatofuz
parents:
diff changeset
501 ineq[ineq.size() - 1] =
anatofuz
parents:
diff changeset
502 destLocalVarCst.atIneq(r, destLocalVarCst.getNumCols() - 1);
anatofuz
parents:
diff changeset
503
anatofuz
parents:
diff changeset
504 dependenceDomain->addInequality(ineq);
anatofuz
parents:
diff changeset
505 }
anatofuz
parents:
diff changeset
506 return success();
anatofuz
parents:
diff changeset
507 }
anatofuz
parents:
diff changeset
508
anatofuz
parents:
diff changeset
509 // Returns the number of outer loop common to 'src/dstDomain'.
anatofuz
parents:
diff changeset
510 // Loops common to 'src/dst' domains are added to 'commonLoops' if non-null.
anatofuz
parents:
diff changeset
511 static unsigned
anatofuz
parents:
diff changeset
512 getNumCommonLoops(const FlatAffineConstraints &srcDomain,
anatofuz
parents:
diff changeset
513 const FlatAffineConstraints &dstDomain,
anatofuz
parents:
diff changeset
514 SmallVectorImpl<AffineForOp> *commonLoops = nullptr) {
anatofuz
parents:
diff changeset
515 // Find the number of common loops shared by src and dst accesses.
anatofuz
parents:
diff changeset
516 unsigned minNumLoops =
anatofuz
parents:
diff changeset
517 std::min(srcDomain.getNumDimIds(), dstDomain.getNumDimIds());
anatofuz
parents:
diff changeset
518 unsigned numCommonLoops = 0;
anatofuz
parents:
diff changeset
519 for (unsigned i = 0; i < minNumLoops; ++i) {
anatofuz
parents:
diff changeset
520 if (!isForInductionVar(srcDomain.getIdValue(i)) ||
anatofuz
parents:
diff changeset
521 !isForInductionVar(dstDomain.getIdValue(i)) ||
anatofuz
parents:
diff changeset
522 srcDomain.getIdValue(i) != dstDomain.getIdValue(i))
anatofuz
parents:
diff changeset
523 break;
anatofuz
parents:
diff changeset
524 if (commonLoops != nullptr)
anatofuz
parents:
diff changeset
525 commonLoops->push_back(getForInductionVarOwner(srcDomain.getIdValue(i)));
anatofuz
parents:
diff changeset
526 ++numCommonLoops;
anatofuz
parents:
diff changeset
527 }
anatofuz
parents:
diff changeset
528 if (commonLoops != nullptr)
anatofuz
parents:
diff changeset
529 assert(commonLoops->size() == numCommonLoops);
anatofuz
parents:
diff changeset
530 return numCommonLoops;
anatofuz
parents:
diff changeset
531 }
anatofuz
parents:
diff changeset
532
anatofuz
parents:
diff changeset
533 // Returns Block common to 'srcAccess.opInst' and 'dstAccess.opInst'.
anatofuz
parents:
diff changeset
534 static Block *getCommonBlock(const MemRefAccess &srcAccess,
anatofuz
parents:
diff changeset
535 const MemRefAccess &dstAccess,
anatofuz
parents:
diff changeset
536 const FlatAffineConstraints &srcDomain,
anatofuz
parents:
diff changeset
537 unsigned numCommonLoops) {
anatofuz
parents:
diff changeset
538 if (numCommonLoops == 0) {
anatofuz
parents:
diff changeset
539 auto *block = srcAccess.opInst->getBlock();
anatofuz
parents:
diff changeset
540 while (!llvm::isa<FuncOp>(block->getParentOp())) {
anatofuz
parents:
diff changeset
541 block = block->getParentOp()->getBlock();
anatofuz
parents:
diff changeset
542 }
anatofuz
parents:
diff changeset
543 return block;
anatofuz
parents:
diff changeset
544 }
anatofuz
parents:
diff changeset
545 auto commonForValue = srcDomain.getIdValue(numCommonLoops - 1);
anatofuz
parents:
diff changeset
546 auto forOp = getForInductionVarOwner(commonForValue);
anatofuz
parents:
diff changeset
547 assert(forOp && "commonForValue was not an induction variable");
anatofuz
parents:
diff changeset
548 return forOp.getBody();
anatofuz
parents:
diff changeset
549 }
anatofuz
parents:
diff changeset
550
anatofuz
parents:
diff changeset
551 // Returns true if the ancestor operation of 'srcAccess' appears before the
anatofuz
parents:
diff changeset
552 // ancestor operation of 'dstAccess' in the common ancestral block. Returns
anatofuz
parents:
diff changeset
553 // false otherwise.
anatofuz
parents:
diff changeset
554 // Note that because 'srcAccess' or 'dstAccess' may be nested in conditionals,
anatofuz
parents:
diff changeset
555 // the function is named 'srcAppearsBeforeDstInCommonBlock'. Note that
anatofuz
parents:
diff changeset
556 // 'numCommonLoops' is the number of contiguous surrounding outer loops.
anatofuz
parents:
diff changeset
557 static bool srcAppearsBeforeDstInAncestralBlock(
anatofuz
parents:
diff changeset
558 const MemRefAccess &srcAccess, const MemRefAccess &dstAccess,
anatofuz
parents:
diff changeset
559 const FlatAffineConstraints &srcDomain, unsigned numCommonLoops) {
anatofuz
parents:
diff changeset
560 // Get Block common to 'srcAccess.opInst' and 'dstAccess.opInst'.
anatofuz
parents:
diff changeset
561 auto *commonBlock =
anatofuz
parents:
diff changeset
562 getCommonBlock(srcAccess, dstAccess, srcDomain, numCommonLoops);
anatofuz
parents:
diff changeset
563 // Check the dominance relationship between the respective ancestors of the
anatofuz
parents:
diff changeset
564 // src and dst in the Block of the innermost among the common loops.
anatofuz
parents:
diff changeset
565 auto *srcInst = commonBlock->findAncestorOpInBlock(*srcAccess.opInst);
anatofuz
parents:
diff changeset
566 assert(srcInst != nullptr);
anatofuz
parents:
diff changeset
567 auto *dstInst = commonBlock->findAncestorOpInBlock(*dstAccess.opInst);
anatofuz
parents:
diff changeset
568 assert(dstInst != nullptr);
anatofuz
parents:
diff changeset
569
anatofuz
parents:
diff changeset
570 // Determine whether dstInst comes after srcInst.
anatofuz
parents:
diff changeset
571 return srcInst->isBeforeInBlock(dstInst);
anatofuz
parents:
diff changeset
572 }
anatofuz
parents:
diff changeset
573
anatofuz
parents:
diff changeset
574 // Adds ordering constraints to 'dependenceDomain' based on number of loops
anatofuz
parents:
diff changeset
575 // common to 'src/dstDomain' and requested 'loopDepth'.
anatofuz
parents:
diff changeset
576 // Note that 'loopDepth' cannot exceed the number of common loops plus one.
anatofuz
parents:
diff changeset
577 // EX: Given a loop nest of depth 2 with IVs 'i' and 'j':
anatofuz
parents:
diff changeset
578 // *) If 'loopDepth == 1' then one constraint is added: i' >= i + 1
anatofuz
parents:
diff changeset
579 // *) If 'loopDepth == 2' then two constraints are added: i == i' and j' > j + 1
anatofuz
parents:
diff changeset
580 // *) If 'loopDepth == 3' then two constraints are added: i == i' and j == j'
anatofuz
parents:
diff changeset
581 static void addOrderingConstraints(const FlatAffineConstraints &srcDomain,
anatofuz
parents:
diff changeset
582 const FlatAffineConstraints &dstDomain,
anatofuz
parents:
diff changeset
583 unsigned loopDepth,
anatofuz
parents:
diff changeset
584 FlatAffineConstraints *dependenceDomain) {
anatofuz
parents:
diff changeset
585 unsigned numCols = dependenceDomain->getNumCols();
anatofuz
parents:
diff changeset
586 SmallVector<int64_t, 4> eq(numCols);
anatofuz
parents:
diff changeset
587 unsigned numSrcDims = srcDomain.getNumDimIds();
anatofuz
parents:
diff changeset
588 unsigned numCommonLoops = getNumCommonLoops(srcDomain, dstDomain);
anatofuz
parents:
diff changeset
589 unsigned numCommonLoopConstraints = std::min(numCommonLoops, loopDepth);
anatofuz
parents:
diff changeset
590 for (unsigned i = 0; i < numCommonLoopConstraints; ++i) {
anatofuz
parents:
diff changeset
591 std::fill(eq.begin(), eq.end(), 0);
anatofuz
parents:
diff changeset
592 eq[i] = -1;
anatofuz
parents:
diff changeset
593 eq[i + numSrcDims] = 1;
anatofuz
parents:
diff changeset
594 if (i == loopDepth - 1) {
anatofuz
parents:
diff changeset
595 eq[numCols - 1] = -1;
anatofuz
parents:
diff changeset
596 dependenceDomain->addInequality(eq);
anatofuz
parents:
diff changeset
597 } else {
anatofuz
parents:
diff changeset
598 dependenceDomain->addEquality(eq);
anatofuz
parents:
diff changeset
599 }
anatofuz
parents:
diff changeset
600 }
anatofuz
parents:
diff changeset
601 }
anatofuz
parents:
diff changeset
602
anatofuz
parents:
diff changeset
603 // Computes distance and direction vectors in 'dependences', by adding
anatofuz
parents:
diff changeset
604 // variables to 'dependenceDomain' which represent the difference of the IVs,
anatofuz
parents:
diff changeset
605 // eliminating all other variables, and reading off distance vectors from
anatofuz
parents:
diff changeset
606 // equality constraints (if possible), and direction vectors from inequalities.
anatofuz
parents:
diff changeset
607 static void computeDirectionVector(
anatofuz
parents:
diff changeset
608 const FlatAffineConstraints &srcDomain,
anatofuz
parents:
diff changeset
609 const FlatAffineConstraints &dstDomain, unsigned loopDepth,
anatofuz
parents:
diff changeset
610 FlatAffineConstraints *dependenceDomain,
anatofuz
parents:
diff changeset
611 SmallVector<DependenceComponent, 2> *dependenceComponents) {
anatofuz
parents:
diff changeset
612 // Find the number of common loops shared by src and dst accesses.
anatofuz
parents:
diff changeset
613 SmallVector<AffineForOp, 4> commonLoops;
anatofuz
parents:
diff changeset
614 unsigned numCommonLoops =
anatofuz
parents:
diff changeset
615 getNumCommonLoops(srcDomain, dstDomain, &commonLoops);
anatofuz
parents:
diff changeset
616 if (numCommonLoops == 0)
anatofuz
parents:
diff changeset
617 return;
anatofuz
parents:
diff changeset
618 // Compute direction vectors for requested loop depth.
anatofuz
parents:
diff changeset
619 unsigned numIdsToEliminate = dependenceDomain->getNumIds();
anatofuz
parents:
diff changeset
620 // Add new variables to 'dependenceDomain' to represent the direction
anatofuz
parents:
diff changeset
621 // constraints for each shared loop.
anatofuz
parents:
diff changeset
622 for (unsigned j = 0; j < numCommonLoops; ++j) {
anatofuz
parents:
diff changeset
623 dependenceDomain->addDimId(j);
anatofuz
parents:
diff changeset
624 }
anatofuz
parents:
diff changeset
625
anatofuz
parents:
diff changeset
626 // Add equality constraints for each common loop, setting newly introduced
anatofuz
parents:
diff changeset
627 // variable at column 'j' to the 'dst' IV minus the 'src IV.
anatofuz
parents:
diff changeset
628 SmallVector<int64_t, 4> eq;
anatofuz
parents:
diff changeset
629 eq.resize(dependenceDomain->getNumCols());
anatofuz
parents:
diff changeset
630 unsigned numSrcDims = srcDomain.getNumDimIds();
anatofuz
parents:
diff changeset
631 // Constraint variables format:
anatofuz
parents:
diff changeset
632 // [num-common-loops][num-src-dim-ids][num-dst-dim-ids][num-symbols][constant]
anatofuz
parents:
diff changeset
633 for (unsigned j = 0; j < numCommonLoops; ++j) {
anatofuz
parents:
diff changeset
634 std::fill(eq.begin(), eq.end(), 0);
anatofuz
parents:
diff changeset
635 eq[j] = 1;
anatofuz
parents:
diff changeset
636 eq[j + numCommonLoops] = 1;
anatofuz
parents:
diff changeset
637 eq[j + numCommonLoops + numSrcDims] = -1;
anatofuz
parents:
diff changeset
638 dependenceDomain->addEquality(eq);
anatofuz
parents:
diff changeset
639 }
anatofuz
parents:
diff changeset
640
anatofuz
parents:
diff changeset
641 // Eliminate all variables other than the direction variables just added.
anatofuz
parents:
diff changeset
642 dependenceDomain->projectOut(numCommonLoops, numIdsToEliminate);
anatofuz
parents:
diff changeset
643
anatofuz
parents:
diff changeset
644 // Scan each common loop variable column and set direction vectors based
anatofuz
parents:
diff changeset
645 // on eliminated constraint system.
anatofuz
parents:
diff changeset
646 dependenceComponents->resize(numCommonLoops);
anatofuz
parents:
diff changeset
647 for (unsigned j = 0; j < numCommonLoops; ++j) {
anatofuz
parents:
diff changeset
648 (*dependenceComponents)[j].op = commonLoops[j].getOperation();
anatofuz
parents:
diff changeset
649 auto lbConst = dependenceDomain->getConstantLowerBound(j);
anatofuz
parents:
diff changeset
650 (*dependenceComponents)[j].lb =
anatofuz
parents:
diff changeset
651 lbConst.getValueOr(std::numeric_limits<int64_t>::min());
anatofuz
parents:
diff changeset
652 auto ubConst = dependenceDomain->getConstantUpperBound(j);
anatofuz
parents:
diff changeset
653 (*dependenceComponents)[j].ub =
anatofuz
parents:
diff changeset
654 ubConst.getValueOr(std::numeric_limits<int64_t>::max());
anatofuz
parents:
diff changeset
655 }
anatofuz
parents:
diff changeset
656 }
anatofuz
parents:
diff changeset
657
anatofuz
parents:
diff changeset
658 // Populates 'accessMap' with composition of AffineApplyOps reachable from
anatofuz
parents:
diff changeset
659 // indices of MemRefAccess.
anatofuz
parents:
diff changeset
660 void MemRefAccess::getAccessMap(AffineValueMap *accessMap) const {
anatofuz
parents:
diff changeset
661 // Get affine map from AffineLoad/Store.
anatofuz
parents:
diff changeset
662 AffineMap map;
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
663 if (auto loadOp = dyn_cast<AffineReadOpInterface>(opInst)) {
150
anatofuz
parents:
diff changeset
664 map = loadOp.getAffineMap();
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
665 } else {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
666 auto storeOp = cast<AffineWriteOpInterface>(opInst);
150
anatofuz
parents:
diff changeset
667 map = storeOp.getAffineMap();
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
668 }
150
anatofuz
parents:
diff changeset
669 SmallVector<Value, 8> operands(indices.begin(), indices.end());
anatofuz
parents:
diff changeset
670 fullyComposeAffineMapAndOperands(&map, &operands);
anatofuz
parents:
diff changeset
671 map = simplifyAffineMap(map);
anatofuz
parents:
diff changeset
672 canonicalizeMapAndOperands(&map, &operands);
anatofuz
parents:
diff changeset
673 accessMap->reset(map, operands);
anatofuz
parents:
diff changeset
674 }
anatofuz
parents:
diff changeset
675
anatofuz
parents:
diff changeset
676 // Builds a flat affine constraint system to check if there exists a dependence
anatofuz
parents:
diff changeset
677 // between memref accesses 'srcAccess' and 'dstAccess'.
anatofuz
parents:
diff changeset
678 // Returns 'NoDependence' if the accesses can be definitively shown not to
anatofuz
parents:
diff changeset
679 // access the same element.
anatofuz
parents:
diff changeset
680 // Returns 'HasDependence' if the accesses do access the same element.
anatofuz
parents:
diff changeset
681 // Returns 'Failure' if an error or unsupported case was encountered.
anatofuz
parents:
diff changeset
682 // If a dependence exists, returns in 'dependenceComponents' a direction
anatofuz
parents:
diff changeset
683 // vector for the dependence, with a component for each loop IV in loops
anatofuz
parents:
diff changeset
684 // common to both accesses (see Dependence in AffineAnalysis.h for details).
anatofuz
parents:
diff changeset
685 //
anatofuz
parents:
diff changeset
686 // The memref access dependence check is comprised of the following steps:
anatofuz
parents:
diff changeset
687 // *) Compute access functions for each access. Access functions are computed
anatofuz
parents:
diff changeset
688 // using AffineValueMaps initialized with the indices from an access, then
anatofuz
parents:
diff changeset
689 // composed with AffineApplyOps reachable from operands of that access,
anatofuz
parents:
diff changeset
690 // until operands of the AffineValueMap are loop IVs or symbols.
anatofuz
parents:
diff changeset
691 // *) Build iteration domain constraints for each access. Iteration domain
anatofuz
parents:
diff changeset
692 // constraints are pairs of inequality constraints representing the
anatofuz
parents:
diff changeset
693 // upper/lower loop bounds for each AffineForOp in the loop nest associated
anatofuz
parents:
diff changeset
694 // with each access.
anatofuz
parents:
diff changeset
695 // *) Build dimension and symbol position maps for each access, which map
anatofuz
parents:
diff changeset
696 // Values from access functions and iteration domains to their position
anatofuz
parents:
diff changeset
697 // in the merged constraint system built by this method.
anatofuz
parents:
diff changeset
698 //
anatofuz
parents:
diff changeset
699 // This method builds a constraint system with the following column format:
anatofuz
parents:
diff changeset
700 //
anatofuz
parents:
diff changeset
701 // [src-dim-identifiers, dst-dim-identifiers, symbols, constant]
anatofuz
parents:
diff changeset
702 //
anatofuz
parents:
diff changeset
703 // For example, given the following MLIR code with "source" and "destination"
anatofuz
parents:
diff changeset
704 // accesses to the same memref label, and symbols %M, %N, %K:
anatofuz
parents:
diff changeset
705 //
anatofuz
parents:
diff changeset
706 // affine.for %i0 = 0 to 100 {
anatofuz
parents:
diff changeset
707 // affine.for %i1 = 0 to 50 {
anatofuz
parents:
diff changeset
708 // %a0 = affine.apply
anatofuz
parents:
diff changeset
709 // (d0, d1) -> (d0 * 2 - d1 * 4 + s1, d1 * 3 - s0) (%i0, %i1)[%M, %N]
anatofuz
parents:
diff changeset
710 // // Source memref access.
anatofuz
parents:
diff changeset
711 // store %v0, %m[%a0#0, %a0#1] : memref<4x4xf32>
anatofuz
parents:
diff changeset
712 // }
anatofuz
parents:
diff changeset
713 // }
anatofuz
parents:
diff changeset
714 //
anatofuz
parents:
diff changeset
715 // affine.for %i2 = 0 to 100 {
anatofuz
parents:
diff changeset
716 // affine.for %i3 = 0 to 50 {
anatofuz
parents:
diff changeset
717 // %a1 = affine.apply
anatofuz
parents:
diff changeset
718 // (d0, d1) -> (d0 * 7 + d1 * 9 - s1, d1 * 11 + s0) (%i2, %i3)[%K, %M]
anatofuz
parents:
diff changeset
719 // // Destination memref access.
anatofuz
parents:
diff changeset
720 // %v1 = load %m[%a1#0, %a1#1] : memref<4x4xf32>
anatofuz
parents:
diff changeset
721 // }
anatofuz
parents:
diff changeset
722 // }
anatofuz
parents:
diff changeset
723 //
anatofuz
parents:
diff changeset
724 // The access functions would be the following:
anatofuz
parents:
diff changeset
725 //
anatofuz
parents:
diff changeset
726 // src: (%i0 * 2 - %i1 * 4 + %N, %i1 * 3 - %M)
anatofuz
parents:
diff changeset
727 // dst: (%i2 * 7 + %i3 * 9 - %M, %i3 * 11 - %K)
anatofuz
parents:
diff changeset
728 //
anatofuz
parents:
diff changeset
729 // The iteration domains for the src/dst accesses would be the following:
anatofuz
parents:
diff changeset
730 //
anatofuz
parents:
diff changeset
731 // src: 0 <= %i0 <= 100, 0 <= %i1 <= 50
anatofuz
parents:
diff changeset
732 // dst: 0 <= %i2 <= 100, 0 <= %i3 <= 50
anatofuz
parents:
diff changeset
733 //
anatofuz
parents:
diff changeset
734 // The symbols by both accesses would be assigned to a canonical position order
anatofuz
parents:
diff changeset
735 // which will be used in the dependence constraint system:
anatofuz
parents:
diff changeset
736 //
anatofuz
parents:
diff changeset
737 // symbol name: %M %N %K
anatofuz
parents:
diff changeset
738 // symbol pos: 0 1 2
anatofuz
parents:
diff changeset
739 //
anatofuz
parents:
diff changeset
740 // Equality constraints are built by equating each result of src/destination
anatofuz
parents:
diff changeset
741 // access functions. For this example, the following two equality constraints
anatofuz
parents:
diff changeset
742 // will be added to the dependence constraint system:
anatofuz
parents:
diff changeset
743 //
anatofuz
parents:
diff changeset
744 // [src_dim0, src_dim1, dst_dim0, dst_dim1, sym0, sym1, sym2, const]
anatofuz
parents:
diff changeset
745 // 2 -4 -7 -9 1 1 0 0 = 0
anatofuz
parents:
diff changeset
746 // 0 3 0 -11 -1 0 1 0 = 0
anatofuz
parents:
diff changeset
747 //
anatofuz
parents:
diff changeset
748 // Inequality constraints from the iteration domain will be meged into
anatofuz
parents:
diff changeset
749 // the dependence constraint system
anatofuz
parents:
diff changeset
750 //
anatofuz
parents:
diff changeset
751 // [src_dim0, src_dim1, dst_dim0, dst_dim1, sym0, sym1, sym2, const]
anatofuz
parents:
diff changeset
752 // 1 0 0 0 0 0 0 0 >= 0
anatofuz
parents:
diff changeset
753 // -1 0 0 0 0 0 0 100 >= 0
anatofuz
parents:
diff changeset
754 // 0 1 0 0 0 0 0 0 >= 0
anatofuz
parents:
diff changeset
755 // 0 -1 0 0 0 0 0 50 >= 0
anatofuz
parents:
diff changeset
756 // 0 0 1 0 0 0 0 0 >= 0
anatofuz
parents:
diff changeset
757 // 0 0 -1 0 0 0 0 100 >= 0
anatofuz
parents:
diff changeset
758 // 0 0 0 1 0 0 0 0 >= 0
anatofuz
parents:
diff changeset
759 // 0 0 0 -1 0 0 0 50 >= 0
anatofuz
parents:
diff changeset
760 //
anatofuz
parents:
diff changeset
761 //
anatofuz
parents:
diff changeset
762 // TODO(andydavis) Support AffineExprs mod/floordiv/ceildiv.
anatofuz
parents:
diff changeset
763 DependenceResult mlir::checkMemrefAccessDependence(
anatofuz
parents:
diff changeset
764 const MemRefAccess &srcAccess, const MemRefAccess &dstAccess,
anatofuz
parents:
diff changeset
765 unsigned loopDepth, FlatAffineConstraints *dependenceConstraints,
anatofuz
parents:
diff changeset
766 SmallVector<DependenceComponent, 2> *dependenceComponents, bool allowRAR) {
anatofuz
parents:
diff changeset
767 LLVM_DEBUG(llvm::dbgs() << "Checking for dependence at depth: "
anatofuz
parents:
diff changeset
768 << Twine(loopDepth) << " between:\n";);
anatofuz
parents:
diff changeset
769 LLVM_DEBUG(srcAccess.opInst->dump(););
anatofuz
parents:
diff changeset
770 LLVM_DEBUG(dstAccess.opInst->dump(););
anatofuz
parents:
diff changeset
771
anatofuz
parents:
diff changeset
772 // Return 'NoDependence' if these accesses do not access the same memref.
anatofuz
parents:
diff changeset
773 if (srcAccess.memref != dstAccess.memref)
anatofuz
parents:
diff changeset
774 return DependenceResult::NoDependence;
anatofuz
parents:
diff changeset
775
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
776 // Return 'NoDependence' if one of these accesses is not an
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
777 // AffineWriteOpInterface.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
778 if (!allowRAR && !isa<AffineWriteOpInterface>(srcAccess.opInst) &&
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
779 !isa<AffineWriteOpInterface>(dstAccess.opInst))
150
anatofuz
parents:
diff changeset
780 return DependenceResult::NoDependence;
anatofuz
parents:
diff changeset
781
anatofuz
parents:
diff changeset
782 // Get composed access function for 'srcAccess'.
anatofuz
parents:
diff changeset
783 AffineValueMap srcAccessMap;
anatofuz
parents:
diff changeset
784 srcAccess.getAccessMap(&srcAccessMap);
anatofuz
parents:
diff changeset
785
anatofuz
parents:
diff changeset
786 // Get composed access function for 'dstAccess'.
anatofuz
parents:
diff changeset
787 AffineValueMap dstAccessMap;
anatofuz
parents:
diff changeset
788 dstAccess.getAccessMap(&dstAccessMap);
anatofuz
parents:
diff changeset
789
anatofuz
parents:
diff changeset
790 // Get iteration domain for the 'srcAccess' operation.
anatofuz
parents:
diff changeset
791 FlatAffineConstraints srcDomain;
anatofuz
parents:
diff changeset
792 if (failed(getInstIndexSet(srcAccess.opInst, &srcDomain)))
anatofuz
parents:
diff changeset
793 return DependenceResult::Failure;
anatofuz
parents:
diff changeset
794
anatofuz
parents:
diff changeset
795 // Get iteration domain for 'dstAccess' operation.
anatofuz
parents:
diff changeset
796 FlatAffineConstraints dstDomain;
anatofuz
parents:
diff changeset
797 if (failed(getInstIndexSet(dstAccess.opInst, &dstDomain)))
anatofuz
parents:
diff changeset
798 return DependenceResult::Failure;
anatofuz
parents:
diff changeset
799
anatofuz
parents:
diff changeset
800 // Return 'NoDependence' if loopDepth > numCommonLoops and if the ancestor
anatofuz
parents:
diff changeset
801 // operation of 'srcAccess' does not properly dominate the ancestor
anatofuz
parents:
diff changeset
802 // operation of 'dstAccess' in the same common operation block.
anatofuz
parents:
diff changeset
803 // Note: this check is skipped if 'allowRAR' is true, because because RAR
anatofuz
parents:
diff changeset
804 // deps can exist irrespective of lexicographic ordering b/w src and dst.
anatofuz
parents:
diff changeset
805 unsigned numCommonLoops = getNumCommonLoops(srcDomain, dstDomain);
anatofuz
parents:
diff changeset
806 assert(loopDepth <= numCommonLoops + 1);
anatofuz
parents:
diff changeset
807 if (!allowRAR && loopDepth > numCommonLoops &&
anatofuz
parents:
diff changeset
808 !srcAppearsBeforeDstInAncestralBlock(srcAccess, dstAccess, srcDomain,
anatofuz
parents:
diff changeset
809 numCommonLoops)) {
anatofuz
parents:
diff changeset
810 return DependenceResult::NoDependence;
anatofuz
parents:
diff changeset
811 }
anatofuz
parents:
diff changeset
812 // Build dim and symbol position maps for each access from access operand
anatofuz
parents:
diff changeset
813 // Value to position in merged constraint system.
anatofuz
parents:
diff changeset
814 ValuePositionMap valuePosMap;
anatofuz
parents:
diff changeset
815 buildDimAndSymbolPositionMaps(srcDomain, dstDomain, srcAccessMap,
anatofuz
parents:
diff changeset
816 dstAccessMap, &valuePosMap,
anatofuz
parents:
diff changeset
817 dependenceConstraints);
anatofuz
parents:
diff changeset
818
anatofuz
parents:
diff changeset
819 initDependenceConstraints(srcDomain, dstDomain, srcAccessMap, dstAccessMap,
anatofuz
parents:
diff changeset
820 valuePosMap, dependenceConstraints);
anatofuz
parents:
diff changeset
821
anatofuz
parents:
diff changeset
822 assert(valuePosMap.getNumDims() ==
anatofuz
parents:
diff changeset
823 srcDomain.getNumDimIds() + dstDomain.getNumDimIds());
anatofuz
parents:
diff changeset
824
anatofuz
parents:
diff changeset
825 // Create memref access constraint by equating src/dst access functions.
anatofuz
parents:
diff changeset
826 // Note that this check is conservative, and will fail in the future when
anatofuz
parents:
diff changeset
827 // local variables for mod/div exprs are supported.
anatofuz
parents:
diff changeset
828 if (failed(addMemRefAccessConstraints(srcAccessMap, dstAccessMap, valuePosMap,
anatofuz
parents:
diff changeset
829 dependenceConstraints)))
anatofuz
parents:
diff changeset
830 return DependenceResult::Failure;
anatofuz
parents:
diff changeset
831
anatofuz
parents:
diff changeset
832 // Add 'src' happens before 'dst' ordering constraints.
anatofuz
parents:
diff changeset
833 addOrderingConstraints(srcDomain, dstDomain, loopDepth,
anatofuz
parents:
diff changeset
834 dependenceConstraints);
anatofuz
parents:
diff changeset
835 // Add src and dst domain constraints.
anatofuz
parents:
diff changeset
836 addDomainConstraints(srcDomain, dstDomain, valuePosMap,
anatofuz
parents:
diff changeset
837 dependenceConstraints);
anatofuz
parents:
diff changeset
838
anatofuz
parents:
diff changeset
839 // Return 'NoDependence' if the solution space is empty: no dependence.
anatofuz
parents:
diff changeset
840 if (dependenceConstraints->isEmpty()) {
anatofuz
parents:
diff changeset
841 return DependenceResult::NoDependence;
anatofuz
parents:
diff changeset
842 }
anatofuz
parents:
diff changeset
843
anatofuz
parents:
diff changeset
844 // Compute dependence direction vector and return true.
anatofuz
parents:
diff changeset
845 if (dependenceComponents != nullptr) {
anatofuz
parents:
diff changeset
846 computeDirectionVector(srcDomain, dstDomain, loopDepth,
anatofuz
parents:
diff changeset
847 dependenceConstraints, dependenceComponents);
anatofuz
parents:
diff changeset
848 }
anatofuz
parents:
diff changeset
849
anatofuz
parents:
diff changeset
850 LLVM_DEBUG(llvm::dbgs() << "Dependence polyhedron:\n");
anatofuz
parents:
diff changeset
851 LLVM_DEBUG(dependenceConstraints->dump());
anatofuz
parents:
diff changeset
852 return DependenceResult::HasDependence;
anatofuz
parents:
diff changeset
853 }
anatofuz
parents:
diff changeset
854
anatofuz
parents:
diff changeset
855 /// Gathers dependence components for dependences between all ops in loop nest
anatofuz
parents:
diff changeset
856 /// rooted at 'forOp' at loop depths in range [1, maxLoopDepth].
anatofuz
parents:
diff changeset
857 void mlir::getDependenceComponents(
anatofuz
parents:
diff changeset
858 AffineForOp forOp, unsigned maxLoopDepth,
anatofuz
parents:
diff changeset
859 std::vector<SmallVector<DependenceComponent, 2>> *depCompsVec) {
anatofuz
parents:
diff changeset
860 // Collect all load and store ops in loop nest rooted at 'forOp'.
anatofuz
parents:
diff changeset
861 SmallVector<Operation *, 8> loadAndStoreOpInsts;
anatofuz
parents:
diff changeset
862 forOp.getOperation()->walk([&](Operation *opInst) {
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
863 if (isa<AffineReadOpInterface>(opInst) ||
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
864 isa<AffineWriteOpInterface>(opInst))
150
anatofuz
parents:
diff changeset
865 loadAndStoreOpInsts.push_back(opInst);
anatofuz
parents:
diff changeset
866 });
anatofuz
parents:
diff changeset
867
anatofuz
parents:
diff changeset
868 unsigned numOps = loadAndStoreOpInsts.size();
anatofuz
parents:
diff changeset
869 for (unsigned d = 1; d <= maxLoopDepth; ++d) {
anatofuz
parents:
diff changeset
870 for (unsigned i = 0; i < numOps; ++i) {
anatofuz
parents:
diff changeset
871 auto *srcOpInst = loadAndStoreOpInsts[i];
anatofuz
parents:
diff changeset
872 MemRefAccess srcAccess(srcOpInst);
anatofuz
parents:
diff changeset
873 for (unsigned j = 0; j < numOps; ++j) {
anatofuz
parents:
diff changeset
874 auto *dstOpInst = loadAndStoreOpInsts[j];
anatofuz
parents:
diff changeset
875 MemRefAccess dstAccess(dstOpInst);
anatofuz
parents:
diff changeset
876
anatofuz
parents:
diff changeset
877 FlatAffineConstraints dependenceConstraints;
anatofuz
parents:
diff changeset
878 SmallVector<DependenceComponent, 2> depComps;
anatofuz
parents:
diff changeset
879 // TODO(andydavis,bondhugula) Explore whether it would be profitable
anatofuz
parents:
diff changeset
880 // to pre-compute and store deps instead of repeatedly checking.
anatofuz
parents:
diff changeset
881 DependenceResult result = checkMemrefAccessDependence(
anatofuz
parents:
diff changeset
882 srcAccess, dstAccess, d, &dependenceConstraints, &depComps);
anatofuz
parents:
diff changeset
883 if (hasDependence(result))
anatofuz
parents:
diff changeset
884 depCompsVec->push_back(depComps);
anatofuz
parents:
diff changeset
885 }
anatofuz
parents:
diff changeset
886 }
anatofuz
parents:
diff changeset
887 }
anatofuz
parents:
diff changeset
888 }