MLIR  20.0.0git
AffineStructures.cpp
Go to the documentation of this file.
1 //===- AffineStructures.cpp - MLIR Affine Structures Class-----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Structures for affine/polyhedral analysis of affine dialect ops.
10 //
11 //===----------------------------------------------------------------------===//
12 
22 #include "mlir/IR/IntegerSet.h"
23 #include "mlir/Support/LLVM.h"
24 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/ADT/SmallPtrSet.h"
26 #include "llvm/ADT/SmallVector.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include <optional>
30 
31 #define DEBUG_TYPE "affine-structures"
32 
33 using namespace mlir;
34 using namespace affine;
35 using namespace presburger;
36 
37 
39  if (containsVar(val))
40  return;
41 
42  // Caller is expected to fully compose map/operands if necessary.
43  assert((isTopLevelValue(val) || isAffineInductionVar(val)) &&
44  "non-terminal symbol / loop IV expected");
45  // Outer loop IVs could be used in forOp's bounds.
46  if (auto loop = getForInductionVarOwner(val)) {
47  appendDimVar(val);
48  if (failed(this->addAffineForOpDomain(loop)))
49  LLVM_DEBUG(
50  loop.emitWarning("failed to add domain info to constraint system"));
51  return;
52  }
53  if (auto parallel = getAffineParallelInductionVarOwner(val)) {
54  appendDimVar(parallel.getIVs());
55  if (failed(this->addAffineParallelOpDomain(parallel)))
56  LLVM_DEBUG(parallel.emitWarning(
57  "failed to add domain info to constraint system"));
58  return;
59  }
60 
61  // Add top level symbol.
62  appendSymbolVar(val);
63  // Check if the symbol is a constant.
64  if (std::optional<int64_t> constOp = getConstantIntValue(val))
65  addBound(BoundType::EQ, val, constOp.value());
66 }
67 
68 LogicalResult
70  unsigned pos;
71  // Pre-condition for this method.
72  if (!findVar(forOp.getInductionVar(), &pos)) {
73  assert(false && "Value not found");
74  return failure();
75  }
76 
77  int64_t step = forOp.getStepAsInt();
78  if (step != 1) {
79  if (!forOp.hasConstantLowerBound())
80  LLVM_DEBUG(forOp.emitWarning("domain conservatively approximated"));
81  else {
82  // Add constraints for the stride.
83  // (iv - lb) % step = 0 can be written as:
84  // (iv - lb) - step * q = 0 where q = (iv - lb) / step.
85  // Add local variable 'q' and add the above equality.
86  // The first constraint is q = (iv - lb) floordiv step
87  SmallVector<int64_t, 8> dividend(getNumCols(), 0);
88  int64_t lb = forOp.getConstantLowerBound();
89  dividend[pos] = 1;
90  dividend.back() -= lb;
91  addLocalFloorDiv(dividend, step);
92  // Second constraint: (iv - lb) - step * q = 0.
93  SmallVector<int64_t, 8> eq(getNumCols(), 0);
94  eq[pos] = 1;
95  eq.back() -= lb;
96  // For the local var just added above.
97  eq[getNumCols() - 2] = -step;
98  addEquality(eq);
99  }
100  }
101 
102  if (forOp.hasConstantLowerBound()) {
103  addBound(BoundType::LB, pos, forOp.getConstantLowerBound());
104  } else {
105  // Non-constant lower bound case.
106  if (failed(addBound(BoundType::LB, pos, forOp.getLowerBoundMap(),
107  forOp.getLowerBoundOperands())))
108  return failure();
109  }
110 
111  if (forOp.hasConstantUpperBound()) {
112  addBound(BoundType::UB, pos, forOp.getConstantUpperBound() - 1);
113  return success();
114  }
115  // Non-constant upper bound case.
116  return addBound(BoundType::UB, pos, forOp.getUpperBoundMap(),
117  forOp.getUpperBoundOperands());
118 }
119 
121  AffineParallelOp parallelOp) {
122  size_t ivPos = 0;
123  for (Value iv : parallelOp.getIVs()) {
124  unsigned pos;
125  if (!findVar(iv, &pos)) {
126  assert(false && "variable expected for the IV value");
127  return failure();
128  }
129 
130  AffineMap lowerBound = parallelOp.getLowerBoundMap(ivPos);
131  if (lowerBound.isConstant())
132  addBound(BoundType::LB, pos, lowerBound.getSingleConstantResult());
133  else if (failed(addBound(BoundType::LB, pos, lowerBound,
134  parallelOp.getLowerBoundsOperands())))
135  return failure();
136 
137  auto upperBound = parallelOp.getUpperBoundMap(ivPos);
138  if (upperBound.isConstant())
139  addBound(BoundType::UB, pos, upperBound.getSingleConstantResult() - 1);
140  else if (failed(addBound(BoundType::UB, pos, upperBound,
141  parallelOp.getUpperBoundsOperands())))
142  return failure();
143  ++ivPos;
144  }
145  return success();
146 }
147 
148 LogicalResult
150  ArrayRef<AffineMap> ubMaps,
151  ArrayRef<Value> operands) {
152  assert(lbMaps.size() == ubMaps.size());
153  assert(lbMaps.size() <= getNumDimVars());
154 
155  for (unsigned i = 0, e = lbMaps.size(); i < e; ++i) {
156  AffineMap lbMap = lbMaps[i];
157  AffineMap ubMap = ubMaps[i];
158  assert(!lbMap || lbMap.getNumInputs() == operands.size());
159  assert(!ubMap || ubMap.getNumInputs() == operands.size());
160 
161  // Check if this slice is just an equality along this dimension. If so,
162  // retrieve the existing loop it equates to and add it to the system.
163  if (lbMap && ubMap && lbMap.getNumResults() == 1 &&
164  ubMap.getNumResults() == 1 &&
165  lbMap.getResult(0) + 1 == ubMap.getResult(0) &&
166  // The condition above will be true for maps describing a single
167  // iteration (e.g., lbMap.getResult(0) = 0, ubMap.getResult(0) = 1).
168  // Make sure we skip those cases by checking that the lb result is not
169  // just a constant.
170  !isa<AffineConstantExpr>(lbMap.getResult(0))) {
171  // Limited support: we expect the lb result to be just a loop dimension.
172  // Not supported otherwise for now.
173  AffineDimExpr result = dyn_cast<AffineDimExpr>(lbMap.getResult(0));
174  if (!result)
175  return failure();
176 
177  AffineForOp loop =
178  getForInductionVarOwner(operands[result.getPosition()]);
179  if (!loop)
180  return failure();
181 
182  if (failed(addAffineForOpDomain(loop)))
183  return failure();
184  continue;
185  }
186 
187  // This slice refers to a loop that doesn't exist in the IR yet. Add its
188  // bounds to the system assuming its dimension variable position is the
189  // same as the position of the loop in the loop nest.
190  if (lbMap && failed(addBound(BoundType::LB, i, lbMap, operands)))
191  return failure();
192  if (ubMap && failed(addBound(BoundType::UB, i, ubMap, operands)))
193  return failure();
194  }
195  return success();
196 }
197 
199  IntegerSet set = ifOp.getIntegerSet();
200  // Canonicalize set and operands to ensure unique values for
201  // FlatAffineValueConstraints below and for early simplification.
202  SmallVector<Value> operands(ifOp.getOperands());
203  canonicalizeSetAndOperands(&set, &operands);
204 
205  // Create the base constraints from the integer set attached to ifOp.
206  FlatAffineValueConstraints cst(set, operands);
207 
208  // Merge the constraints from ifOp to the current domain. We need first merge
209  // and align the IDs from both constraints, and then append the constraints
210  // from the ifOp into the current one.
211  mergeAndAlignVarsWithOther(0, &cst);
212  append(cst);
213 }
214 
215 LogicalResult FlatAffineValueConstraints::addBound(BoundType type, unsigned pos,
216  AffineMap boundMap,
217  ValueRange boundOperands) {
218  // Fully compose map and operands; canonicalize and simplify so that we
219  // transitively get to terminal symbols or loop IVs.
220  auto map = boundMap;
221  SmallVector<Value, 4> operands(boundOperands.begin(), boundOperands.end());
222  fullyComposeAffineMapAndOperands(&map, &operands);
223  map = simplifyAffineMap(map);
224  canonicalizeMapAndOperands(&map, &operands);
225  for (auto operand : operands)
226  addInductionVarOrTerminalSymbol(operand);
227  return addBound(type, pos, computeAlignedMap(map, operands));
228 }
229 
230 // Adds slice lower bounds represented by lower bounds in 'lbMaps' and upper
231 // bounds in 'ubMaps' to each value in `values' that appears in the constraint
232 // system. Note that both lower/upper bounds share the same operand list
233 // 'operands'.
234 // This function assumes 'values.size' == 'lbMaps.size' == 'ubMaps.size', and
235 // skips any null AffineMaps in 'lbMaps' or 'ubMaps'.
236 // Note that both lower/upper bounds use operands from 'operands'.
237 // Returns failure for unimplemented cases such as semi-affine expressions or
238 // expressions with mod/floordiv.
240  ArrayRef<Value> values, ArrayRef<AffineMap> lbMaps,
241  ArrayRef<AffineMap> ubMaps, ArrayRef<Value> operands) {
242  assert(values.size() == lbMaps.size());
243  assert(lbMaps.size() == ubMaps.size());
244 
245  for (unsigned i = 0, e = lbMaps.size(); i < e; ++i) {
246  unsigned pos;
247  if (!findVar(values[i], &pos))
248  continue;
249 
250  AffineMap lbMap = lbMaps[i];
251  AffineMap ubMap = ubMaps[i];
252  assert(!lbMap || lbMap.getNumInputs() == operands.size());
253  assert(!ubMap || ubMap.getNumInputs() == operands.size());
254 
255  // Check if this slice is just an equality along this dimension.
256  if (lbMap && ubMap && lbMap.getNumResults() == 1 &&
257  ubMap.getNumResults() == 1 &&
258  lbMap.getResult(0) + 1 == ubMap.getResult(0)) {
259  if (failed(addBound(BoundType::EQ, pos, lbMap, operands)))
260  return failure();
261  continue;
262  }
263 
264  // If lower or upper bound maps are null or provide no results, it implies
265  // that the source loop was not at all sliced, and the entire loop will be a
266  // part of the slice.
267  if (lbMap && lbMap.getNumResults() != 0 && ubMap &&
268  ubMap.getNumResults() != 0) {
269  if (failed(addBound(BoundType::LB, pos, lbMap, operands)))
270  return failure();
271  if (failed(addBound(BoundType::UB, pos, ubMap, operands)))
272  return failure();
273  } else {
274  auto loop = getForInductionVarOwner(values[i]);
275  if (failed(this->addAffineForOpDomain(loop)))
276  return failure();
277  }
278  }
279  return success();
280 }
281 
282 LogicalResult
284  return composeMatchingMap(
285  computeAlignedMap(vMap->getAffineMap(), vMap->getOperands()));
286 }
287 
288 // Turn a symbol into a dimension.
290  unsigned pos;
291  if (cst->findVar(value, &pos) && pos >= cst->getNumDimVars() &&
292  pos < cst->getNumDimAndSymbolVars()) {
293  cst->swapVar(pos, cst->getNumDimVars());
294  cst->setDimSymbolSeparation(cst->getNumSymbolVars() - 1);
295  }
296 }
297 
298 // Changes all symbol variables which are loop IVs to dim variables.
300  // Gather all symbols which are loop IVs.
301  SmallVector<Value, 4> loopIVs;
302  for (unsigned i = getNumDimVars(), e = getNumDimAndSymbolVars(); i < e; i++) {
303  if (hasValue(i) && getForInductionVarOwner(getValue(i)))
304  loopIVs.push_back(getValue(i));
305  }
306  // Turn each symbol in 'loopIVs' into a dim variable.
307  for (auto iv : loopIVs) {
308  turnSymbolIntoDim(this, iv);
309  }
310 }
311 
313  unsigned pos, unsigned ineqPos, AffineValueMap &vmap,
314  MLIRContext *context) const {
315  unsigned numDims = getNumDimVars();
316  unsigned numSyms = getNumSymbolVars();
317 
318  assert(pos < numDims && "invalid position");
319  assert(ineqPos < getNumInequalities() && "invalid inequality position");
320 
321  // Get expressions for local vars.
322  SmallVector<AffineExpr, 8> memo(getNumVars(), AffineExpr());
323  if (failed(computeLocalVars(memo, context)))
324  assert(false &&
325  "one or more local exprs do not have an explicit representation");
326  auto localExprs = ArrayRef<AffineExpr>(memo).take_back(getNumLocalVars());
327 
328  // Compute the AffineExpr lower/upper bound for this inequality.
329  SmallVector<int64_t, 8> inequality = getInequality64(ineqPos);
331  bound.reserve(getNumCols() - 1);
332  // Everything other than the coefficient at `pos`.
333  bound.append(inequality.begin(), inequality.begin() + pos);
334  bound.append(inequality.begin() + pos + 1, inequality.end());
335 
336  if (inequality[pos] > 0)
337  // Lower bound.
338  std::transform(bound.begin(), bound.end(), bound.begin(),
339  std::negate<int64_t>());
340  else
341  // Upper bound (which is exclusive).
342  bound.back() += 1;
343 
344  // Convert to AffineExpr (tree) form.
345  auto boundExpr = getAffineExprFromFlatForm(bound, numDims - 1, numSyms,
346  localExprs, context);
347 
348  // Get the values to bind to this affine expr (all dims and symbols).
349  SmallVector<Value, 4> operands;
350  getValues(0, pos, &operands);
351  SmallVector<Value, 4> trailingOperands;
352  getValues(pos + 1, getNumDimAndSymbolVars(), &trailingOperands);
353  operands.append(trailingOperands.begin(), trailingOperands.end());
354  vmap.reset(AffineMap::get(numDims - 1, numSyms, boundExpr), operands);
355 }
356 
358  FlatAffineValueConstraints domain = *this;
359  // Convert all range variables to local variables.
360  domain.convertToLocal(VarKind::SetDim, getNumDomainDims(),
361  getNumDomainDims() + getNumRangeDims());
362  return domain;
363 }
364 
366  FlatAffineValueConstraints range = *this;
367  // Convert all domain variables to local variables.
368  range.convertToLocal(VarKind::SetDim, 0, getNumDomainDims());
369  return range;
370 }
371 
373  assert(getNumDomainDims() == other.getNumRangeDims() &&
374  "Domain of this and range of other do not match");
375  assert(space.getDomainSpace().isAligned(other.getSpace().getRangeSpace()) &&
376  "Values of domain of this and range of other do not match");
377 
378  FlatAffineRelation rel = other;
379 
380  // Convert `rel` from
381  // [otherDomain] -> [otherRange]
382  // to
383  // [otherDomain] -> [otherRange thisRange]
384  // and `this` from
385  // [thisDomain] -> [thisRange]
386  // to
387  // [otherDomain thisDomain] -> [thisRange].
388  unsigned removeDims = rel.getNumRangeDims();
389  insertDomainVar(0, rel.getNumDomainDims());
390  rel.appendRangeVar(getNumRangeDims());
391 
392  // Merge symbol and local variables.
393  mergeSymbolVars(rel);
394  mergeLocalVars(rel);
395 
396  // Convert `rel` from [otherDomain] -> [otherRange thisRange] to
397  // [otherDomain] -> [thisRange] by converting first otherRange range vars
398  // to local vars.
399  rel.convertToLocal(VarKind::SetDim, rel.getNumDomainDims(),
400  rel.getNumDomainDims() + removeDims);
401  // Convert `this` from [otherDomain thisDomain] -> [thisRange] to
402  // [otherDomain] -> [thisRange] by converting last thisDomain domain vars
403  // to local vars.
404  convertToLocal(VarKind::SetDim, getNumDomainDims() - removeDims,
405  getNumDomainDims());
406 
407  auto thisMaybeValues = getMaybeValues(VarKind::SetDim);
408  auto relMaybeValues = rel.getMaybeValues(VarKind::SetDim);
409 
410  // Add and match domain of `rel` to domain of `this`.
411  for (unsigned i = 0, e = rel.getNumDomainDims(); i < e; ++i)
412  if (relMaybeValues[i].has_value())
413  setValue(i, *relMaybeValues[i]);
414  // Add and match range of `this` to range of `rel`.
415  for (unsigned i = 0, e = getNumRangeDims(); i < e; ++i) {
416  unsigned rangeIdx = rel.getNumDomainDims() + i;
417  if (thisMaybeValues[rangeIdx].has_value())
418  rel.setValue(rangeIdx, *thisMaybeValues[rangeIdx]);
419  }
420 
421  // Append `this` to `rel` and simplify constraints.
422  rel.append(*this);
424 
425  *this = rel;
426 }
427 
429  unsigned oldDomain = getNumDomainDims();
430  unsigned oldRange = getNumRangeDims();
431  // Add new range vars.
432  appendRangeVar(oldDomain);
433  // Swap new vars with domain.
434  for (unsigned i = 0; i < oldDomain; ++i)
435  swapVar(i, oldDomain + oldRange + i);
436  // Remove the swapped domain.
437  removeVarRange(0, oldDomain);
438  // Set domain and range as inverse.
439  numDomainDims = oldRange;
440  numRangeDims = oldDomain;
441 }
442 
443 void FlatAffineRelation::insertDomainVar(unsigned pos, unsigned num) {
444  assert(pos <= getNumDomainDims() &&
445  "Var cannot be inserted at invalid position");
446  insertDimVar(pos, num);
447  numDomainDims += num;
448 }
449 
450 void FlatAffineRelation::insertRangeVar(unsigned pos, unsigned num) {
451  assert(pos <= getNumRangeDims() &&
452  "Var cannot be inserted at invalid position");
453  insertDimVar(getNumDomainDims() + pos, num);
454  numRangeDims += num;
455 }
456 
458  insertDimVar(getNumDomainDims(), num);
459  numDomainDims += num;
460 }
461 
463  insertDimVar(getNumDimVars(), num);
464  numRangeDims += num;
465 }
466 
467 void FlatAffineRelation::removeVarRange(VarKind kind, unsigned varStart,
468  unsigned varLimit) {
469  assert(varLimit <= getNumVarKind(kind));
470  if (varStart >= varLimit)
471  return;
472 
473  FlatAffineValueConstraints::removeVarRange(kind, varStart, varLimit);
474 
475  // If kind is not SetDim, domain and range don't need to be updated.
476  if (kind != VarKind::SetDim)
477  return;
478 
479  // Compute number of domain and range variables to remove. This is done by
480  // intersecting the range of domain/range vars with range of vars to remove.
481  unsigned intersectDomainLHS = std::min(varLimit, getNumDomainDims());
482  unsigned intersectDomainRHS = varStart;
483  unsigned intersectRangeLHS = std::min(varLimit, getNumDimVars());
484  unsigned intersectRangeRHS = std::max(varStart, getNumDomainDims());
485 
486  if (intersectDomainLHS > intersectDomainRHS)
487  numDomainDims -= intersectDomainLHS - intersectDomainRHS;
488  if (intersectRangeLHS > intersectRangeRHS)
489  numRangeDims -= intersectRangeLHS - intersectRangeRHS;
490 }
491 
493  IntegerRelation &rel) {
494  // Get flattened affine expressions.
495  std::vector<SmallVector<int64_t, 8>> flatExprs;
496  FlatAffineValueConstraints localVarCst;
497  if (failed(getFlattenedAffineExprs(map, &flatExprs, &localVarCst)))
498  return failure();
499 
500  const unsigned oldDimNum = localVarCst.getNumDimVars();
501  const unsigned oldCols = localVarCst.getNumCols();
502  const unsigned numRangeVars = map.getNumResults();
503  const unsigned numDomainVars = map.getNumDims();
504 
505  // Add range as the new expressions.
506  localVarCst.appendDimVar(numRangeVars);
507 
508  // Add identifiers to the local constraints as getFlattenedAffineExprs creates
509  // a FlatLinearConstraints with no identifiers.
510  for (unsigned i = 0, e = localVarCst.getNumDimAndSymbolVars(); i < e; ++i)
511  localVarCst.setValue(i, Value());
512 
513  // Add equalities between source and range.
514  SmallVector<int64_t, 8> eq(localVarCst.getNumCols());
515  for (unsigned i = 0, e = map.getNumResults(); i < e; ++i) {
516  // Zero fill.
517  std::fill(eq.begin(), eq.end(), 0);
518  // Fill equality.
519  for (unsigned j = 0, f = oldDimNum; j < f; ++j)
520  eq[j] = flatExprs[i][j];
521  for (unsigned j = oldDimNum, f = oldCols; j < f; ++j)
522  eq[j + numRangeVars] = flatExprs[i][j];
523  // Set this dimension to -1 to equate lhs and rhs and add equality.
524  eq[numDomainVars + i] = -1;
525  localVarCst.addEquality(eq);
526  }
527 
528  rel = localVarCst;
529  return success();
530 }
531 
533  IntegerRelation &rel) {
534 
535  AffineMap affineMap = map.getAffineMap();
536  if (failed(getRelationFromMap(affineMap, rel)))
537  return failure();
538 
539  // Set identifiers for domain and symbol variables.
540  for (unsigned i = 0, e = affineMap.getNumDims(); i < e; ++i)
541  rel.setId(VarKind::SetDim, i, Identifier(map.getOperand(i)));
542 
543  const unsigned mapNumResults = affineMap.getNumResults();
544  for (unsigned i = 0, e = rel.getNumSymbolVars(); i < e; ++i)
545  rel.setId(
546  VarKind::Symbol, i,
547  Identifier(map.getOperand(rel.getNumDimVars() + i - mapNumResults)));
548 
549  return success();
550 }
static void turnSymbolIntoDim(FlatAffineValueConstraints *cst, Value value)
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
A dimensional identifier appearing in an affine expression.
Definition: AffineExpr.h:236
unsigned getPosition() const
Definition: AffineExpr.cpp:348
Base type for affine expression.
Definition: AffineExpr.h:68
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition: AffineMap.h:46
int64_t getSingleConstantResult() const
Returns the constant result of this map.
Definition: AffineMap.cpp:381
bool isConstant() const
Returns true if this affine map has only constant results.
Definition: AffineMap.cpp:377
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
unsigned getNumDims() const
Definition: AffineMap.cpp:394
unsigned getNumResults() const
Definition: AffineMap.cpp:402
unsigned getNumInputs() const
Definition: AffineMap.cpp:403
AffineExpr getResult(unsigned idx) const
Definition: AffineMap.cpp:411
SmallVector< std::optional< Value > > getMaybeValues() const
void removeVarRange(presburger::VarKind kind, unsigned varStart, unsigned varLimit) override
Removes variables in the column range [varStart, varLimit), and copies any remaining valid data into ...
bool findVar(Value val, unsigned *pos, unsigned offset=0) const
Looks up the position of the variable with the specified Value starting with variables at offset offs...
void setValue(unsigned pos, Value val)
Sets the Value associated with the pos^th variable.
An integer set representing a conjunction of one or more affine equalities and inequalities.
Definition: IntegerSet.h:44
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
This class provides an abstraction over the different types of ranges over Values.
Definition: ValueRange.h:381
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:96
An AffineValueMap is an affine map plus its ML value operands and results for analysis purposes.
Value getOperand(unsigned i) const
ArrayRef< Value > getOperands() const
void reset(AffineMap map, ValueRange operands, ValueRange results={})
A FlatAffineRelation represents a set of ordered pairs (domain -> range) where "domain" and "range" a...
void appendDomainVar(unsigned num=1)
Append num variables of the specified kind after the last variable of that kind.
void compose(const FlatAffineRelation &other)
Given affine relation other: (domainOther -> rangeOther), this operation takes the composition of oth...
unsigned getNumDomainDims() const
Returns the number of variables corresponding to domain/range of relation.
void inverse()
Swap domain and range of the relation.
FlatAffineValueConstraints getDomainSet() const
Returns a set corresponding to the domain/range of the affine relation.
void removeVarRange(VarKind kind, unsigned varStart, unsigned varLimit) override
Removes variables in the column range [varStart, varLimit), and copies any remaining valid data into ...
FlatAffineValueConstraints getRangeSet() const
void insertRangeVar(unsigned pos, unsigned num=1)
void insertDomainVar(unsigned pos, unsigned num=1)
Insert num variables of the specified kind after the pos variable of that kind.
FlatAffineValueConstraints is an extension of FlatLinearValueConstraints with helper functions for Af...
void addInductionVarOrTerminalSymbol(Value val)
Add the specified values as a dim or symbol var depending on its nature, if it already doesn't exist ...
void addAffineIfOpDomain(AffineIfOp ifOp)
Adds constraints imposed by the affine.if operation.
void convertLoopIVSymbolsToDims()
Changes all symbol variables which are loop IVs to dim variables.
LogicalResult addDomainFromSliceMaps(ArrayRef< AffineMap > lbMaps, ArrayRef< AffineMap > ubMaps, ArrayRef< Value > operands)
Adds constraints (lower and upper bounds) for each loop in the loop nest described by the bound maps ...
LogicalResult addAffineParallelOpDomain(AffineParallelOp parallelOp)
Add constraints (lower and upper bounds) for the specified 'affine.parallel' operation's Value using ...
LogicalResult addAffineForOpDomain(AffineForOp forOp)
Adds constraints (lower and upper bounds) for the specified 'affine.for' operation's Value using IR i...
void addBound(presburger::BoundType type, Value val, int64_t value)
Adds a constant bound for the variable associated with the given Value.
void getIneqAsAffineValueMap(unsigned pos, unsigned ineqPos, AffineValueMap &vmap, MLIRContext *context) const
Returns the bound for the variable at pos from the inequality at ineqPos as a 1-d affine value map (a...
LogicalResult addSliceBounds(ArrayRef< Value > values, ArrayRef< AffineMap > lbMaps, ArrayRef< AffineMap > ubMaps, ArrayRef< Value > operands)
Adds slice lower bounds represented by lower bounds in lbMaps and upper bounds in ubMaps to each vari...
LogicalResult composeMap(const AffineValueMap *vMap)
Composes the affine value map with this FlatAffineValueConstrains, adding the results of the map as d...
An Identifier stores a pointer to an object, such as a Value or an Operation.
An IntegerRelation represents the set of points from a PresburgerSpace that satisfy a list of affine ...
void setId(VarKind kind, unsigned i, Identifier id)
Set the identifier for the ith variable of the specified kind of the IntegerRelation's PresburgerSpac...
virtual void swapVar(unsigned posA, unsigned posB)
Swap the posA^th variable with the posB^th variable.
void convertToLocal(VarKind kind, unsigned varStart, unsigned varLimit)
void append(const IntegerRelation &other)
Appends constraints from other into this.
void addEquality(ArrayRef< DynamicAPInt > eq)
Adds an equality from the coefficients specified in eq.
void setDimSymbolSeparation(unsigned newSymbolCount)
Changes the partition between dimensions and symbols.
unsigned getNumCols() const
Returns the number of columns in the constraint system.
void removeRedundantLocalVars()
Removes local variables using equalities.
const PresburgerSpace & getSpace() const
Returns a reference to the underlying space.
PresburgerSpace getRangeSpace() const
void fullyComposeAffineMapAndOperands(AffineMap *map, SmallVectorImpl< Value > *operands)
Given an affine map map and its input operands, this method composes into map, maps of AffineApplyOps...
Definition: AffineOps.cpp:1132
bool isAffineInductionVar(Value val)
Returns true if the provided value is the induction variable of an AffineForOp or AffineParallelOp.
Definition: AffineOps.cpp:2559
AffineForOp getForInductionVarOwner(Value val)
Returns the loop parent of an induction variable.
Definition: AffineOps.cpp:2563
void canonicalizeMapAndOperands(AffineMap *map, SmallVectorImpl< Value > *operands)
Modifies both map and operands in-place so as to:
Definition: AffineOps.cpp:1433
bool isTopLevelValue(Value value)
A utility function to check if a value is defined at the top level of an op with trait AffineScope or...
Definition: AffineOps.cpp:246
void canonicalizeSetAndOperands(IntegerSet *set, SmallVectorImpl< Value > *operands)
Canonicalizes an integer set the same way canonicalizeMapAndOperands does for affine maps.
Definition: AffineOps.cpp:1438
LogicalResult getRelationFromMap(AffineMap &map, presburger::IntegerRelation &rel)
Builds a relation from the given AffineMap/AffineValueMap map, containing all pairs of the form opera...
AffineParallelOp getAffineParallelInductionVarOwner(Value val)
Returns true if the provided value is among the induction variables of an AffineParallelOp.
Definition: AffineOps.cpp:2574
BoundType
The type of bound: equal, lower bound or upper bound.
VarKind
Kind of variable.
void mergeLocalVars(IntegerRelation &relA, IntegerRelation &relB, llvm::function_ref< bool(unsigned i, unsigned j)> merge)
Given two relations, A and B, add additional local vars to the sets such that both have the union of ...
Definition: Utils.cpp:289
Include the generated interface declarations.
AffineMap simplifyAffineMap(AffineMap map)
Simplifies an affine map by simplifying its underlying AffineExpr results.
Definition: AffineMap.cpp:750
std::optional< int64_t > getConstantIntValue(OpFoldResult ofr)
If ofr is a constant integer or an IntegerAttr, return the integer.
AffineExpr getAffineExprFromFlatForm(ArrayRef< int64_t > flatExprs, unsigned numDims, unsigned numSymbols, ArrayRef< AffineExpr > localExprs, MLIRContext *context)
Constructs an affine expression from a flat ArrayRef.
LogicalResult getFlattenedAffineExprs(AffineMap map, std::vector< SmallVector< int64_t, 8 >> *flattenedExprs, FlatLinearConstraints *cst=nullptr, bool addConservativeSemiAffineBounds=false)
Flattens the result expressions of the map to their corresponding flattened forms and set in 'flatten...
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.