MLIR  21.0.0git
IntegerRelation.cpp
Go to the documentation of this file.
1 //===- IntegerRelation.cpp - MLIR IntegerRelation 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 // A class to represent an relation over integer tuples. A relation is
10 // represented as a constraint system over a space of tuples of integer valued
11 // variables supporting symbolic variables and existential quantification.
12 //
13 //===----------------------------------------------------------------------===//
14 
23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/ADT/DenseSet.h"
25 #include "llvm/ADT/STLExtras.h"
26 #include "llvm/ADT/Sequence.h"
27 #include "llvm/ADT/SmallBitVector.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/LogicalResult.h"
30 #include "llvm/Support/raw_ostream.h"
31 #include <algorithm>
32 #include <cassert>
33 #include <functional>
34 #include <memory>
35 #include <numeric>
36 #include <optional>
37 #include <sstream>
38 #include <string>
39 #include <utility>
40 #include <vector>
41 
42 #define DEBUG_TYPE "presburger"
43 
44 using namespace mlir;
45 using namespace presburger;
46 
47 using llvm::SmallDenseMap;
48 using llvm::SmallDenseSet;
49 
50 std::unique_ptr<IntegerRelation> IntegerRelation::clone() const {
51  return std::make_unique<IntegerRelation>(*this);
52 }
53 
54 std::unique_ptr<IntegerPolyhedron> IntegerPolyhedron::clone() const {
55  return std::make_unique<IntegerPolyhedron>(*this);
56 }
57 
59  assert(space.getNumVars() == oSpace.getNumVars() && "invalid space!");
60  space = oSpace;
61 }
62 
64  assert(oSpace.getNumLocalVars() == 0 && "no locals should be present!");
65  assert(oSpace.getNumVars() <= getNumVars() && "invalid space!");
66  unsigned newNumLocals = getNumVars() - oSpace.getNumVars();
67  space = oSpace;
68  space.insertVar(VarKind::Local, 0, newNumLocals);
69 }
70 
72  assert(space.isUsingIds() &&
73  "space must be using identifiers to set an identifier");
74  assert(kind != VarKind::Local && "local variables cannot have identifiers");
75  assert(i < space.getNumVarKind(kind) && "invalid variable index");
76  space.setId(kind, i, id);
77 }
78 
80  if (!space.isUsingIds())
81  space.resetIds();
82  return space.getIds(kind);
83 }
84 
86  assert(space.isEqual(other.getSpace()) && "Spaces must be equal.");
87 
89  other.getNumInequalities());
91 
92  for (unsigned r = 0, e = other.getNumInequalities(); r < e; r++) {
93  addInequality(other.getInequality(r));
94  }
95  for (unsigned r = 0, e = other.getNumEqualities(); r < e; r++) {
96  addEquality(other.getEquality(r));
97  }
98 }
99 
101  IntegerRelation result = *this;
102  result.mergeLocalVars(other);
103  result.append(other);
104  return result;
105 }
106 
107 bool IntegerRelation::isEqual(const IntegerRelation &other) const {
108  assert(space.isCompatible(other.getSpace()) && "Spaces must be compatible.");
109  return PresburgerRelation(*this).isEqual(PresburgerRelation(other));
110 }
111 
113  if (!space.isEqual(other.getSpace()))
114  return false;
115  if (getNumEqualities() != other.getNumEqualities())
116  return false;
117  if (getNumInequalities() != other.getNumInequalities())
118  return false;
119 
120  unsigned cols = getNumCols();
121  for (unsigned i = 0, eqs = getNumEqualities(); i < eqs; ++i) {
122  for (unsigned j = 0; j < cols; ++j) {
123  if (atEq(i, j) != other.atEq(i, j))
124  return false;
125  }
126  }
127  for (unsigned i = 0, ineqs = getNumInequalities(); i < ineqs; ++i) {
128  for (unsigned j = 0; j < cols; ++j) {
129  if (atIneq(i, j) != other.atIneq(i, j))
130  return false;
131  }
132  }
133  return true;
134 }
135 
137  assert(space.isCompatible(other.getSpace()) && "Spaces must be compatible.");
138  return PresburgerRelation(*this).isSubsetOf(PresburgerRelation(other));
139 }
140 
143  assert(getNumSymbolVars() == 0 && "Symbols are not supported!");
146 
147  if (!maybeLexMin.isBounded())
148  return maybeLexMin;
149 
150  // The Simplex returns the lexmin over all the variables including locals. But
151  // locals are not actually part of the space and should not be returned in the
152  // result. Since the locals are placed last in the list of variables, they
153  // will be minimized last in the lexmin. So simply truncating out the locals
154  // from the end of the answer gives the desired lexmin over the dimensions.
155  assert(maybeLexMin->size() == getNumVars() &&
156  "Incorrect number of vars in lexMin!");
157  maybeLexMin->resize(getNumDimAndSymbolVars());
158  return maybeLexMin;
159 }
160 
163  assert(getNumSymbolVars() == 0 && "Symbols are not supported!");
165  LexSimplex(*this).findIntegerLexMin();
166 
167  if (!maybeLexMin.isBounded())
168  return maybeLexMin.getKind();
169 
170  // The Simplex returns the lexmin over all the variables including locals. But
171  // locals are not actually part of the space and should not be returned in the
172  // result. Since the locals are placed last in the list of variables, they
173  // will be minimized last in the lexmin. So simply truncating out the locals
174  // from the end of the answer gives the desired lexmin over the dimensions.
175  assert(maybeLexMin->size() == getNumVars() &&
176  "Incorrect number of vars in lexMin!");
177  maybeLexMin->resize(getNumDimAndSymbolVars());
178  return maybeLexMin;
179 }
180 
182  return llvm::all_of(range, [](const DynamicAPInt &x) { return x == 0; });
183 }
184 
186  unsigned begin, unsigned count) {
187  // We loop until i > 0 and index into i - 1 to avoid sign issues.
188  //
189  // We iterate backwards so that whether we remove constraint i - 1 or not, the
190  // next constraint to be tested is always i - 2.
191  for (unsigned i = poly.getNumEqualities(); i > 0; i--)
192  if (!rangeIsZero(poly.getEquality(i - 1).slice(begin, count)))
193  poly.removeEquality(i - 1);
194  for (unsigned i = poly.getNumInequalities(); i > 0; i--)
195  if (!rangeIsZero(poly.getInequality(i - 1).slice(begin, count)))
196  poly.removeInequality(i - 1);
197 }
198 
201 }
202 
204  unsigned curNum = getNumVarKind(kind);
205  assert(num <= curNum && "Can't truncate to more vars!");
206  removeVarRange(kind, num, curNum);
207 }
208 
210  const CountsSnapshot &counts) {
212 }
213 
221 }
222 
224  // If there are no locals, we're done.
225  if (getNumLocalVars() == 0)
226  return PresburgerRelation(*this);
227 
228  // Move all the non-div locals to the end, as the current API to
229  // SymbolicLexOpt requires these to form a contiguous range.
230  //
231  // Take a copy so we can perform mutations.
232  IntegerRelation copy = *this;
233  std::vector<MaybeLocalRepr> reprs(getNumLocalVars());
234  copy.getLocalReprs(&reprs);
235 
236  // Iterate through all the locals. The last `numNonDivLocals` are the locals
237  // that have been scanned already and do not have division representations.
238  unsigned numNonDivLocals = 0;
239  unsigned offset = copy.getVarKindOffset(VarKind::Local);
240  for (unsigned i = 0, e = copy.getNumLocalVars(); i < e - numNonDivLocals;) {
241  if (!reprs[i]) {
242  // Whenever we come across a local that does not have a division
243  // representation, we swap it to the `numNonDivLocals`-th last position
244  // and increment `numNonDivLocal`s. `reprs` also needs to be swapped.
245  copy.swapVar(offset + i, offset + e - numNonDivLocals - 1);
246  std::swap(reprs[i], reprs[e - numNonDivLocals - 1]);
247  ++numNonDivLocals;
248  continue;
249  }
250  ++i;
251  }
252 
253  // If there are no non-div locals, we're done.
254  if (numNonDivLocals == 0)
255  return PresburgerRelation(*this);
256 
257  // We computeSymbolicIntegerLexMin by considering the non-div locals as
258  // "non-symbols" and considering everything else as "symbols". This will
259  // compute a function mapping assignments to "symbols" to the
260  // lexicographically minimal valid assignment of "non-symbols", when a
261  // satisfying assignment exists. It separately returns the set of assignments
262  // to the "symbols" such that a satisfying assignment to the "non-symbols"
263  // exists but the lexmin is unbounded. We basically want to find the set of
264  // values of the "symbols" such that an assignment to the "non-symbols"
265  // exists, which is the union of the domain of the returned lexmin function
266  // and the returned set of assignments to the "symbols" that makes the lexmin
267  // unbounded.
268  SymbolicLexOpt lexminResult =
269  SymbolicLexSimplex(copy, /*symbolOffset*/ 0,
271  /*numDims=*/copy.getNumVars() - numNonDivLocals)))
273  PresburgerRelation result =
274  lexminResult.lexopt.getDomain().unionSet(lexminResult.unboundedDomain);
275 
276  // The result set might lie in the wrong space -- all its ids are dims.
277  // Set it to the desired space and return.
280  result.setSpace(space);
281  return result;
282 }
283 
285  // Symbol and Domain vars will be used as symbols for symbolic lexmin.
286  // In other words, for every value of the symbols and domain, return the
287  // lexmin value of the (range, locals).
288  llvm::SmallBitVector isSymbol(getNumVars(), false);
289  isSymbol.set(getVarKindOffset(VarKind::Symbol),
291  isSymbol.set(getVarKindOffset(VarKind::Domain),
293  // Compute the symbolic lexmin of the dims and locals, with the symbols being
294  // the actual symbols of this set.
295  // The resultant space of lexmin is the space of the relation itself.
296  SymbolicLexOpt result =
297  SymbolicLexSimplex(*this,
299  /*numDims=*/getNumDomainVars(),
300  /*numSymbols=*/getNumSymbolVars())),
301  isSymbol)
303 
304  // We want to return only the lexmin over the dims, so strip the locals from
305  // the computed lexmin.
307  result.lexopt.getNumOutputs());
308  return result;
309 }
310 
311 /// findSymbolicIntegerLexMax is implemented using findSymbolicIntegerLexMin as
312 /// follows:
313 /// 1. A new relation is created which is `this` relation with the sign of
314 /// each dimension variable in range flipped;
315 /// 2. findSymbolicIntegerLexMin is called on the range negated relation to
316 /// compute the negated lexmax of `this` relation;
317 /// 3. The sign of the negated lexmax is flipped and returned.
319  IntegerRelation flippedRel = *this;
320  // Flip range sign by flipping the sign of range variables in all constraints.
321  for (unsigned j = getNumDomainVars(),
323  j < b; j++) {
324  for (unsigned i = 0, a = getNumEqualities(); i < a; i++)
325  flippedRel.atEq(i, j) = -1 * atEq(i, j);
326  for (unsigned i = 0, a = getNumInequalities(); i < a; i++)
327  flippedRel.atIneq(i, j) = -1 * atIneq(i, j);
328  }
329  // Compute negated lexmax by computing lexmin.
330  SymbolicLexOpt flippedSymbolicIntegerLexMax =
331  flippedRel.findSymbolicIntegerLexMin(),
332  symbolicIntegerLexMax(
333  flippedSymbolicIntegerLexMax.lexopt.getSpace());
334  // Get lexmax by flipping range sign in the PWMA constraints.
335  for (auto &flippedPiece :
336  flippedSymbolicIntegerLexMax.lexopt.getAllPieces()) {
337  IntMatrix mat = flippedPiece.output.getOutputMatrix();
338  for (unsigned i = 0, e = mat.getNumRows(); i < e; i++)
339  mat.negateRow(i);
340  MultiAffineFunction maf(flippedPiece.output.getSpace(), mat);
341  PWMAFunction::Piece piece = {flippedPiece.domain, maf};
342  symbolicIntegerLexMax.lexopt.addPiece(piece);
343  }
344  symbolicIntegerLexMax.unboundedDomain =
345  flippedSymbolicIntegerLexMax.unboundedDomain;
346  return symbolicIntegerLexMax;
347 }
348 
351  return PresburgerRelation(*this).subtract(set);
352 }
353 
354 unsigned IntegerRelation::insertVar(VarKind kind, unsigned pos, unsigned num) {
355  assert(pos <= getNumVarKind(kind));
356 
357  unsigned insertPos = space.insertVar(kind, pos, num);
358  inequalities.insertColumns(insertPos, num);
359  equalities.insertColumns(insertPos, num);
360  return insertPos;
361 }
362 
363 unsigned IntegerRelation::appendVar(VarKind kind, unsigned num) {
364  unsigned pos = getNumVarKind(kind);
365  return insertVar(kind, pos, num);
366 }
367 
369  assert(eq.size() == getNumCols());
370  unsigned row = equalities.appendExtraRow();
371  for (unsigned i = 0, e = eq.size(); i < e; ++i)
372  equalities(row, i) = eq[i];
373 }
374 
376  assert(inEq.size() == getNumCols());
377  unsigned row = inequalities.appendExtraRow();
378  for (unsigned i = 0, e = inEq.size(); i < e; ++i)
379  inequalities(row, i) = inEq[i];
380 }
381 
383  removeVarRange(kind, pos, pos + 1);
384 }
385 
386 void IntegerRelation::removeVar(unsigned pos) { removeVarRange(pos, pos + 1); }
387 
389  unsigned varLimit) {
390  assert(varLimit <= getNumVarKind(kind));
391 
392  if (varStart >= varLimit)
393  return;
394 
395  // Remove eliminated variables from the constraints.
396  unsigned offset = getVarKindOffset(kind);
397  equalities.removeColumns(offset + varStart, varLimit - varStart);
398  inequalities.removeColumns(offset + varStart, varLimit - varStart);
399 
400  // Remove eliminated variables from the space.
401  space.removeVarRange(kind, varStart, varLimit);
402 }
403 
404 void IntegerRelation::removeVarRange(unsigned varStart, unsigned varLimit) {
405  assert(varLimit <= getNumVars());
406 
407  if (varStart >= varLimit)
408  return;
409 
410  // Helper function to remove vars of the specified kind in the given range
411  // [start, limit), The range is absolute (i.e. it is not relative to the kind
412  // of variable). Also updates `limit` to reflect the deleted variables.
413  auto removeVarKindInRange = [this](VarKind kind, unsigned &start,
414  unsigned &limit) {
415  if (start >= limit)
416  return;
417 
418  unsigned offset = getVarKindOffset(kind);
419  unsigned num = getNumVarKind(kind);
420 
421  // Get `start`, `limit` relative to the specified kind.
422  unsigned relativeStart =
423  start <= offset ? 0 : std::min(num, start - offset);
424  unsigned relativeLimit =
425  limit <= offset ? 0 : std::min(num, limit - offset);
426 
427  // Remove vars of the specified kind in the relative range.
428  removeVarRange(kind, relativeStart, relativeLimit);
429 
430  // Update `limit` to reflect deleted variables.
431  // `start` does not need to be updated because any variables that are
432  // deleted are after position `start`.
433  limit -= relativeLimit - relativeStart;
434  };
435 
436  removeVarKindInRange(VarKind::Domain, varStart, varLimit);
437  removeVarKindInRange(VarKind::Range, varStart, varLimit);
438  removeVarKindInRange(VarKind::Symbol, varStart, varLimit);
439  removeVarKindInRange(VarKind::Local, varStart, varLimit);
440 }
441 
443  equalities.removeRow(pos);
444 }
445 
447  inequalities.removeRow(pos);
448 }
449 
450 void IntegerRelation::removeEqualityRange(unsigned start, unsigned end) {
451  if (start >= end)
452  return;
453  equalities.removeRows(start, end - start);
454 }
455 
456 void IntegerRelation::removeInequalityRange(unsigned start, unsigned end) {
457  if (start >= end)
458  return;
459  inequalities.removeRows(start, end - start);
460 }
461 
462 void IntegerRelation::swapVar(unsigned posA, unsigned posB) {
463  assert(posA < getNumVars() && "invalid position A");
464  assert(posB < getNumVars() && "invalid position B");
465 
466  if (posA == posB)
467  return;
468 
469  VarKind kindA = space.getVarKindAt(posA);
470  VarKind kindB = space.getVarKindAt(posB);
471  unsigned relativePosA = posA - getVarKindOffset(kindA);
472  unsigned relativePosB = posB - getVarKindOffset(kindB);
473  space.swapVar(kindA, kindB, relativePosA, relativePosB);
474 
475  inequalities.swapColumns(posA, posB);
476  equalities.swapColumns(posA, posB);
477 }
478 
482 }
483 
484 /// Gather all lower and upper bounds of the variable at `pos`, and
485 /// optionally any equalities on it. In addition, the bounds are to be
486 /// independent of variables in position range [`offset`, `offset` + `num`).
488  unsigned pos, SmallVectorImpl<unsigned> *lbIndices,
490  unsigned offset, unsigned num) const {
491  assert(pos < getNumVars() && "invalid position");
492  assert(offset + num < getNumCols() && "invalid range");
493 
494  // Checks for a constraint that has a non-zero coeff for the variables in
495  // the position range [offset, offset + num) while ignoring `pos`.
496  auto containsConstraintDependentOnRange = [&](unsigned r, bool isEq) {
497  unsigned c, f;
498  auto cst = isEq ? getEquality(r) : getInequality(r);
499  for (c = offset, f = offset + num; c < f; ++c) {
500  if (c == pos)
501  continue;
502  if (cst[c] != 0)
503  break;
504  }
505  return c < f;
506  };
507 
508  // Gather all lower bounds and upper bounds of the variable. Since the
509  // canonical form c_1*x_1 + c_2*x_2 + ... + c_0 >= 0, a constraint is a lower
510  // bound for x_i if c_i >= 1, and an upper bound if c_i <= -1.
511  for (unsigned r = 0, e = getNumInequalities(); r < e; r++) {
512  // The bounds are to be independent of [offset, offset + num) columns.
513  if (containsConstraintDependentOnRange(r, /*isEq=*/false))
514  continue;
515  if (atIneq(r, pos) >= 1) {
516  // Lower bound.
517  lbIndices->emplace_back(r);
518  } else if (atIneq(r, pos) <= -1) {
519  // Upper bound.
520  ubIndices->emplace_back(r);
521  }
522  }
523 
524  // An equality is both a lower and upper bound. Record any equalities
525  // involving the pos^th variable.
526  if (!eqIndices)
527  return;
528 
529  for (unsigned r = 0, e = getNumEqualities(); r < e; r++) {
530  if (atEq(r, pos) == 0)
531  continue;
532  if (containsConstraintDependentOnRange(r, /*isEq=*/true))
533  continue;
534  eqIndices->emplace_back(r);
535  }
536 }
537 
540  return false;
542  return false;
543  return true;
544 }
545 
547  ArrayRef<DynamicAPInt> values) {
548  if (values.empty())
549  return;
550  assert(pos + values.size() <= getNumVars() &&
551  "invalid position or too many values");
552  // Setting x_j = p in sum_i a_i x_i + c is equivalent to adding p*a_j to the
553  // constant term and removing the var x_j. We do this for all the vars
554  // pos, pos + 1, ... pos + values.size() - 1.
555  unsigned constantColPos = getNumCols() - 1;
556  for (unsigned i = 0, numVals = values.size(); i < numVals; ++i)
557  inequalities.addToColumn(i + pos, constantColPos, values[i]);
558  for (unsigned i = 0, numVals = values.size(); i < numVals; ++i)
559  equalities.addToColumn(i + pos, constantColPos, values[i]);
560  removeVarRange(pos, pos + values.size());
561 }
562 
564  *this = other;
565 }
566 
567 std::optional<unsigned>
568 IntegerRelation::findConstraintWithNonZeroAt(unsigned colIdx, bool isEq) const {
569  assert(colIdx < getNumCols() && "position out of bounds");
570  auto at = [&](unsigned rowIdx) -> DynamicAPInt {
571  return isEq ? atEq(rowIdx, colIdx) : atIneq(rowIdx, colIdx);
572  };
573  unsigned e = isEq ? getNumEqualities() : getNumInequalities();
574  for (unsigned rowIdx = 0; rowIdx < e; ++rowIdx) {
575  if (at(rowIdx) != 0)
576  return rowIdx;
577  }
578  return std::nullopt;
579 }
580 
582  for (unsigned i = 0, e = getNumEqualities(); i < e; ++i)
584  for (unsigned i = 0, e = getNumInequalities(); i < e; ++i)
586 }
587 
589  assert(hasConsistentState());
590  auto check = [&](bool isEq) -> bool {
591  unsigned numCols = getNumCols();
592  unsigned numRows = isEq ? getNumEqualities() : getNumInequalities();
593  for (unsigned i = 0, e = numRows; i < e; ++i) {
594  unsigned j;
595  for (j = 0; j < numCols - 1; ++j) {
596  DynamicAPInt v = isEq ? atEq(i, j) : atIneq(i, j);
597  // Skip rows with non-zero variable coefficients.
598  if (v != 0)
599  break;
600  }
601  if (j < numCols - 1) {
602  continue;
603  }
604  // Check validity of constant term at 'numCols - 1' w.r.t 'isEq'.
605  // Example invalid constraints include: '1 == 0' or '-1 >= 0'
606  DynamicAPInt v = isEq ? atEq(i, numCols - 1) : atIneq(i, numCols - 1);
607  if ((isEq && v != 0) || (!isEq && v < 0)) {
608  return true;
609  }
610  }
611  return false;
612  };
613  if (check(/*isEq=*/true))
614  return true;
615  return check(/*isEq=*/false);
616 }
617 
618 /// Eliminate variable from constraint at `rowIdx` based on coefficient at
619 /// pivotRow, pivotCol. Columns in range [elimColStart, pivotCol) will not be
620 /// updated as they have already been eliminated.
621 static void eliminateFromConstraint(IntegerRelation *constraints,
622  unsigned rowIdx, unsigned pivotRow,
623  unsigned pivotCol, unsigned elimColStart,
624  bool isEq) {
625  // Skip if equality 'rowIdx' if same as 'pivotRow'.
626  if (isEq && rowIdx == pivotRow)
627  return;
628  auto at = [&](unsigned i, unsigned j) -> DynamicAPInt {
629  return isEq ? constraints->atEq(i, j) : constraints->atIneq(i, j);
630  };
631  DynamicAPInt leadCoeff = at(rowIdx, pivotCol);
632  // Skip if leading coefficient at 'rowIdx' is already zero.
633  if (leadCoeff == 0)
634  return;
635  DynamicAPInt pivotCoeff = constraints->atEq(pivotRow, pivotCol);
636  int sign = (leadCoeff * pivotCoeff > 0) ? -1 : 1;
637  DynamicAPInt lcm = llvm::lcm(pivotCoeff, leadCoeff);
638  DynamicAPInt pivotMultiplier = sign * (lcm / abs(pivotCoeff));
639  DynamicAPInt rowMultiplier = lcm / abs(leadCoeff);
640 
641  unsigned numCols = constraints->getNumCols();
642  for (unsigned j = 0; j < numCols; ++j) {
643  // Skip updating column 'j' if it was just eliminated.
644  if (j >= elimColStart && j < pivotCol)
645  continue;
646  DynamicAPInt v = pivotMultiplier * constraints->atEq(pivotRow, j) +
647  rowMultiplier * at(rowIdx, j);
648  isEq ? constraints->atEq(rowIdx, j) = v
649  : constraints->atIneq(rowIdx, j) = v;
650  }
651 }
652 
653 /// Returns the position of the variable that has the minimum <number of lower
654 /// bounds> times <number of upper bounds> from the specified range of
655 /// variables [start, end). It is often best to eliminate in the increasing
656 /// order of these counts when doing Fourier-Motzkin elimination since FM adds
657 /// that many new constraints.
658 static unsigned getBestVarToEliminate(const IntegerRelation &cst,
659  unsigned start, unsigned end) {
660  assert(start < cst.getNumVars() && end < cst.getNumVars() + 1);
661 
662  auto getProductOfNumLowerUpperBounds = [&](unsigned pos) {
663  unsigned numLb = 0;
664  unsigned numUb = 0;
665  for (unsigned r = 0, e = cst.getNumInequalities(); r < e; r++) {
666  if (cst.atIneq(r, pos) > 0) {
667  ++numLb;
668  } else if (cst.atIneq(r, pos) < 0) {
669  ++numUb;
670  }
671  }
672  return numLb * numUb;
673  };
674 
675  unsigned minLoc = start;
676  unsigned min = getProductOfNumLowerUpperBounds(start);
677  for (unsigned c = start + 1; c < end; c++) {
678  unsigned numLbUbProduct = getProductOfNumLowerUpperBounds(c);
679  if (numLbUbProduct < min) {
680  min = numLbUbProduct;
681  minLoc = c;
682  }
683  }
684  return minLoc;
685 }
686 
687 // Checks for emptiness of the set by eliminating variables successively and
688 // using the GCD test (on all equality constraints) and checking for trivially
689 // invalid constraints. Returns 'true' if the constraint system is found to be
690 // empty; false otherwise.
693  return true;
694 
695  IntegerRelation tmpCst(*this);
696 
697  // First, eliminate as many local variables as possible using equalities.
698  tmpCst.removeRedundantLocalVars();
699  if (tmpCst.isEmptyByGCDTest() || tmpCst.hasInvalidConstraint())
700  return true;
701 
702  // Eliminate as many variables as possible using Gaussian elimination.
703  unsigned currentPos = 0;
704  while (currentPos < tmpCst.getNumVars()) {
705  tmpCst.gaussianEliminateVars(currentPos, tmpCst.getNumVars());
706  ++currentPos;
707  // We check emptiness through trivial checks after eliminating each ID to
708  // detect emptiness early. Since the checks isEmptyByGCDTest() and
709  // hasInvalidConstraint() are linear time and single sweep on the constraint
710  // buffer, this appears reasonable - but can optimize in the future.
711  if (tmpCst.hasInvalidConstraint() || tmpCst.isEmptyByGCDTest())
712  return true;
713  }
714 
715  // Eliminate the remaining using FM.
716  for (unsigned i = 0, e = tmpCst.getNumVars(); i < e; i++) {
718  getBestVarToEliminate(tmpCst, 0, tmpCst.getNumVars()));
719  // Check for a constraint explosion. This rarely happens in practice, but
720  // this check exists as a safeguard against improperly constructed
721  // constraint systems or artificially created arbitrarily complex systems
722  // that aren't the intended use case for IntegerRelation. This is
723  // needed since FM has a worst case exponential complexity in theory.
724  if (tmpCst.getNumConstraints() >= kExplosionFactor * getNumVars()) {
725  LLVM_DEBUG(llvm::dbgs() << "FM constraint explosion detected\n");
726  return false;
727  }
728 
729  // FM wouldn't have modified the equalities in any way. So no need to again
730  // run GCD test. Check for trivial invalid constraints.
731  if (tmpCst.hasInvalidConstraint())
732  return true;
733  }
734  return false;
735 }
736 
739 }
740 
741 // Runs the GCD test on all equality constraints. Returns 'true' if this test
742 // fails on any equality. Returns 'false' otherwise.
743 // This test can be used to disprove the existence of a solution. If it returns
744 // true, no integer solution to the equality constraints can exist.
745 //
746 // GCD test definition:
747 //
748 // The equality constraint:
749 //
750 // c_1*x_1 + c_2*x_2 + ... + c_n*x_n = c_0
751 //
752 // has an integer solution iff:
753 //
754 // GCD of c_1, c_2, ..., c_n divides c_0.
756  assert(hasConsistentState());
757  unsigned numCols = getNumCols();
758  for (unsigned i = 0, e = getNumEqualities(); i < e; ++i) {
759  DynamicAPInt gcd = abs(atEq(i, 0));
760  for (unsigned j = 1; j < numCols - 1; ++j) {
761  gcd = llvm::gcd(gcd, abs(atEq(i, j)));
762  }
763  DynamicAPInt v = abs(atEq(i, numCols - 1));
764  if (gcd > 0 && (v % gcd != 0)) {
765  return true;
766  }
767  }
768  return false;
769 }
770 
771 // Returns a matrix where each row is a vector along which the polytope is
772 // bounded. The span of the returned vectors is guaranteed to contain all
773 // such vectors. The returned vectors are NOT guaranteed to be linearly
774 // independent. This function should not be called on empty sets.
775 //
776 // It is sufficient to check the perpendiculars of the constraints, as the set
777 // of perpendiculars which are bounded must span all bounded directions.
779  // Note that it is necessary to add the equalities too (which the constructor
780  // does) even though we don't need to check if they are bounded; whether an
781  // inequality is bounded or not depends on what other constraints, including
782  // equalities, are present.
783  Simplex simplex(*this);
784 
785  assert(!simplex.isEmpty() && "It is not meaningful to ask whether a "
786  "direction is bounded in an empty set.");
787 
788  SmallVector<unsigned, 8> boundedIneqs;
789  // The constructor adds the inequalities to the simplex first, so this
790  // processes all the inequalities.
791  for (unsigned i = 0, e = getNumInequalities(); i < e; ++i) {
792  if (simplex.isBoundedAlongConstraint(i))
793  boundedIneqs.emplace_back(i);
794  }
795 
796  // The direction vector is given by the coefficients and does not include the
797  // constant term, so the matrix has one fewer column.
798  unsigned dirsNumCols = getNumCols() - 1;
799  IntMatrix dirs(boundedIneqs.size() + getNumEqualities(), dirsNumCols);
800 
801  // Copy the bounded inequalities.
802  unsigned row = 0;
803  for (unsigned i : boundedIneqs) {
804  for (unsigned col = 0; col < dirsNumCols; ++col)
805  dirs(row, col) = atIneq(i, col);
806  ++row;
807  }
808 
809  // Copy the equalities. All the equalities' perpendiculars are bounded.
810  for (unsigned i = 0, e = getNumEqualities(); i < e; ++i) {
811  for (unsigned col = 0; col < dirsNumCols; ++col)
812  dirs(row, col) = atEq(i, col);
813  ++row;
814  }
815 
816  return dirs;
817 }
818 
820 
821 /// Let this set be S. If S is bounded then we directly call into the GBR
822 /// sampling algorithm. Otherwise, there are some unbounded directions, i.e.,
823 /// vectors v such that S extends to infinity along v or -v. In this case we
824 /// use an algorithm described in the integer set library (isl) manual and used
825 /// by the isl_set_sample function in that library. The algorithm is:
826 ///
827 /// 1) Apply a unimodular transform T to S to obtain S*T, such that all
828 /// dimensions in which S*T is bounded lie in the linear span of a prefix of the
829 /// dimensions.
830 ///
831 /// 2) Construct a set B by removing all constraints that involve
832 /// the unbounded dimensions and then deleting the unbounded dimensions. Note
833 /// that B is a Bounded set.
834 ///
835 /// 3) Try to obtain a sample from B using the GBR sampling
836 /// algorithm. If no sample is found, return that S is empty.
837 ///
838 /// 4) Otherwise, substitute the obtained sample into S*T to obtain a set
839 /// C. C is a full-dimensional Cone and always contains a sample.
840 ///
841 /// 5) Obtain an integer sample from C.
842 ///
843 /// 6) Return T*v, where v is the concatenation of the samples from B and C.
844 ///
845 /// The following is a sketch of a proof that
846 /// a) If the algorithm returns empty, then S is empty.
847 /// b) If the algorithm returns a sample, it is a valid sample in S.
848 ///
849 /// The algorithm returns empty only if B is empty, in which case S*T is
850 /// certainly empty since B was obtained by removing constraints and then
851 /// deleting unconstrained dimensions from S*T. Since T is unimodular, a vector
852 /// v is in S*T iff T*v is in S. So in this case, since
853 /// S*T is empty, S is empty too.
854 ///
855 /// Otherwise, the algorithm substitutes the sample from B into S*T. All the
856 /// constraints of S*T that did not involve unbounded dimensions are satisfied
857 /// by this substitution. All dimensions in the linear span of the dimensions
858 /// outside the prefix are unbounded in S*T (step 1). Substituting values for
859 /// the bounded dimensions cannot make these dimensions bounded, and these are
860 /// the only remaining dimensions in C, so C is unbounded along every vector (in
861 /// the positive or negative direction, or both). C is hence a full-dimensional
862 /// cone and therefore always contains an integer point.
863 ///
864 /// Concatenating the samples from B and C gives a sample v in S*T, so the
865 /// returned sample T*v is a sample in S.
866 std::optional<SmallVector<DynamicAPInt, 8>>
868  // First, try the GCD test heuristic.
869  if (isEmptyByGCDTest())
870  return {};
871 
872  Simplex simplex(*this);
873  if (simplex.isEmpty())
874  return {};
875 
876  // For a bounded set, we directly call into the GBR sampling algorithm.
877  if (!simplex.isUnbounded())
878  return simplex.findIntegerSample();
879 
880  // The set is unbounded. We cannot directly use the GBR algorithm.
881  //
882  // m is a matrix containing, in each row, a vector in which S is
883  // bounded, such that the linear span of all these dimensions contains all
884  // bounded dimensions in S.
886  // In column echelon form, each row of m occupies only the first rank(m)
887  // columns and has zeros on the other columns. The transform T that brings S
888  // to column echelon form is unimodular as well, so this is a suitable
889  // transform to use in step 1 of the algorithm.
890  std::pair<unsigned, LinearTransform> result =
892  const LinearTransform &transform = result.second;
893  // 1) Apply T to S to obtain S*T.
894  IntegerRelation transformedSet = transform.applyTo(*this);
895 
896  // 2) Remove the unbounded dimensions and constraints involving them to
897  // obtain a bounded set.
898  IntegerRelation boundedSet(transformedSet);
899  unsigned numBoundedDims = result.first;
900  unsigned numUnboundedDims = getNumVars() - numBoundedDims;
901  removeConstraintsInvolvingVarRange(boundedSet, numBoundedDims,
902  numUnboundedDims);
903  boundedSet.removeVarRange(numBoundedDims, boundedSet.getNumVars());
904 
905  // 3) Try to obtain a sample from the bounded set.
906  std::optional<SmallVector<DynamicAPInt, 8>> boundedSample =
907  Simplex(boundedSet).findIntegerSample();
908  if (!boundedSample)
909  return {};
910  assert(boundedSet.containsPoint(*boundedSample) &&
911  "Simplex returned an invalid sample!");
912 
913  // 4) Substitute the values of the bounded dimensions into S*T to obtain a
914  // full-dimensional cone, which necessarily contains an integer sample.
915  transformedSet.setAndEliminate(0, *boundedSample);
916  IntegerRelation &cone = transformedSet;
917 
918  // 5) Obtain an integer sample from the cone.
919  //
920  // We shrink the cone such that for any rational point in the shrunken cone,
921  // rounding up each of the point's coordinates produces a point that still
922  // lies in the original cone.
923  //
924  // Rounding up a point x adds a number e_i in [0, 1) to each coordinate x_i.
925  // For each inequality sum_i a_i x_i + c >= 0 in the original cone, the
926  // shrunken cone will have the inequality tightened by some amount s, such
927  // that if x satisfies the shrunken cone's tightened inequality, then x + e
928  // satisfies the original inequality, i.e.,
929  //
930  // sum_i a_i x_i + c + s >= 0 implies sum_i a_i (x_i + e_i) + c >= 0
931  //
932  // for any e_i values in [0, 1). In fact, we will handle the slightly more
933  // general case where e_i can be in [0, 1]. For example, consider the
934  // inequality 2x_1 - 3x_2 - 7x_3 - 6 >= 0, and let x = (3, 0, 0). How low
935  // could the LHS go if we added a number in [0, 1] to each coordinate? The LHS
936  // is minimized when we add 1 to the x_i with negative coefficient a_i and
937  // keep the other x_i the same. In the example, we would get x = (3, 1, 1),
938  // changing the value of the LHS by -3 + -7 = -10.
939  //
940  // In general, the value of the LHS can change by at most the sum of the
941  // negative a_i, so we accomodate this by shifting the inequality by this
942  // amount for the shrunken cone.
943  for (unsigned i = 0, e = cone.getNumInequalities(); i < e; ++i) {
944  for (unsigned j = 0; j < cone.getNumVars(); ++j) {
945  DynamicAPInt coeff = cone.atIneq(i, j);
946  if (coeff < 0)
947  cone.atIneq(i, cone.getNumVars()) += coeff;
948  }
949  }
950 
951  // Obtain an integer sample in the cone by rounding up a rational point from
952  // the shrunken cone. Shrinking the cone amounts to shifting its apex
953  // "inwards" without changing its "shape"; the shrunken cone is still a
954  // full-dimensional cone and is hence non-empty.
955  Simplex shrunkenConeSimplex(cone);
956  assert(!shrunkenConeSimplex.isEmpty() && "Shrunken cone cannot be empty!");
957 
958  // The sample will always exist since the shrunken cone is non-empty.
959  SmallVector<Fraction, 8> shrunkenConeSample =
960  *shrunkenConeSimplex.getRationalSample();
961 
962  SmallVector<DynamicAPInt, 8> coneSample(
963  llvm::map_range(shrunkenConeSample, ceil));
964 
965  // 6) Return transform * concat(boundedSample, coneSample).
966  SmallVector<DynamicAPInt, 8> &sample = *boundedSample;
967  sample.append(coneSample.begin(), coneSample.end());
968  return transform.postMultiplyWithColumn(sample);
969 }
970 
971 /// Helper to evaluate an affine expression at a point.
972 /// The expression is a list of coefficients for the dimensions followed by the
973 /// constant term.
974 static DynamicAPInt valueAt(ArrayRef<DynamicAPInt> expr,
975  ArrayRef<DynamicAPInt> point) {
976  assert(expr.size() == 1 + point.size() &&
977  "Dimensionalities of point and expression don't match!");
978  DynamicAPInt value = expr.back();
979  for (unsigned i = 0; i < point.size(); ++i)
980  value += expr[i] * point[i];
981  return value;
982 }
983 
984 /// A point satisfies an equality iff the value of the equality at the
985 /// expression is zero, and it satisfies an inequality iff the value of the
986 /// inequality at that point is non-negative.
988  for (unsigned i = 0, e = getNumEqualities(); i < e; ++i) {
989  if (valueAt(getEquality(i), point) != 0)
990  return false;
991  }
992  for (unsigned i = 0, e = getNumInequalities(); i < e; ++i) {
993  if (valueAt(getInequality(i), point) < 0)
994  return false;
995  }
996  return true;
997 }
998 
999 /// Just substitute the values given and check if an integer sample exists for
1000 /// the local vars.
1001 ///
1002 /// TODO: this could be made more efficient by handling divisions separately.
1003 /// Instead of finding an integer sample over all the locals, we can first
1004 /// compute the values of the locals that have division representations and
1005 /// only use the integer emptiness check for the locals that don't have this.
1006 /// Handling this correctly requires ordering the divs, though.
1007 std::optional<SmallVector<DynamicAPInt, 8>>
1009  assert(point.size() == getNumVars() - getNumLocalVars() &&
1010  "Point should contain all vars except locals!");
1012  "This function depends on locals being stored last!");
1013  IntegerRelation copy = *this;
1014  copy.setAndEliminate(0, point);
1015  return copy.findIntegerSample();
1016 }
1017 
1019 IntegerRelation::getLocalReprs(std::vector<MaybeLocalRepr> *repr) const {
1020  SmallVector<bool, 8> foundRepr(getNumVars(), false);
1021  for (unsigned i = 0, e = getNumDimAndSymbolVars(); i < e; ++i)
1022  foundRepr[i] = true;
1023 
1024  unsigned localOffset = getVarKindOffset(VarKind::Local);
1026  bool changed;
1027  do {
1028  // Each time changed is true, at end of this iteration, one or more local
1029  // vars have been detected as floor divs.
1030  changed = false;
1031  for (unsigned i = 0, e = getNumLocalVars(); i < e; ++i) {
1032  if (!foundRepr[i + localOffset]) {
1033  MaybeLocalRepr res =
1034  computeSingleVarRepr(*this, foundRepr, localOffset + i,
1035  divs.getDividend(i), divs.getDenom(i));
1036  if (!res) {
1037  // No representation was found, so clear the representation and
1038  // continue.
1039  divs.clearRepr(i);
1040  continue;
1041  }
1042  foundRepr[localOffset + i] = true;
1043  if (repr)
1044  (*repr)[i] = res;
1045  changed = true;
1046  }
1047  }
1048  } while (changed);
1049 
1050  return divs;
1051 }
1052 
1053 /// Tightens inequalities given that we are dealing with integer spaces. This is
1054 /// analogous to the GCD test but applied to inequalities. The constant term can
1055 /// be reduced to the preceding multiple of the GCD of the coefficients, i.e.,
1056 /// 64*i - 100 >= 0 => 64*i - 128 >= 0 (since 'i' is an integer). This is a
1057 /// fast method - linear in the number of coefficients.
1058 // Example on how this affects practical cases: consider the scenario:
1059 // 64*i >= 100, j = 64*i; without a tightening, elimination of i would yield
1060 // j >= 100 instead of the tighter (exact) j >= 128.
1062  unsigned numCols = getNumCols();
1063  for (unsigned i = 0, e = getNumInequalities(); i < e; ++i) {
1064  // Normalize the constraint and tighten the constant term by the GCD.
1065  DynamicAPInt gcd = inequalities.normalizeRow(i, getNumCols() - 1);
1066  if (gcd > 1)
1067  atIneq(i, numCols - 1) = floorDiv(atIneq(i, numCols - 1), gcd);
1068  }
1069 }
1070 
1071 // Eliminates all variable variables in column range [posStart, posLimit).
1072 // Returns the number of variables eliminated.
1073 unsigned IntegerRelation::gaussianEliminateVars(unsigned posStart,
1074  unsigned posLimit) {
1075  // Return if variable positions to eliminate are out of range.
1076  assert(posLimit <= getNumVars());
1077  assert(hasConsistentState());
1078 
1079  if (posStart >= posLimit)
1080  return 0;
1081 
1083 
1084  unsigned pivotCol = 0;
1085  for (pivotCol = posStart; pivotCol < posLimit; ++pivotCol) {
1086  // Find a row which has a non-zero coefficient in column 'j'.
1087  std::optional<unsigned> pivotRow =
1088  findConstraintWithNonZeroAt(pivotCol, /*isEq=*/true);
1089  // No pivot row in equalities with non-zero at 'pivotCol'.
1090  if (!pivotRow) {
1091  // If inequalities are also non-zero in 'pivotCol', it can be eliminated.
1092  if ((pivotRow = findConstraintWithNonZeroAt(pivotCol, /*isEq=*/false)))
1093  break;
1094  continue;
1095  }
1096 
1097  // Eliminate variable at 'pivotCol' from each equality row.
1098  for (unsigned i = 0, e = getNumEqualities(); i < e; ++i) {
1099  eliminateFromConstraint(this, i, *pivotRow, pivotCol, posStart,
1100  /*isEq=*/true);
1102  }
1103 
1104  // Eliminate variable at 'pivotCol' from each inequality row.
1105  for (unsigned i = 0, e = getNumInequalities(); i < e; ++i) {
1106  eliminateFromConstraint(this, i, *pivotRow, pivotCol, posStart,
1107  /*isEq=*/false);
1109  }
1110  removeEquality(*pivotRow);
1112  }
1113  // Update position limit based on number eliminated.
1114  posLimit = pivotCol;
1115  // Remove eliminated columns from all constraints.
1116  removeVarRange(posStart, posLimit);
1117  return posLimit - posStart;
1118 }
1119 
1122  unsigned firstVar = 0, vars = getNumVars();
1123  unsigned nowDone, eqs;
1124  std::optional<unsigned> pivotRow;
1125  for (nowDone = 0, eqs = getNumEqualities(); nowDone < eqs; ++nowDone) {
1126  // Finds the first non-empty column.
1127  for (; firstVar < vars; ++firstVar) {
1128  if ((pivotRow = findConstraintWithNonZeroAt(firstVar, /*isEq=*/true)))
1129  break;
1130  }
1131  // The matrix has been normalized to row echelon form.
1132  if (firstVar >= vars)
1133  break;
1134 
1135  // The first pivot row found is below where it should currently be placed.
1136  if (*pivotRow > nowDone) {
1137  equalities.swapRows(*pivotRow, nowDone);
1138  *pivotRow = nowDone;
1139  }
1140 
1141  // Normalize all lower equations and all inequalities.
1142  for (unsigned i = nowDone + 1; i < eqs; ++i) {
1143  eliminateFromConstraint(this, i, *pivotRow, firstVar, 0, true);
1145  }
1146  for (unsigned i = 0, ineqs = getNumInequalities(); i < ineqs; ++i) {
1147  eliminateFromConstraint(this, i, *pivotRow, firstVar, 0, false);
1149  }
1151  }
1152 
1153  // No redundant rows.
1154  if (nowDone == eqs)
1155  return false;
1156 
1157  // Check to see if the redundant rows constant is zero, a non-zero value means
1158  // the set is empty.
1159  for (unsigned i = nowDone; i < eqs; ++i) {
1160  if (atEq(i, vars) == 0)
1161  continue;
1162 
1163  *this = getEmpty(getSpace());
1164  return true;
1165  }
1166  // Eliminate rows that are confined to be all zeros.
1167  removeEqualityRange(nowDone, eqs);
1168  return true;
1169 }
1170 
1171 // A more complex check to eliminate redundant inequalities. Uses FourierMotzkin
1172 // to check if a constraint is redundant.
1174  SmallVector<bool, 32> redun(getNumInequalities(), false);
1175  // To check if an inequality is redundant, we replace the inequality by its
1176  // complement (for eg., i - 1 >= 0 by i <= 0), and check if the resulting
1177  // system is empty. If it is, the inequality is redundant.
1178  IntegerRelation tmpCst(*this);
1179  for (unsigned r = 0, e = getNumInequalities(); r < e; r++) {
1180  // Change the inequality to its complement.
1181  tmpCst.inequalities.negateRow(r);
1182  --tmpCst.atIneq(r, tmpCst.getNumCols() - 1);
1183  if (tmpCst.isEmpty()) {
1184  redun[r] = true;
1185  // Zero fill the redundant inequality.
1186  inequalities.fillRow(r, /*value=*/0);
1187  tmpCst.inequalities.fillRow(r, /*value=*/0);
1188  } else {
1189  // Reverse the change (to avoid recreating tmpCst each time).
1190  ++tmpCst.atIneq(r, tmpCst.getNumCols() - 1);
1191  tmpCst.inequalities.negateRow(r);
1192  }
1193  }
1194 
1195  unsigned pos = 0;
1196  for (unsigned r = 0, e = getNumInequalities(); r < e; ++r) {
1197  if (!redun[r])
1198  inequalities.copyRow(r, pos++);
1199  }
1201 }
1202 
1203 // A more complex check to eliminate redundant inequalities and equalities. Uses
1204 // Simplex to check if a constraint is redundant.
1206  // First, we run gcdTightenInequalities. This allows us to catch some
1207  // constraints which are not redundant when considering rational solutions
1208  // but are redundant in terms of integer solutions.
1210  Simplex simplex(*this);
1211  simplex.detectRedundant();
1212 
1213  unsigned pos = 0;
1214  unsigned numIneqs = getNumInequalities();
1215  // Scan to get rid of all inequalities marked redundant, in-place. In Simplex,
1216  // the first constraints added are the inequalities.
1217  for (unsigned r = 0; r < numIneqs; r++) {
1218  if (!simplex.isMarkedRedundant(r))
1219  inequalities.copyRow(r, pos++);
1220  }
1222 
1223  // Scan to get rid of all equalities marked redundant, in-place. In Simplex,
1224  // after the inequalities, a pair of constraints for each equality is added.
1225  // An equality is redundant if both the inequalities in its pair are
1226  // redundant.
1227  pos = 0;
1228  for (unsigned r = 0, e = getNumEqualities(); r < e; r++) {
1229  if (!(simplex.isMarkedRedundant(numIneqs + 2 * r) &&
1230  simplex.isMarkedRedundant(numIneqs + 2 * r + 1)))
1231  equalities.copyRow(r, pos++);
1232  }
1234 }
1235 
1236 std::optional<DynamicAPInt> IntegerRelation::computeVolume() const {
1237  assert(getNumSymbolVars() == 0 && "Symbols are not yet supported!");
1238 
1239  Simplex simplex(*this);
1240  // If the polytope is rationally empty, there are certainly no integer
1241  // points.
1242  if (simplex.isEmpty())
1243  return DynamicAPInt(0);
1244 
1245  // Just find the maximum and minimum integer value of each non-local var
1246  // separately, thus finding the number of integer values each such var can
1247  // take. Multiplying these together gives a valid overapproximation of the
1248  // number of integer points in the relation. The result this gives is
1249  // equivalent to projecting (rationally) the relation onto its non-local vars
1250  // and returning the number of integer points in a minimal axis-parallel
1251  // hyperrectangular overapproximation of that.
1252  //
1253  // We also handle the special case where one dimension is unbounded and
1254  // another dimension can take no integer values. In this case, the volume is
1255  // zero.
1256  //
1257  // If there is no such empty dimension, if any dimension is unbounded we
1258  // just return the result as unbounded.
1259  DynamicAPInt count(1);
1261  bool hasUnboundedVar = false;
1262  for (unsigned i = 0, e = getNumDimAndSymbolVars(); i < e; ++i) {
1263  dim[i] = 1;
1264  auto [min, max] = simplex.computeIntegerBounds(dim);
1265  dim[i] = 0;
1266 
1267  assert((!min.isEmpty() && !max.isEmpty()) &&
1268  "Polytope should be rationally non-empty!");
1269 
1270  // One of the dimensions is unbounded. Note this fact. We will return
1271  // unbounded if none of the other dimensions makes the volume zero.
1272  if (min.isUnbounded() || max.isUnbounded()) {
1273  hasUnboundedVar = true;
1274  continue;
1275  }
1276 
1277  // In this case there are no valid integer points and the volume is
1278  // definitely zero.
1279  if (min.getBoundedOptimum() > max.getBoundedOptimum())
1280  return DynamicAPInt(0);
1281 
1282  count *= (*max - *min + 1);
1283  }
1284 
1285  if (count == 0)
1286  return DynamicAPInt(0);
1287  if (hasUnboundedVar)
1288  return {};
1289  return count;
1290 }
1291 
1292 void IntegerRelation::eliminateRedundantLocalVar(unsigned posA, unsigned posB) {
1293  assert(posA < getNumLocalVars() && "Invalid local var position");
1294  assert(posB < getNumLocalVars() && "Invalid local var position");
1295 
1296  unsigned localOffset = getVarKindOffset(VarKind::Local);
1297  posA += localOffset;
1298  posB += localOffset;
1299  inequalities.addToColumn(posB, posA, 1);
1300  equalities.addToColumn(posB, posA, 1);
1301  removeVar(posB);
1302 }
1303 
1304 /// mergeAndAlignSymbols's implementation can be broken down into two steps:
1305 /// 1. Merge and align identifiers into `other` from `this. If an identifier
1306 /// from `this` exists in `other` then we align it. Otherwise, we assume it is a
1307 /// new identifier and insert it into `other` in the same position as `this`.
1308 /// 2. Add identifiers that are in `other` but not `this to `this`.
1310  assert(space.isUsingIds() && other.space.isUsingIds() &&
1311  "both relations need to have identifers to merge and align");
1312 
1313  unsigned i = 0;
1314  for (const Identifier identifier : space.getIds(VarKind::Symbol)) {
1315  // Search in `other` starting at position `i` since the left of `i` is
1316  // aligned.
1317  const Identifier *findBegin =
1318  other.space.getIds(VarKind::Symbol).begin() + i;
1319  const Identifier *findEnd = other.space.getIds(VarKind::Symbol).end();
1320  const Identifier *itr = std::find(findBegin, findEnd, identifier);
1321  if (itr != findEnd) {
1322  other.swapVar(other.getVarKindOffset(VarKind::Symbol) + i,
1323  other.getVarKindOffset(VarKind::Symbol) + i +
1324  std::distance(findBegin, itr));
1325  } else {
1326  other.insertVar(VarKind::Symbol, i);
1327  other.space.setId(VarKind::Symbol, i, identifier);
1328  }
1329  ++i;
1330  }
1331 
1332  for (unsigned e = other.getNumVarKind(VarKind::Symbol); i < e; ++i) {
1335  }
1336 }
1337 
1338 /// Adds additional local ids to the sets such that they both have the union
1339 /// of the local ids in each set, without changing the set of points that
1340 /// lie in `this` and `other`.
1341 ///
1342 /// To detect local ids that always take the same value, each local id is
1343 /// represented as a floordiv with constant denominator in terms of other ids.
1344 /// After extracting these divisions, local ids in `other` with the same
1345 /// division representation as some other local id in any set are considered
1346 /// duplicate and are merged.
1347 ///
1348 /// It is possible that division representation for some local id cannot be
1349 /// obtained, and thus these local ids are not considered for detecting
1350 /// duplicates.
1352  IntegerRelation &relA = *this;
1353  IntegerRelation &relB = other;
1354 
1355  unsigned oldALocals = relA.getNumLocalVars();
1356 
1357  // Merge function that merges the local variables in both sets by treating
1358  // them as the same variable.
1359  auto merge = [&relA, &relB, oldALocals](unsigned i, unsigned j) -> bool {
1360  // We only merge from local at pos j to local at pos i, where j > i.
1361  if (i >= j)
1362  return false;
1363 
1364  // If i < oldALocals, we are trying to merge duplicate divs. Since we do not
1365  // want to merge duplicates in A, we ignore this call.
1366  if (j < oldALocals)
1367  return false;
1368 
1369  // Merge local at pos j into local at position i.
1370  relA.eliminateRedundantLocalVar(i, j);
1371  relB.eliminateRedundantLocalVar(i, j);
1372  return true;
1373  };
1374 
1375  presburger::mergeLocalVars(*this, other, merge);
1376 
1377  // Since we do not remove duplicate divisions in relA, this is guranteed to be
1378  // non-negative.
1379  return relA.getNumLocalVars() - oldALocals;
1380 }
1381 
1383  return getLocalReprs().hasAllReprs();
1384 }
1385 
1387  DivisionRepr divs = getLocalReprs();
1388  auto merge = [this](unsigned i, unsigned j) -> bool {
1390  return true;
1391  };
1392  divs.removeDuplicateDivs(merge);
1393 }
1394 
1396  bool changed = true;
1397  // Repeat until we reach a fixed point.
1398  while (changed) {
1399  if (isObviouslyEmpty())
1400  return;
1401  changed = false;
1405  }
1406  // Current set is not empty.
1407 }
1408 
1409 /// Removes local variables using equalities. Each equality is checked if it
1410 /// can be reduced to the form: `e = affine-expr`, where `e` is a local
1411 /// variable and `affine-expr` is an affine expression not containing `e`.
1412 /// If an equality satisfies this form, the local variable is replaced in
1413 /// each constraint and then removed. The equality used to replace this local
1414 /// variable is also removed.
1416  // Normalize the equality constraints to reduce coefficients of local
1417  // variables to 1 wherever possible.
1418  for (unsigned i = 0, e = getNumEqualities(); i < e; ++i)
1420 
1421  while (true) {
1422  unsigned i, e, j, f;
1423  for (i = 0, e = getNumEqualities(); i < e; ++i) {
1424  // Find a local variable to eliminate using ith equality.
1425  for (j = getNumDimAndSymbolVars(), f = getNumVars(); j < f; ++j)
1426  if (abs(atEq(i, j)) == 1)
1427  break;
1428 
1429  // Local variable can be eliminated using ith equality.
1430  if (j < f)
1431  break;
1432  }
1433 
1434  // No equality can be used to eliminate a local variable.
1435  if (i == e)
1436  break;
1437 
1438  // Use the ith equality to simplify other equalities. If any changes
1439  // are made to an equality constraint, it is normalized by GCD.
1440  for (unsigned k = 0, t = getNumEqualities(); k < t; ++k) {
1441  if (atEq(k, j) != 0) {
1442  eliminateFromConstraint(this, k, i, j, j, /*isEq=*/true);
1444  }
1445  }
1446 
1447  // Use the ith equality to simplify inequalities.
1448  for (unsigned k = 0, t = getNumInequalities(); k < t; ++k)
1449  eliminateFromConstraint(this, k, i, j, j, /*isEq=*/false);
1450 
1451  // Remove the ith equality and the found local variable.
1452  removeVar(j);
1453  removeEquality(i);
1454  }
1455 }
1456 
1457 void IntegerRelation::convertVarKind(VarKind srcKind, unsigned varStart,
1458  unsigned varLimit, VarKind dstKind,
1459  unsigned pos) {
1460  assert(varLimit <= getNumVarKind(srcKind) && "invalid id range");
1461 
1462  if (varStart >= varLimit)
1463  return;
1464 
1465  unsigned srcOffset = getVarKindOffset(srcKind);
1466  unsigned dstOffset = getVarKindOffset(dstKind);
1467  unsigned convertCount = varLimit - varStart;
1468  int forwardMoveOffset = dstOffset > srcOffset ? -convertCount : 0;
1469 
1470  equalities.moveColumns(srcOffset + varStart, convertCount,
1471  dstOffset + pos + forwardMoveOffset);
1472  inequalities.moveColumns(srcOffset + varStart, convertCount,
1473  dstOffset + pos + forwardMoveOffset);
1474 
1475  space.convertVarKind(srcKind, varStart, varLimit - varStart, dstKind, pos);
1476 }
1477 
1478 void IntegerRelation::addBound(BoundType type, unsigned pos,
1479  const DynamicAPInt &value) {
1480  assert(pos < getNumCols());
1481  if (type == BoundType::EQ) {
1482  unsigned row = equalities.appendExtraRow();
1483  equalities(row, pos) = 1;
1484  equalities(row, getNumCols() - 1) = -value;
1485  } else {
1486  unsigned row = inequalities.appendExtraRow();
1487  inequalities(row, pos) = type == BoundType::LB ? 1 : -1;
1488  inequalities(row, getNumCols() - 1) =
1489  type == BoundType::LB ? -value : value;
1490  }
1491 }
1492 
1494  const DynamicAPInt &value) {
1495  assert(type != BoundType::EQ && "EQ not implemented");
1496  assert(expr.size() == getNumCols());
1497  unsigned row = inequalities.appendExtraRow();
1498  for (unsigned i = 0, e = expr.size(); i < e; ++i)
1499  inequalities(row, i) = type == BoundType::LB ? expr[i] : -expr[i];
1501  type == BoundType::LB ? -value : value;
1502 }
1503 
1504 /// Adds a new local variable as the floordiv of an affine function of other
1505 /// variables, the coefficients of which are provided in 'dividend' and with
1506 /// respect to a positive constant 'divisor'. Two constraints are added to the
1507 /// system to capture equivalence with the floordiv.
1508 /// q = expr floordiv c <=> c*q <= expr <= c*q + c - 1.
1510  const DynamicAPInt &divisor) {
1511  assert(dividend.size() == getNumCols() && "incorrect dividend size");
1512  assert(divisor > 0 && "positive divisor expected");
1513 
1515 
1516  SmallVector<DynamicAPInt, 8> dividendCopy(dividend);
1517  dividendCopy.insert(dividendCopy.end() - 1, DynamicAPInt(0));
1518  addInequality(
1519  getDivLowerBound(dividendCopy, divisor, dividendCopy.size() - 2));
1520  addInequality(
1521  getDivUpperBound(dividendCopy, divisor, dividendCopy.size() - 2));
1522 }
1523 
1524 int IntegerRelation::findEqualityToConstant(unsigned pos, bool symbolic) const {
1525  assert(pos < getNumVars() && "invalid position");
1526  for (unsigned r = 0, e = getNumEqualities(); r < e; r++) {
1527  DynamicAPInt v = atEq(r, pos);
1528  if (v * v != 1)
1529  continue;
1530  unsigned c;
1531  unsigned f = symbolic ? getNumDimVars() : getNumVars();
1532  // This checks for zeros in all positions other than 'pos' in [0, f)
1533  for (c = 0; c < f; c++) {
1534  if (c == pos)
1535  continue;
1536  if (atEq(r, c) != 0) {
1537  // Dependent on another variable.
1538  break;
1539  }
1540  }
1541  if (c == f)
1542  // Equality is free of other variables.
1543  return r;
1544  }
1545  return -1;
1546 }
1547 
1548 LogicalResult IntegerRelation::constantFoldVar(unsigned pos) {
1549  assert(pos < getNumVars() && "invalid position");
1550  int rowIdx;
1551  if ((rowIdx = findEqualityToConstant(pos)) == -1)
1552  return failure();
1553 
1554  // atEq(rowIdx, pos) is either -1 or 1.
1555  assert(atEq(rowIdx, pos) * atEq(rowIdx, pos) == 1);
1556  DynamicAPInt constVal = -atEq(rowIdx, getNumCols() - 1) / atEq(rowIdx, pos);
1557  setAndEliminate(pos, constVal);
1558  return success();
1559 }
1560 
1561 void IntegerRelation::constantFoldVarRange(unsigned pos, unsigned num) {
1562  for (unsigned s = pos, t = pos, e = pos + num; s < e; s++) {
1563  if (constantFoldVar(t).failed())
1564  t++;
1565  }
1566 }
1567 
1568 /// Returns a non-negative constant bound on the extent (upper bound - lower
1569 /// bound) of the specified variable if it is found to be a constant; returns
1570 /// std::nullopt if it's not a constant. This methods treats symbolic variables
1571 /// specially, i.e., it looks for constant differences between affine
1572 /// expressions involving only the symbolic variables. See comments at function
1573 /// definition for example. 'lb', if provided, is set to the lower bound
1574 /// associated with the constant difference. Note that 'lb' is purely symbolic
1575 /// and thus will contain the coefficients of the symbolic variables and the
1576 /// constant coefficient.
1577 // Egs: 0 <= i <= 15, return 16.
1578 // s0 + 2 <= i <= s0 + 17, returns 16. (s0 has to be a symbol)
1579 // s0 + s1 + 16 <= d0 <= s0 + s1 + 31, returns 16.
1580 // s0 - 7 <= 8*j <= s0 returns 1 with lb = s0, lbDivisor = 8 (since lb =
1581 // ceil(s0 - 7 / 8) = floor(s0 / 8)).
1583  unsigned pos, SmallVectorImpl<DynamicAPInt> *lb,
1584  DynamicAPInt *boundFloorDivisor, SmallVectorImpl<DynamicAPInt> *ub,
1585  unsigned *minLbPos, unsigned *minUbPos) const {
1586  assert(pos < getNumDimVars() && "Invalid variable position");
1587 
1588  // Find an equality for 'pos'^th variable that equates it to some function
1589  // of the symbolic variables (+ constant).
1590  int eqPos = findEqualityToConstant(pos, /*symbolic=*/true);
1591  if (eqPos != -1) {
1592  auto eq = getEquality(eqPos);
1593  // If the equality involves a local var, we do not handle it.
1594  // FlatLinearConstraints can instead be used to detect the local variable as
1595  // an affine function (potentially div/mod) of other variables and use
1596  // affine expressions/maps to represent output.
1597  if (!std::all_of(eq.begin() + getNumDimAndSymbolVars(), eq.end() - 1,
1598  [](const DynamicAPInt &coeff) { return coeff == 0; }))
1599  return std::nullopt;
1600 
1601  // This variable can only take a single value.
1602  if (lb) {
1603  // Set lb to that symbolic value.
1604  lb->resize(getNumSymbolVars() + 1);
1605  if (ub)
1606  ub->resize(getNumSymbolVars() + 1);
1607  for (unsigned c = 0, f = getNumSymbolVars() + 1; c < f; c++) {
1608  DynamicAPInt v = atEq(eqPos, pos);
1609  // atEq(eqRow, pos) is either -1 or 1.
1610  assert(v * v == 1);
1611  (*lb)[c] = v < 0 ? atEq(eqPos, getNumDimVars() + c) / -v
1612  : -atEq(eqPos, getNumDimVars() + c) / v;
1613  // Since this is an equality, ub = lb.
1614  if (ub)
1615  (*ub)[c] = (*lb)[c];
1616  }
1617  assert(boundFloorDivisor &&
1618  "both lb and divisor or none should be provided");
1619  *boundFloorDivisor = 1;
1620  }
1621  if (minLbPos)
1622  *minLbPos = eqPos;
1623  if (minUbPos)
1624  *minUbPos = eqPos;
1625  return DynamicAPInt(1);
1626  }
1627 
1628  // Check if the variable appears at all in any of the inequalities.
1629  unsigned r, e;
1630  for (r = 0, e = getNumInequalities(); r < e; r++) {
1631  if (atIneq(r, pos) != 0)
1632  break;
1633  }
1634  if (r == e)
1635  // If it doesn't, there isn't a bound on it.
1636  return std::nullopt;
1637 
1638  // Positions of constraints that are lower/upper bounds on the variable.
1639  SmallVector<unsigned, 4> lbIndices, ubIndices;
1640 
1641  // Gather all symbolic lower bounds and upper bounds of the variable, i.e.,
1642  // the bounds can only involve symbolic (and local) variables. Since the
1643  // canonical form c_1*x_1 + c_2*x_2 + ... + c_0 >= 0, a constraint is a lower
1644  // bound for x_i if c_i >= 1, and an upper bound if c_i <= -1.
1645  getLowerAndUpperBoundIndices(pos, &lbIndices, &ubIndices,
1646  /*eqIndices=*/nullptr, /*offset=*/0,
1647  /*num=*/getNumDimVars());
1648 
1649  std::optional<DynamicAPInt> minDiff;
1650  unsigned minLbPosition = 0, minUbPosition = 0;
1651  for (auto ubPos : ubIndices) {
1652  for (auto lbPos : lbIndices) {
1653  // Look for a lower bound and an upper bound that only differ by a
1654  // constant, i.e., pairs of the form 0 <= c_pos - f(c_i's) <= diffConst.
1655  // For example, if ii is the pos^th variable, we are looking for
1656  // constraints like ii >= i, ii <= ii + 50, 50 being the difference. The
1657  // minimum among all such constant differences is kept since that's the
1658  // constant bounding the extent of the pos^th variable.
1659  unsigned j, e;
1660  for (j = 0, e = getNumCols() - 1; j < e; j++)
1661  if (atIneq(ubPos, j) != -atIneq(lbPos, j)) {
1662  break;
1663  }
1664  if (j < getNumCols() - 1)
1665  continue;
1666  DynamicAPInt diff = ceilDiv(atIneq(ubPos, getNumCols() - 1) +
1667  atIneq(lbPos, getNumCols() - 1) + 1,
1668  atIneq(lbPos, pos));
1669  // This bound is non-negative by definition.
1670  diff = std::max<DynamicAPInt>(diff, DynamicAPInt(0));
1671  if (minDiff == std::nullopt || diff < minDiff) {
1672  minDiff = diff;
1673  minLbPosition = lbPos;
1674  minUbPosition = ubPos;
1675  }
1676  }
1677  }
1678  if (lb && minDiff) {
1679  // Set lb to the symbolic lower bound.
1680  lb->resize(getNumSymbolVars() + 1);
1681  if (ub)
1682  ub->resize(getNumSymbolVars() + 1);
1683  // The lower bound is the ceildiv of the lb constraint over the coefficient
1684  // of the variable at 'pos'. We express the ceildiv equivalently as a floor
1685  // for uniformity. For eg., if the lower bound constraint was: 32*d0 - N +
1686  // 31 >= 0, the lower bound for d0 is ceil(N - 31, 32), i.e., floor(N, 32).
1687  *boundFloorDivisor = atIneq(minLbPosition, pos);
1688  assert(*boundFloorDivisor == -atIneq(minUbPosition, pos));
1689  for (unsigned c = 0, e = getNumSymbolVars() + 1; c < e; c++) {
1690  (*lb)[c] = -atIneq(minLbPosition, getNumDimVars() + c);
1691  }
1692  if (ub) {
1693  for (unsigned c = 0, e = getNumSymbolVars() + 1; c < e; c++)
1694  (*ub)[c] = atIneq(minUbPosition, getNumDimVars() + c);
1695  }
1696  // The lower bound leads to a ceildiv while the upper bound is a floordiv
1697  // whenever the coefficient at pos != 1. ceildiv (val / d) = floordiv (val +
1698  // d - 1 / d); hence, the addition of 'atIneq(minLbPosition, pos) - 1' to
1699  // the constant term for the lower bound.
1700  (*lb)[getNumSymbolVars()] += atIneq(minLbPosition, pos) - 1;
1701  }
1702  if (minLbPos)
1703  *minLbPos = minLbPosition;
1704  if (minUbPos)
1705  *minUbPos = minUbPosition;
1706  return minDiff;
1707 }
1708 
1709 template <bool isLower>
1710 std::optional<DynamicAPInt>
1712  assert(pos < getNumVars() && "invalid position");
1713  // Project to 'pos'.
1714  projectOut(0, pos);
1715  projectOut(1, getNumVars() - 1);
1716  // Check if there's an equality equating the '0'^th variable to a constant.
1717  int eqRowIdx = findEqualityToConstant(/*pos=*/0, /*symbolic=*/false);
1718  if (eqRowIdx != -1)
1719  // atEq(rowIdx, 0) is either -1 or 1.
1720  return -atEq(eqRowIdx, getNumCols() - 1) / atEq(eqRowIdx, 0);
1721 
1722  // Check if the variable appears at all in any of the inequalities.
1723  unsigned r, e;
1724  for (r = 0, e = getNumInequalities(); r < e; r++) {
1725  if (atIneq(r, 0) != 0)
1726  break;
1727  }
1728  if (r == e)
1729  // If it doesn't, there isn't a bound on it.
1730  return std::nullopt;
1731 
1732  std::optional<DynamicAPInt> minOrMaxConst;
1733 
1734  // Take the max across all const lower bounds (or min across all constant
1735  // upper bounds).
1736  for (unsigned r = 0, e = getNumInequalities(); r < e; r++) {
1737  if (isLower) {
1738  if (atIneq(r, 0) <= 0)
1739  // Not a lower bound.
1740  continue;
1741  } else if (atIneq(r, 0) >= 0) {
1742  // Not an upper bound.
1743  continue;
1744  }
1745  unsigned c, f;
1746  for (c = 0, f = getNumCols() - 1; c < f; c++)
1747  if (c != 0 && atIneq(r, c) != 0)
1748  break;
1749  if (c < getNumCols() - 1)
1750  // Not a constant bound.
1751  continue;
1752 
1753  DynamicAPInt boundConst =
1754  isLower ? ceilDiv(-atIneq(r, getNumCols() - 1), atIneq(r, 0))
1755  : floorDiv(atIneq(r, getNumCols() - 1), -atIneq(r, 0));
1756  if (isLower) {
1757  if (minOrMaxConst == std::nullopt || boundConst > minOrMaxConst)
1758  minOrMaxConst = boundConst;
1759  } else {
1760  if (minOrMaxConst == std::nullopt || boundConst < minOrMaxConst)
1761  minOrMaxConst = boundConst;
1762  }
1763  }
1764  return minOrMaxConst;
1765 }
1766 
1767 std::optional<DynamicAPInt>
1769  if (type == BoundType::LB)
1770  return IntegerRelation(*this)
1771  .computeConstantLowerOrUpperBound</*isLower=*/true>(pos);
1772  if (type == BoundType::UB)
1773  return IntegerRelation(*this)
1774  .computeConstantLowerOrUpperBound</*isLower=*/false>(pos);
1775 
1776  assert(type == BoundType::EQ && "expected EQ");
1777  std::optional<DynamicAPInt> lb =
1778  IntegerRelation(*this).computeConstantLowerOrUpperBound</*isLower=*/true>(
1779  pos);
1780  std::optional<DynamicAPInt> ub =
1781  IntegerRelation(*this)
1782  .computeConstantLowerOrUpperBound</*isLower=*/false>(pos);
1783  return (lb && ub && *lb == *ub) ? std::optional<DynamicAPInt>(*ub)
1784  : std::nullopt;
1785 }
1786 
1787 // A simple (naive and conservative) check for hyper-rectangularity.
1788 bool IntegerRelation::isHyperRectangular(unsigned pos, unsigned num) const {
1789  assert(pos < getNumCols() - 1);
1790  // Check for two non-zero coefficients in the range [pos, pos + sum).
1791  for (unsigned r = 0, e = getNumInequalities(); r < e; r++) {
1792  unsigned sum = 0;
1793  for (unsigned c = pos; c < pos + num; c++) {
1794  if (atIneq(r, c) != 0)
1795  sum++;
1796  }
1797  if (sum > 1)
1798  return false;
1799  }
1800  for (unsigned r = 0, e = getNumEqualities(); r < e; r++) {
1801  unsigned sum = 0;
1802  for (unsigned c = pos; c < pos + num; c++) {
1803  if (atEq(r, c) != 0)
1804  sum++;
1805  }
1806  if (sum > 1)
1807  return false;
1808  }
1809  return true;
1810 }
1811 
1812 /// Removes duplicate constraints, trivially true constraints, and constraints
1813 /// that can be detected as redundant as a result of differing only in their
1814 /// constant term part. A constraint of the form <non-negative constant> >= 0 is
1815 /// considered trivially true.
1816 // Uses a DenseSet to hash and detect duplicates followed by a linear scan to
1817 // remove duplicates in place.
1821 
1822  // A map used to detect redundancy stemming from constraints that only differ
1823  // in their constant term. The value stored is <row position, const term>
1824  // for a given row.
1825  SmallDenseMap<ArrayRef<DynamicAPInt>, std::pair<unsigned, DynamicAPInt>>
1826  rowsWithoutConstTerm;
1827  // To unique rows.
1828  SmallDenseSet<ArrayRef<DynamicAPInt>, 8> rowSet;
1829 
1830  // Check if constraint is of the form <non-negative-constant> >= 0.
1831  auto isTriviallyValid = [&](unsigned r) -> bool {
1832  for (unsigned c = 0, e = getNumCols() - 1; c < e; c++) {
1833  if (atIneq(r, c) != 0)
1834  return false;
1835  }
1836  return atIneq(r, getNumCols() - 1) >= 0;
1837  };
1838 
1839  // Detect and mark redundant constraints.
1840  SmallVector<bool, 256> redunIneq(getNumInequalities(), false);
1841  for (unsigned r = 0, e = getNumInequalities(); r < e; r++) {
1842  DynamicAPInt *rowStart = &inequalities(r, 0);
1843  auto row = ArrayRef<DynamicAPInt>(rowStart, getNumCols());
1844  if (isTriviallyValid(r) || !rowSet.insert(row).second) {
1845  redunIneq[r] = true;
1846  continue;
1847  }
1848 
1849  // Among constraints that only differ in the constant term part, mark
1850  // everything other than the one with the smallest constant term redundant.
1851  // (eg: among i - 16j - 5 >= 0, i - 16j - 1 >=0, i - 16j - 7 >= 0, the
1852  // former two are redundant).
1853  DynamicAPInt constTerm = atIneq(r, getNumCols() - 1);
1854  auto rowWithoutConstTerm =
1855  ArrayRef<DynamicAPInt>(rowStart, getNumCols() - 1);
1856  const auto &ret =
1857  rowsWithoutConstTerm.insert({rowWithoutConstTerm, {r, constTerm}});
1858  if (!ret.second) {
1859  // Check if the other constraint has a higher constant term.
1860  auto &val = ret.first->second;
1861  if (val.second > constTerm) {
1862  // The stored row is redundant. Mark it so, and update with this one.
1863  redunIneq[val.first] = true;
1864  val = {r, constTerm};
1865  } else {
1866  // The one stored makes this one redundant.
1867  redunIneq[r] = true;
1868  }
1869  }
1870  }
1871 
1872  // Scan to get rid of all rows marked redundant, in-place.
1873  unsigned pos = 0;
1874  for (unsigned r = 0, e = getNumInequalities(); r < e; r++)
1875  if (!redunIneq[r])
1876  inequalities.copyRow(r, pos++);
1877 
1879 
1880  // TODO: consider doing this for equalities as well, but probably not worth
1881  // the savings.
1882 }
1883 
1884 #undef DEBUG_TYPE
1885 #define DEBUG_TYPE "fm"
1886 
1887 /// Eliminates variable at the specified position using Fourier-Motzkin
1888 /// variable elimination. This technique is exact for rational spaces but
1889 /// conservative (in "rare" cases) for integer spaces. The operation corresponds
1890 /// to a projection operation yielding the (convex) set of integer points
1891 /// contained in the rational shadow of the set. An emptiness test that relies
1892 /// on this method will guarantee emptiness, i.e., it disproves the existence of
1893 /// a solution if it says it's empty.
1894 /// If a non-null isResultIntegerExact is passed, it is set to true if the
1895 /// result is also integer exact. If it's set to false, the obtained solution
1896 /// *may* not be exact, i.e., it may contain integer points that do not have an
1897 /// integer pre-image in the original set.
1898 ///
1899 /// Eg:
1900 /// j >= 0, j <= i + 1
1901 /// i >= 0, i <= N + 1
1902 /// Eliminating i yields,
1903 /// j >= 0, 0 <= N + 1, j - 1 <= N + 1
1904 ///
1905 /// If darkShadow = true, this method computes the dark shadow on elimination;
1906 /// the dark shadow is a convex integer subset of the exact integer shadow. A
1907 /// non-empty dark shadow proves the existence of an integer solution. The
1908 /// elimination in such a case could however be an under-approximation, and thus
1909 /// should not be used for scanning sets or used by itself for dependence
1910 /// checking.
1911 ///
1912 /// Eg: 2-d set, * represents grid points, 'o' represents a point in the set.
1913 /// ^
1914 /// |
1915 /// | * * * * o o
1916 /// i | * * o o o o
1917 /// | o * * * * *
1918 /// --------------->
1919 /// j ->
1920 ///
1921 /// Eliminating i from this system (projecting on the j dimension):
1922 /// rational shadow / integer light shadow: 1 <= j <= 6
1923 /// dark shadow: 3 <= j <= 6
1924 /// exact integer shadow: j = 1 \union 3 <= j <= 6
1925 /// holes/splinters: j = 2
1926 ///
1927 /// darkShadow = false, isResultIntegerExact = nullptr are default values.
1928 // TODO: a slight modification to yield dark shadow version of FM (tightened),
1929 // which can prove the existence of a solution if there is one.
1930 void IntegerRelation::fourierMotzkinEliminate(unsigned pos, bool darkShadow,
1931  bool *isResultIntegerExact) {
1932  LLVM_DEBUG(llvm::dbgs() << "FM input (eliminate pos " << pos << "):\n");
1933  LLVM_DEBUG(dump());
1934  assert(pos < getNumVars() && "invalid position");
1935  assert(hasConsistentState());
1936 
1937  // Check if this variable can be eliminated through a substitution.
1938  for (unsigned r = 0, e = getNumEqualities(); r < e; r++) {
1939  if (atEq(r, pos) != 0) {
1940  // Use Gaussian elimination here (since we have an equality).
1941  LogicalResult ret = gaussianEliminateVar(pos);
1942  (void)ret;
1943  assert(ret.succeeded() && "Gaussian elimination guaranteed to succeed");
1944  LLVM_DEBUG(llvm::dbgs() << "FM output (through Gaussian elimination):\n");
1945  LLVM_DEBUG(dump());
1946  return;
1947  }
1948  }
1949 
1950  // A fast linear time tightening.
1952 
1953  // Check if the variable appears at all in any of the inequalities.
1954  if (isColZero(pos)) {
1955  // If it doesn't appear, just remove the column and return.
1956  // TODO: refactor removeColumns to use it from here.
1957  removeVar(pos);
1958  LLVM_DEBUG(llvm::dbgs() << "FM output:\n");
1959  LLVM_DEBUG(dump());
1960  return;
1961  }
1962 
1963  // Positions of constraints that are lower bounds on the variable.
1964  SmallVector<unsigned, 4> lbIndices;
1965  // Positions of constraints that are lower bounds on the variable.
1966  SmallVector<unsigned, 4> ubIndices;
1967  // Positions of constraints that do not involve the variable.
1968  std::vector<unsigned> nbIndices;
1969  nbIndices.reserve(getNumInequalities());
1970 
1971  // Gather all lower bounds and upper bounds of the variable. Since the
1972  // canonical form c_1*x_1 + c_2*x_2 + ... + c_0 >= 0, a constraint is a lower
1973  // bound for x_i if c_i >= 1, and an upper bound if c_i <= -1.
1974  for (unsigned r = 0, e = getNumInequalities(); r < e; r++) {
1975  if (atIneq(r, pos) == 0) {
1976  // Var does not appear in bound.
1977  nbIndices.emplace_back(r);
1978  } else if (atIneq(r, pos) >= 1) {
1979  // Lower bound.
1980  lbIndices.emplace_back(r);
1981  } else {
1982  // Upper bound.
1983  ubIndices.emplace_back(r);
1984  }
1985  }
1986 
1987  PresburgerSpace newSpace = getSpace();
1988  VarKind idKindRemove = newSpace.getVarKindAt(pos);
1989  unsigned relativePos = pos - newSpace.getVarKindOffset(idKindRemove);
1990  newSpace.removeVarRange(idKindRemove, relativePos, relativePos + 1);
1991 
1992  /// Create the new system which has one variable less.
1993  IntegerRelation newRel(lbIndices.size() * ubIndices.size() + nbIndices.size(),
1994  getNumEqualities(), getNumCols() - 1, newSpace);
1995 
1996  // This will be used to check if the elimination was integer exact.
1997  bool allLCMsAreOne = true;
1998 
1999  // Let x be the variable we are eliminating.
2000  // For each lower bound, lb <= c_l*x, and each upper bound c_u*x <= ub, (note
2001  // that c_l, c_u >= 1) we have:
2002  // lb*lcm(c_l, c_u)/c_l <= lcm(c_l, c_u)*x <= ub*lcm(c_l, c_u)/c_u
2003  // We thus generate a constraint:
2004  // lcm(c_l, c_u)/c_l*lb <= lcm(c_l, c_u)/c_u*ub.
2005  // Note if c_l = c_u = 1, all integer points captured by the resulting
2006  // constraint correspond to integer points in the original system (i.e., they
2007  // have integer pre-images). Hence, if the lcm's are all 1, the elimination is
2008  // integer exact.
2009  for (auto ubPos : ubIndices) {
2010  for (auto lbPos : lbIndices) {
2012  ineq.reserve(newRel.getNumCols());
2013  DynamicAPInt lbCoeff = atIneq(lbPos, pos);
2014  // Note that in the comments above, ubCoeff is the negation of the
2015  // coefficient in the canonical form as the view taken here is that of the
2016  // term being moved to the other size of '>='.
2017  DynamicAPInt ubCoeff = -atIneq(ubPos, pos);
2018  // TODO: refactor this loop to avoid all branches inside.
2019  for (unsigned l = 0, e = getNumCols(); l < e; l++) {
2020  if (l == pos)
2021  continue;
2022  assert(lbCoeff >= 1 && ubCoeff >= 1 && "bounds wrongly identified");
2023  DynamicAPInt lcm = llvm::lcm(lbCoeff, ubCoeff);
2024  ineq.emplace_back(atIneq(ubPos, l) * (lcm / ubCoeff) +
2025  atIneq(lbPos, l) * (lcm / lbCoeff));
2026  assert(lcm > 0 && "lcm should be positive!");
2027  if (lcm != 1)
2028  allLCMsAreOne = false;
2029  }
2030  if (darkShadow) {
2031  // The dark shadow is a convex subset of the exact integer shadow. If
2032  // there is a point here, it proves the existence of a solution.
2033  ineq[ineq.size() - 1] += lbCoeff * ubCoeff - lbCoeff - ubCoeff + 1;
2034  }
2035  // TODO: we need to have a way to add inequalities in-place in
2036  // IntegerRelation instead of creating and copying over.
2037  newRel.addInequality(ineq);
2038  }
2039  }
2040 
2041  LLVM_DEBUG(llvm::dbgs() << "FM isResultIntegerExact: " << allLCMsAreOne
2042  << "\n");
2043  if (allLCMsAreOne && isResultIntegerExact)
2044  *isResultIntegerExact = true;
2045 
2046  // Copy over the constraints not involving this variable.
2047  for (auto nbPos : nbIndices) {
2049  ineq.reserve(getNumCols() - 1);
2050  for (unsigned l = 0, e = getNumCols(); l < e; l++) {
2051  if (l == pos)
2052  continue;
2053  ineq.emplace_back(atIneq(nbPos, l));
2054  }
2055  newRel.addInequality(ineq);
2056  }
2057 
2058  assert(newRel.getNumConstraints() ==
2059  lbIndices.size() * ubIndices.size() + nbIndices.size());
2060 
2061  // Copy over the equalities.
2062  for (unsigned r = 0, e = getNumEqualities(); r < e; r++) {
2064  eq.reserve(newRel.getNumCols());
2065  for (unsigned l = 0, e = getNumCols(); l < e; l++) {
2066  if (l == pos)
2067  continue;
2068  eq.emplace_back(atEq(r, l));
2069  }
2070  newRel.addEquality(eq);
2071  }
2072 
2073  // GCD tightening and normalization allows detection of more trivially
2074  // redundant constraints.
2075  newRel.gcdTightenInequalities();
2076  newRel.normalizeConstraintsByGCD();
2077  newRel.removeTrivialRedundancy();
2078  clearAndCopyFrom(newRel);
2079  LLVM_DEBUG(llvm::dbgs() << "FM output:\n");
2080  LLVM_DEBUG(dump());
2081 }
2082 
2083 #undef DEBUG_TYPE
2084 #define DEBUG_TYPE "presburger"
2085 
2086 void IntegerRelation::projectOut(unsigned pos, unsigned num) {
2087  if (num == 0)
2088  return;
2089 
2090  // 'pos' can be at most getNumCols() - 2 if num > 0.
2091  assert((getNumCols() < 2 || pos <= getNumCols() - 2) && "invalid position");
2092  assert(pos + num < getNumCols() && "invalid range");
2093 
2094  // Eliminate as many variables as possible using Gaussian elimination.
2095  unsigned currentPos = pos;
2096  unsigned numToEliminate = num;
2097  unsigned numGaussianEliminated = 0;
2098 
2099  while (currentPos < getNumVars()) {
2100  unsigned curNumEliminated =
2101  gaussianEliminateVars(currentPos, currentPos + numToEliminate);
2102  ++currentPos;
2103  numToEliminate -= curNumEliminated + 1;
2104  numGaussianEliminated += curNumEliminated;
2105  }
2106 
2107  // Eliminate the remaining using Fourier-Motzkin.
2108  for (unsigned i = 0; i < num - numGaussianEliminated; i++) {
2109  unsigned numToEliminate = num - numGaussianEliminated - i;
2111  getBestVarToEliminate(*this, pos, pos + numToEliminate));
2112  }
2113 
2114  // Fast/trivial simplifications.
2116  // Normalize constraints after tightening since the latter impacts this, but
2117  // not the other way round.
2119 }
2120 
2121 namespace {
2122 
2123 enum BoundCmpResult { Greater, Less, Equal, Unknown };
2124 
2125 /// Compares two affine bounds whose coefficients are provided in 'first' and
2126 /// 'second'. The last coefficient is the constant term.
2127 static BoundCmpResult compareBounds(ArrayRef<DynamicAPInt> a,
2129  assert(a.size() == b.size());
2130 
2131  // For the bounds to be comparable, their corresponding variable
2132  // coefficients should be equal; the constant terms are then compared to
2133  // determine less/greater/equal.
2134 
2135  if (!std::equal(a.begin(), a.end() - 1, b.begin()))
2136  return Unknown;
2137 
2138  if (a.back() == b.back())
2139  return Equal;
2140 
2141  return a.back() < b.back() ? Less : Greater;
2142 }
2143 } // namespace
2144 
2145 // Returns constraints that are common to both A & B.
2147  const IntegerRelation &b, IntegerRelation &c) {
2148  c = IntegerRelation(a.getSpace());
2149  // a naive O(n^2) check should be enough here given the input sizes.
2150  for (unsigned r = 0, e = a.getNumInequalities(); r < e; ++r) {
2151  for (unsigned s = 0, f = b.getNumInequalities(); s < f; ++s) {
2152  if (a.getInequality(r) == b.getInequality(s)) {
2153  c.addInequality(a.getInequality(r));
2154  break;
2155  }
2156  }
2157  }
2158  for (unsigned r = 0, e = a.getNumEqualities(); r < e; ++r) {
2159  for (unsigned s = 0, f = b.getNumEqualities(); s < f; ++s) {
2160  if (a.getEquality(r) == b.getEquality(s)) {
2161  c.addEquality(a.getEquality(r));
2162  break;
2163  }
2164  }
2165  }
2166 }
2167 
2168 // Computes the bounding box with respect to 'other' by finding the min of the
2169 // lower bounds and the max of the upper bounds along each of the dimensions.
2170 LogicalResult
2172  assert(space.isEqual(otherCst.getSpace()) && "Spaces should match.");
2173  assert(getNumLocalVars() == 0 && "local ids not supported yet here");
2174 
2175  // Get the constraints common to both systems; these will be added as is to
2176  // the union.
2178  getCommonConstraints(*this, otherCst, commonCst);
2179 
2180  std::vector<SmallVector<DynamicAPInt, 8>> boundingLbs;
2181  std::vector<SmallVector<DynamicAPInt, 8>> boundingUbs;
2182  boundingLbs.reserve(2 * getNumDimVars());
2183  boundingUbs.reserve(2 * getNumDimVars());
2184 
2185  // To hold lower and upper bounds for each dimension.
2186  SmallVector<DynamicAPInt, 4> lb, otherLb, ub, otherUb;
2187  // To compute min of lower bounds and max of upper bounds for each dimension.
2190  // To compute final new lower and upper bounds for the union.
2192 
2193  DynamicAPInt lbFloorDivisor, otherLbFloorDivisor;
2194  for (unsigned d = 0, e = getNumDimVars(); d < e; ++d) {
2195  auto extent = getConstantBoundOnDimSize(d, &lb, &lbFloorDivisor, &ub);
2196  if (!extent.has_value())
2197  // TODO: symbolic extents when necessary.
2198  // TODO: handle union if a dimension is unbounded.
2199  return failure();
2200 
2201  auto otherExtent = otherCst.getConstantBoundOnDimSize(
2202  d, &otherLb, &otherLbFloorDivisor, &otherUb);
2203  if (!otherExtent.has_value() || lbFloorDivisor != otherLbFloorDivisor)
2204  // TODO: symbolic extents when necessary.
2205  return failure();
2206 
2207  assert(lbFloorDivisor > 0 && "divisor always expected to be positive");
2208 
2209  auto res = compareBounds(lb, otherLb);
2210  // Identify min.
2211  if (res == BoundCmpResult::Less || res == BoundCmpResult::Equal) {
2212  minLb = lb;
2213  // Since the divisor is for a floordiv, we need to convert to ceildiv,
2214  // i.e., i >= expr floordiv div <=> i >= (expr - div + 1) ceildiv div <=>
2215  // div * i >= expr - div + 1.
2216  minLb.back() -= lbFloorDivisor - 1;
2217  } else if (res == BoundCmpResult::Greater) {
2218  minLb = otherLb;
2219  minLb.back() -= otherLbFloorDivisor - 1;
2220  } else {
2221  // Uncomparable - check for constant lower/upper bounds.
2222  auto constLb = getConstantBound(BoundType::LB, d);
2223  auto constOtherLb = otherCst.getConstantBound(BoundType::LB, d);
2224  if (!constLb.has_value() || !constOtherLb.has_value())
2225  return failure();
2226  std::fill(minLb.begin(), minLb.end(), 0);
2227  minLb.back() = std::min(*constLb, *constOtherLb);
2228  }
2229 
2230  // Do the same for ub's but max of upper bounds. Identify max.
2231  auto uRes = compareBounds(ub, otherUb);
2232  if (uRes == BoundCmpResult::Greater || uRes == BoundCmpResult::Equal) {
2233  maxUb = ub;
2234  } else if (uRes == BoundCmpResult::Less) {
2235  maxUb = otherUb;
2236  } else {
2237  // Uncomparable - check for constant lower/upper bounds.
2238  auto constUb = getConstantBound(BoundType::UB, d);
2239  auto constOtherUb = otherCst.getConstantBound(BoundType::UB, d);
2240  if (!constUb.has_value() || !constOtherUb.has_value())
2241  return failure();
2242  std::fill(maxUb.begin(), maxUb.end(), 0);
2243  maxUb.back() = std::max(*constUb, *constOtherUb);
2244  }
2245 
2246  std::fill(newLb.begin(), newLb.end(), 0);
2247  std::fill(newUb.begin(), newUb.end(), 0);
2248 
2249  // The divisor for lb, ub, otherLb, otherUb at this point is lbDivisor,
2250  // and so it's the divisor for newLb and newUb as well.
2251  newLb[d] = lbFloorDivisor;
2252  newUb[d] = -lbFloorDivisor;
2253  // Copy over the symbolic part + constant term.
2254  std::copy(minLb.begin(), minLb.end(), newLb.begin() + getNumDimVars());
2255  std::transform(newLb.begin() + getNumDimVars(), newLb.end(),
2256  newLb.begin() + getNumDimVars(),
2257  std::negate<DynamicAPInt>());
2258  std::copy(maxUb.begin(), maxUb.end(), newUb.begin() + getNumDimVars());
2259 
2260  boundingLbs.emplace_back(newLb);
2261  boundingUbs.emplace_back(newUb);
2262  }
2263 
2264  // Clear all constraints and add the lower/upper bounds for the bounding box.
2265  clearConstraints();
2266  for (unsigned d = 0, e = getNumDimVars(); d < e; ++d) {
2267  addInequality(boundingLbs[d]);
2268  addInequality(boundingUbs[d]);
2269  }
2270 
2271  // Add the constraints that were common to both systems.
2272  append(commonCst);
2274 
2275  // TODO: copy over pure symbolic constraints from this and 'other' over to the
2276  // union (since the above are just the union along dimensions); we shouldn't
2277  // be discarding any other constraints on the symbols.
2278 
2279  return success();
2280 }
2281 
2282 bool IntegerRelation::isColZero(unsigned pos) const {
2283  return !findConstraintWithNonZeroAt(pos, /*isEq=*/false) &&
2284  !findConstraintWithNonZeroAt(pos, /*isEq=*/true);
2285 }
2286 
2287 /// Find positions of inequalities and equalities that do not have a coefficient
2288 /// for [pos, pos + num) variables.
2289 static void getIndependentConstraints(const IntegerRelation &cst, unsigned pos,
2290  unsigned num,
2291  SmallVectorImpl<unsigned> &nbIneqIndices,
2292  SmallVectorImpl<unsigned> &nbEqIndices) {
2293  assert(pos < cst.getNumVars() && "invalid start position");
2294  assert(pos + num <= cst.getNumVars() && "invalid limit");
2295 
2296  for (unsigned r = 0, e = cst.getNumInequalities(); r < e; r++) {
2297  // The bounds are to be independent of [offset, offset + num) columns.
2298  unsigned c;
2299  for (c = pos; c < pos + num; ++c) {
2300  if (cst.atIneq(r, c) != 0)
2301  break;
2302  }
2303  if (c == pos + num)
2304  nbIneqIndices.emplace_back(r);
2305  }
2306 
2307  for (unsigned r = 0, e = cst.getNumEqualities(); r < e; r++) {
2308  // The bounds are to be independent of [offset, offset + num) columns.
2309  unsigned c;
2310  for (c = pos; c < pos + num; ++c) {
2311  if (cst.atEq(r, c) != 0)
2312  break;
2313  }
2314  if (c == pos + num)
2315  nbEqIndices.emplace_back(r);
2316  }
2317 }
2318 
2319 void IntegerRelation::removeIndependentConstraints(unsigned pos, unsigned num) {
2320  assert(pos + num <= getNumVars() && "invalid range");
2321 
2322  // Remove constraints that are independent of these variables.
2323  SmallVector<unsigned, 4> nbIneqIndices, nbEqIndices;
2324  getIndependentConstraints(*this, /*pos=*/0, num, nbIneqIndices, nbEqIndices);
2325 
2326  // Iterate in reverse so that indices don't have to be updated.
2327  // TODO: This method can be made more efficient (because removal of each
2328  // inequality leads to much shifting/copying in the underlying buffer).
2329  for (auto nbIndex : llvm::reverse(nbIneqIndices))
2330  removeInequality(nbIndex);
2331  for (auto nbIndex : llvm::reverse(nbEqIndices))
2332  removeEquality(nbIndex);
2333 }
2334 
2336  IntegerRelation copyRel = *this;
2337 
2338  // Convert Range variables to Local variables.
2340  VarKind::Local);
2341 
2342  // Convert Domain variables to SetDim(Range) variables.
2344  VarKind::SetDim);
2345 
2346  return IntegerPolyhedron(std::move(copyRel));
2347 }
2348 
2350  bool changed = false;
2351  SmallDenseMap<ArrayRef<DynamicAPInt>, unsigned> hashTable;
2352  unsigned ineqs = getNumInequalities(), cols = getNumCols();
2353 
2354  if (ineqs <= 1)
2355  return changed;
2356 
2357  // Check if the non-constant part of the constraint is the same.
2358  ArrayRef<DynamicAPInt> row = getInequality(0).drop_back();
2359  hashTable.insert({row, 0});
2360  for (unsigned k = 1; k < ineqs; ++k) {
2361  row = getInequality(k).drop_back();
2362  if (hashTable.try_emplace(row, k).second)
2363  continue;
2364 
2365  // For identical cases, keep only the smaller part of the constant term.
2366  unsigned l = hashTable[row];
2367  changed = true;
2368  if (atIneq(k, cols - 1) <= atIneq(l, cols - 1))
2369  inequalities.swapRows(k, l);
2370  removeInequality(k);
2371  --k;
2372  --ineqs;
2373  }
2374 
2375  // Check the neg form of each inequality, need an extra vector to store it.
2376  SmallVector<DynamicAPInt> negIneq(cols - 1);
2377  for (unsigned k = 0; k < ineqs; ++k) {
2378  row = getInequality(k).drop_back();
2379  negIneq.assign(row.begin(), row.end());
2380  for (DynamicAPInt &ele : negIneq)
2381  ele = -ele;
2382  if (!hashTable.contains(negIneq))
2383  continue;
2384 
2385  // For cases where the neg is the same as other inequalities, check that the
2386  // sum of their constant terms is positive.
2387  unsigned l = hashTable[row];
2388  auto sum = atIneq(l, cols - 1) + atIneq(k, cols - 1);
2389  if (sum > 0 || l == k)
2390  continue;
2391 
2392  // A sum of constant terms equal to zero combines two inequalities into one
2393  // equation, less than zero means the set is empty.
2394  changed = true;
2395  if (k < l)
2396  std::swap(l, k);
2397  if (sum == 0) {
2399  removeInequality(k);
2400  removeInequality(l);
2401  } else
2402  *this = getEmpty(getSpace());
2403  break;
2404  }
2405 
2406  return changed;
2407 }
2408 
2410  IntegerRelation copyRel = *this;
2411 
2412  // Convert Domain variables to Local variables.
2414  VarKind::Local);
2415 
2416  // We do not need to do anything to Range variables since they are already in
2417  // SetDim position.
2418 
2419  return IntegerPolyhedron(std::move(copyRel));
2420 }
2421 
2423  assert(getDomainSet().getSpace().isCompatible(poly.getSpace()) &&
2424  "Domain set is not compatible with poly");
2425 
2426  // Treating the poly as a relation, convert it from `0 -> R` to `R -> 0`.
2427  IntegerRelation rel = poly;
2428  rel.inverse();
2429 
2430  // Append dummy range variables to make the spaces compatible.
2432 
2433  // Intersect in place.
2434  mergeLocalVars(rel);
2435  append(rel);
2436 }
2437 
2439  assert(getRangeSet().getSpace().isCompatible(poly.getSpace()) &&
2440  "Range set is not compatible with poly");
2441 
2442  IntegerRelation rel = poly;
2443 
2444  // Append dummy domain variables to make the spaces compatible.
2446 
2447  mergeLocalVars(rel);
2448  append(rel);
2449 }
2450 
2452  unsigned numRangeVars = getNumVarKind(VarKind::Range);
2454  VarKind::Range);
2455  convertVarKind(VarKind::Range, 0, numRangeVars, VarKind::Domain);
2456 }
2457 
2459  assert(getRangeSet().getSpace().isCompatible(rel.getDomainSet().getSpace()) &&
2460  "Range of `this` should be compatible with Domain of `rel`");
2461 
2462  IntegerRelation copyRel = rel;
2463 
2464  // Let relation `this` be R1: A -> B, and `rel` be R2: B -> C.
2465  // We convert R1 to A -> (B X C), and R2 to B X C then intersect the range of
2466  // R1 with R2. After this, we get R1: A -> C, by projecting out B.
2467  // TODO: Using nested spaces here would help, since we could directly
2468  // intersect the range with another relation.
2469  unsigned numBVars = getNumRangeVars();
2470 
2471  // Convert R1 from A -> B to A -> (B X C).
2473 
2474  // Convert R2 to B X C.
2475  copyRel.convertVarKind(VarKind::Domain, 0, numBVars, VarKind::Range, 0);
2476 
2477  // Intersect R2 to range of R1.
2479 
2480  // Project out B in R1.
2482 }
2483 
2485  inverse();
2486  compose(rel);
2487  inverse();
2488 }
2489 
2491 
2492 void IntegerRelation::printSpace(raw_ostream &os) const {
2493  space.print(os);
2494  os << getNumConstraints() << " constraints\n";
2495 }
2496 
2498  for (int i = getNumEqualities() - 1; i >= 0; --i)
2499  if (rangeIsZero(getEquality(i)))
2500  removeEquality(i);
2501 }
2502 
2504  if (getNumVars() == 0)
2505  return true;
2506  if (isEmpty())
2507  return false;
2508 
2509  // If there is a non-trivial equality, the space cannot be full-dimensional.
2511  if (getNumEqualities() > 0)
2512  return false;
2513 
2514  // The polytope is full-dimensional iff it is not flat along any of the
2515  // inequality directions.
2516  Simplex simplex(*this);
2517  return llvm::none_of(llvm::seq<int>(getNumInequalities()), [&](int i) {
2518  return simplex.isFlatAlong(getInequality(i));
2519  });
2520 }
2521 
2523  assert(getNumDomainVars() == other.getNumRangeVars() &&
2524  "Domain of this and range of other do not match");
2525  // assert(std::equal(values.begin(), values.begin() +
2526  // other.getNumDomainVars(),
2527  // otherValues.begin() + other.getNumDomainVars()) &&
2528  // "Domain of this and range of other do not match");
2529 
2530  IntegerRelation result = other;
2531 
2532  const unsigned thisDomain = getNumDomainVars();
2533  const unsigned thisRange = getNumRangeVars();
2534  const unsigned otherDomain = other.getNumDomainVars();
2535  const unsigned otherRange = other.getNumRangeVars();
2536 
2537  // Add dimension variables temporarily to merge symbol and local vars.
2538  // Convert `this` from
2539  // [thisDomain] -> [thisRange]
2540  // to
2541  // [otherDomain thisDomain] -> [otherRange thisRange].
2542  // and `result` from
2543  // [otherDomain] -> [otherRange]
2544  // to
2545  // [otherDomain thisDomain] -> [otherRange thisRange]
2546  insertVar(VarKind::Domain, 0, otherDomain);
2547  insertVar(VarKind::Range, 0, otherRange);
2548  result.insertVar(VarKind::Domain, otherDomain, thisDomain);
2549  result.insertVar(VarKind::Range, otherRange, thisRange);
2550 
2551  // Merge symbol and local variables.
2552  mergeAndAlignSymbols(result);
2553  mergeLocalVars(result);
2554 
2555  // Convert `result` from [otherDomain thisDomain] -> [otherRange thisRange] to
2556  // [otherDomain] -> [thisRange]
2557  result.removeVarRange(VarKind::Domain, otherDomain, otherDomain + thisDomain);
2558  result.convertToLocal(VarKind::Range, 0, otherRange);
2559  // Convert `this` from [otherDomain thisDomain] -> [otherRange thisRange] to
2560  // [otherDomain] -> [thisRange]
2561  convertToLocal(VarKind::Domain, otherDomain, otherDomain + thisDomain);
2562  removeVarRange(VarKind::Range, 0, otherRange);
2563 
2564  // Add and match domain of `result` to domain of `this`.
2565  for (unsigned i = 0, e = result.getNumDomainVars(); i < e; ++i)
2566  if (result.getSpace().getId(VarKind::Domain, i).hasValue())
2568  result.getSpace().getId(VarKind::Domain, i));
2569  // Add and match range of `this` to range of `result`.
2570  for (unsigned i = 0, e = getNumRangeVars(); i < e; ++i)
2571  if (space.getId(VarKind::Range, i).hasValue())
2573 
2574  // Append `this` to `result` and simplify constraints.
2575  result.append(*this);
2576  result.removeRedundantLocalVars();
2577 
2578  *this = result;
2579 }
2580 
2581 void IntegerRelation::print(raw_ostream &os) const {
2582  assert(hasConsistentState());
2583  printSpace(os);
2584  PrintTableMetrics ptm = {0, 0, "-"};
2585  for (unsigned i = 0, e = getNumEqualities(); i < e; ++i)
2586  for (unsigned j = 0, f = getNumCols(); j < f; ++j)
2587  updatePrintMetrics<DynamicAPInt>(atEq(i, j), ptm);
2588  for (unsigned i = 0, e = getNumInequalities(); i < e; ++i)
2589  for (unsigned j = 0, f = getNumCols(); j < f; ++j)
2590  updatePrintMetrics<DynamicAPInt>(atIneq(i, j), ptm);
2591  // Print using PrintMetrics.
2592  constexpr unsigned kMinSpacing = 1;
2593  for (unsigned i = 0, e = getNumEqualities(); i < e; ++i) {
2594  for (unsigned j = 0, f = getNumCols(); j < f; ++j) {
2595  printWithPrintMetrics<DynamicAPInt>(os, atEq(i, j), kMinSpacing, ptm);
2596  }
2597  os << " = 0\n";
2598  }
2599  for (unsigned i = 0, e = getNumInequalities(); i < e; ++i) {
2600  for (unsigned j = 0, f = getNumCols(); j < f; ++j) {
2601  printWithPrintMetrics<DynamicAPInt>(os, atIneq(i, j), kMinSpacing, ptm);
2602  }
2603  os << " >= 0\n";
2604  }
2605  os << '\n';
2606 }
2607 
2608 void IntegerRelation::dump() const { print(llvm::errs()); }
2609 
2611  unsigned num) {
2612  assert((kind != VarKind::Domain || num == 0) &&
2613  "Domain has to be zero in a set");
2614  return IntegerRelation::insertVar(kind, pos, num);
2615 }
2619 }
2620 
2623 }
static void copy(Location loc, Value dst, Value src, Value size, OpBuilder &builder)
Copies the given number of bytes from src to dst pointers.
static bool rangeIsZero(ArrayRef< DynamicAPInt > range)
static void getIndependentConstraints(const IntegerRelation &cst, unsigned pos, unsigned num, SmallVectorImpl< unsigned > &nbIneqIndices, SmallVectorImpl< unsigned > &nbEqIndices)
Find positions of inequalities and equalities that do not have a coefficient for [pos,...
static void removeConstraintsInvolvingVarRange(IntegerRelation &poly, unsigned begin, unsigned count)
static unsigned getBestVarToEliminate(const IntegerRelation &cst, unsigned start, unsigned end)
Returns the position of the variable that has the minimum <number of lower bounds> times <number of u...
static void getCommonConstraints(const IntegerRelation &a, const IntegerRelation &b, IntegerRelation &c)
static void eliminateFromConstraint(IntegerRelation *constraints, unsigned rowIdx, unsigned pivotRow, unsigned pivotCol, unsigned elimColStart, bool isEq)
Eliminate variable from constraint at rowIdx based on coefficient at pivotRow, pivotCol.
static DynamicAPInt valueAt(ArrayRef< DynamicAPInt > expr, ArrayRef< DynamicAPInt > point)
Helper to evaluate an affine expression at a point.
union mlir::linalg::@1183::ArityGroupAndKind::Kind kind
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
int64_t cols
Class storing division representation of local variables of a constraint system.
Definition: Utils.h:117
void removeDuplicateDivs(llvm::function_ref< bool(unsigned i, unsigned j)> merge)
Removes duplicate divisions.
Definition: Utils.cpp:441
bool hasAllReprs() const
Definition: Utils.h:133
void clearRepr(unsigned i)
Definition: Utils.h:136
DynamicAPInt & getDenom(unsigned i)
Definition: Utils.h:153
MutableArrayRef< DynamicAPInt > getDividend(unsigned i)
Definition: Utils.h:139
An Identifier stores a pointer to an object, such as a Value or an Operation.
DynamicAPInt normalizeRow(unsigned row, unsigned nCols)
Divide the first nCols of the specified row by their GCD.
Definition: Matrix.cpp:549
An IntegerPolyhedron represents the set of points from a PresburgerSpace that satisfy a list of affin...
IntegerPolyhedron intersect(const IntegerPolyhedron &other) const
Return the intersection of the two relations.
unsigned insertVar(VarKind kind, unsigned pos, unsigned num=1) override
Insert num variables of the specified kind at position pos.
PresburgerSet subtract(const PresburgerSet &other) const
Return the set difference of this set and the given set, i.e., return this \ set.
IntegerPolyhedron(unsigned numReservedInequalities, unsigned numReservedEqualities, unsigned numReservedCols, const PresburgerSpace &space)
Constructs a set reserving memory for the specified number of constraints and variables.
std::unique_ptr< IntegerPolyhedron > clone() const
An IntegerRelation represents the set of points from a PresburgerSpace that satisfy a list of affine ...
std::optional< DynamicAPInt > getConstantBoundOnDimSize(unsigned pos, SmallVectorImpl< DynamicAPInt > *lb=nullptr, DynamicAPInt *boundFloorDivisor=nullptr, SmallVectorImpl< DynamicAPInt > *ub=nullptr, unsigned *minLbPos=nullptr, unsigned *minUbPos=nullptr) const
Returns the smallest known constant bound for the extent of the specified variable (pos^th),...
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 removeIndependentConstraints(unsigned pos, unsigned num)
Removes constraints that are independent of (i.e., do not have a coefficient) variables in the range ...
void compose(const IntegerRelation &rel)
Let the relation this be R1, and the relation rel be R2.
void applyRange(const IntegerRelation &rel)
Given a relation rel, apply the relation to the range of this relation.
unsigned getVarKindEnd(VarKind kind) const
Return the index at Which the specified kind of vars ends.
ArrayRef< Identifier > getIds(VarKind kind)
Get the identifiers for the variables of specified varKind.
void removeTrivialRedundancy()
Removes duplicate constraints, trivially true constraints, and constraints that can be detected as re...
static IntegerRelation getEmpty(const PresburgerSpace &space)
Return an empty system containing an invalid equation 0 = 1.
std::optional< unsigned > findConstraintWithNonZeroAt(unsigned colIdx, bool isEq) const
Finds a constraint with a non-zero coefficient at colIdx in equality (isEq=true) or inequality (isEq=...
void removeInequalityRange(unsigned start, unsigned end)
void normalizeConstraintsByGCD()
Normalized each constraints by the GCD of its coefficients.
void truncate(const CountsSnapshot &counts)
virtual void eliminateRedundantLocalVar(unsigned posA, unsigned posB)
Eliminate the posB^th local variable, replacing every instance of it with the posA^th local variable.
std::optional< DynamicAPInt > computeConstantLowerOrUpperBound(unsigned pos)
Returns the constant lower bound if isLower is true, and the upper bound if isLower is false.
void removeEqualityRange(unsigned start, unsigned end)
Remove the (in)equalities at positions [start, end).
LogicalResult constantFoldVar(unsigned pos)
Tries to fold the specified variable to a constant using a trivial equality detection; if successful,...
bool isObviouslyEqual(const IntegerRelation &other) const
Perform a quick equality check on this and other.
IntegerPolyhedron getRangeSet() const
Return a set corresponding to all points in the range of the relation.
std::optional< SmallVector< DynamicAPInt, 8 > > containsPointNoLocal(ArrayRef< DynamicAPInt > point) const
Given the values of non-local vars, return a satisfying assignment to the local if one exists,...
ArrayRef< DynamicAPInt > getInequality(unsigned idx) const
unsigned getNumVarKind(VarKind kind) const
Get the number of vars of the specified kind.
bool isEmptyByGCDTest() const
Runs the GCD test on all equality constraints.
void simplify()
Simplify the constraint system by removing canonicalizing constraints and removing redundant constrai...
void convertVarKind(VarKind srcKind, unsigned varStart, unsigned varLimit, VarKind dstKind, unsigned pos)
Converts variables of kind srcKind in the range [varStart, varLimit) to variables of kind dstKind.
void addBound(BoundType type, unsigned pos, const DynamicAPInt &value)
Adds a constant bound for the specified variable.
unsigned appendVar(VarKind kind, unsigned num=1)
Append num variables of the specified kind after the last variable of that kind.
void intersectRange(const IntegerPolyhedron &poly)
Intersect the given poly with the range in-place.
void addLocalFloorDiv(ArrayRef< DynamicAPInt > dividend, const DynamicAPInt &divisor)
Adds a new local variable as the floordiv of an affine function of other variables,...
void print(raw_ostream &os) const
bool isIntegerEmpty() const
Returns true if the set of constraints is found to have no solution, false if a solution exists.
DynamicAPInt atIneq(unsigned i, unsigned j) const
Returns the value at the specified inequality row and column.
virtual unsigned insertVar(VarKind kind, unsigned pos, unsigned num=1)
Insert num variables of the specified kind at position pos.
bool containsPoint(ArrayRef< DynamicAPInt > point) const
Returns true if the given point satisfies the constraints, or false otherwise.
std::optional< SmallVector< DynamicAPInt, 8 > > findIntegerSample() const
Find an integer sample point satisfying the constraints using a branch and bound algorithm with gener...
bool hasInvalidConstraint() const
Checks all rows of equality/inequality constraints for trivial contradictions (for example: 1 == 0,...
LogicalResult unionBoundingBox(const IntegerRelation &other)
Updates the constraints to be the smallest bounding (enclosing) box that contains the points of this ...
IntegerRelation(unsigned numReservedInequalities, unsigned numReservedEqualities, unsigned numReservedCols, const PresburgerSpace &space)
Constructs a relation reserving memory for the specified number of constraints and variables.
bool isHyperRectangular(unsigned pos, unsigned num) const
Returns true if the set can be trivially detected as being hyper-rectangular on the specified contigu...
void convertToLocal(VarKind kind, unsigned varStart, unsigned varLimit)
IntMatrix getBoundedDirections() const
Returns a matrix where each row is a vector along which the polytope is bounded.
LogicalResult gaussianEliminateVar(unsigned position)
Eliminates a single variable at position from equality and inequality constraints.
void clearConstraints()
Removes all equalities and inequalities.
DynamicAPInt atEq(unsigned i, unsigned j) const
Returns the value at the specified equality row and column.
IntegerRelation intersect(IntegerRelation other) const
Return the intersection of the two relations.
std::optional< DynamicAPInt > computeVolume() const
Compute an overapproximation of the number of integer points in the relation.
MaybeOptimum< SmallVector< DynamicAPInt, 8 > > findIntegerLexMin() const
Same as above, but returns lexicographically minimal integer point.
SymbolicLexOpt findSymbolicIntegerLexMin() const
Compute the symbolic integer lexmin of the relation.
void setSpace(const PresburgerSpace &oSpace)
Set the space to oSpace, which should have the same number of ids as the current space.
int findEqualityToConstant(unsigned pos, bool symbolic=false) const
Finds an equality that equates the specified variable to a constant.
void inverse()
Invert the relation i.e., swap its domain and range.
void append(const IntegerRelation &other)
Appends constraints from other into this.
void applyDomain(const IntegerRelation &rel)
Given a relation rel, apply the relation to the domain of this relation.
void intersectDomain(const IntegerPolyhedron &poly)
Intersect the given poly with the domain in-place.
PresburgerRelation subtract(const PresburgerRelation &set) const
Return the set difference of this set and the given set, i.e., return this \ set.
bool isEqual(const IntegerRelation &other) const
Return whether this and other are equal.
virtual void printSpace(raw_ostream &os) const
Prints the number of constraints, dimensions, symbols and locals in the IntegerRelation.
void addEquality(ArrayRef< DynamicAPInt > eq)
Adds an equality from the coefficients specified in eq.
void removeRedundantConstraints()
Removes redundant constraints using Simplex.
PresburgerRelation computeReprWithOnlyDivLocals() const
Compute an equivalent representation of the same set, such that all local vars in all disjuncts have ...
void removeRedundantInequalities()
A more expensive check than removeTrivialRedundancy to detect redundant inequalities.
bool isObviouslyEmpty() const
Performs GCD checks and invalid constraint checks.
IntMatrix equalities
Coefficients of affine equalities (in == 0 form).
SymbolicLexOpt findSymbolicIntegerLexMax() const
Same as findSymbolicIntegerLexMin but produces lexmax instead of lexmin.
bool gaussianEliminate()
Perform a Gaussian elimination operation to reduce all equations to standard form.
void truncateVarKind(VarKind kind, unsigned num)
Truncate the vars of the specified kind to the specified number by dropping some vars at the end.
void constantFoldVarRange(unsigned pos, unsigned num)
This method calls constantFoldVar for the specified range of variables, num variables starting at pos...
bool isEmpty() const
Checks for emptiness by performing variable elimination on all variables, running the GCD test on eac...
unsigned getNumCols() const
Returns the number of columns in the constraint system.
void getLowerAndUpperBoundIndices(unsigned pos, SmallVectorImpl< unsigned > *lbIndices, SmallVectorImpl< unsigned > *ubIndices, SmallVectorImpl< unsigned > *eqIndices=nullptr, unsigned offset=0, unsigned num=0) const
Gather positions of all lower and upper bounds of the variable at pos, and optionally any equalities ...
void gcdTightenInequalities()
Tightens inequalities given that we are dealing with integer spaces.
void removeVar(VarKind kind, unsigned pos)
Removes variables of the specified kind with the specified pos (or within the specified range) from t...
void setSpaceExceptLocals(const PresburgerSpace &oSpace)
Set the space to oSpace, which should not have any local ids.
unsigned gaussianEliminateVars(unsigned posStart, unsigned posLimit)
Eliminates variables from equality and inequality constraints in column range [posStart,...
void mergeAndCompose(const IntegerRelation &other)
Given a relation other: (A -> B), this operation merges the symbol and local variables and then takes...
IntegerPolyhedron getDomainSet() const
Return a set corresponding to all points in the domain of the relation.
DivisionRepr getLocalReprs(std::vector< MaybeLocalRepr > *repr=nullptr) const
Returns a DivisonRepr representing the division representation of local variables in the constraint s...
bool hasOnlyDivLocals() const
Check whether all local ids have a division representation.
constexpr static unsigned kExplosionFactor
A parameter that controls detection of an unrealistic number of constraints.
std::optional< DynamicAPInt > getConstantBound(BoundType type, unsigned pos) const
Returns the constant bound for the pos^th variable if there is one; std::nullopt otherwise.
virtual void clearAndCopyFrom(const IntegerRelation &other)
Replaces the contents of this IntegerRelation with other.
void projectOut(unsigned pos, unsigned num)
Projects out (aka eliminates) num variables starting at position pos.
void addInequality(ArrayRef< DynamicAPInt > inEq)
Adds an inequality (>= 0) from the coefficients specified in inEq.
void mergeAndAlignSymbols(IntegerRelation &other)
Merge and align symbol variables of this and other with respect to identifiers.
void removeRedundantLocalVars()
Removes local variables using equalities.
unsigned mergeLocalVars(IntegerRelation &other)
Adds additional local vars to the sets such that they both have the union of the local vars in each s...
MaybeOptimum< SmallVector< Fraction, 8 > > findRationalLexMin() const
Get the lexicographically minimum rational point satisfying the constraints.
IntMatrix inequalities
Coefficients of affine inequalities (in >= 0 form).
virtual bool hasConsistentState() const
Returns false if the fields corresponding to various variable counts, or equality/inequality buffer s...
ArrayRef< DynamicAPInt > getEquality(unsigned idx) const
bool isSubsetOf(const IntegerRelation &other) const
Return whether this is a subset of the given IntegerRelation.
std::unique_ptr< IntegerRelation > clone() const
const PresburgerSpace & getSpace() const
Returns a reference to the underlying space.
void setAndEliminate(unsigned pos, ArrayRef< DynamicAPInt > values)
Sets the values.size() variables starting at pos to the specified values and removes them.
bool isColZero(unsigned pos) const
Returns true if the pos^th column is all zero for both inequalities and equalities.
unsigned getVarKindOffset(VarKind kind) const
Return the index at which the specified kind of vars starts.
virtual void removeVarRange(VarKind kind, unsigned varStart, unsigned varLimit)
virtual void fourierMotzkinEliminate(unsigned pos, bool darkShadow=false, bool *isResultIntegerExact=nullptr)
Eliminates the variable at the specified position using Fourier-Motzkin variable elimination,...
bool removeDuplicateConstraints()
Checks for identical inequalities and eliminates redundant inequalities.
A class for lexicographic optimization without any symbols.
Definition: Simplex.h:478
MaybeOptimum< SmallVector< Fraction, 8 > > findRationalLexMin()
Return the lexicographically minimum rational solution to the constraints.
Definition: Simplex.cpp:235
MaybeOptimum< SmallVector< DynamicAPInt, 8 > > findIntegerLexMin()
Return the lexicographically minimum integer solution to the constraints.
Definition: Simplex.cpp:306
static std::pair< unsigned, LinearTransform > makeTransformToColumnEchelon(const IntMatrix &m)
IntegerRelation applyTo(const IntegerRelation &rel) const
SmallVector< DynamicAPInt, 8 > postMultiplyWithColumn(ArrayRef< DynamicAPInt > colVec) const
void moveColumns(unsigned srcPos, unsigned num, unsigned dstPos)
Move the columns in the source range [srcPos, srcPos + num) to the specified destination [dstPos,...
Definition: Matrix.cpp:266
bool hasConsistentState() const
Return whether the Matrix is in a consistent state with all its invariants satisfied.
Definition: Matrix.cpp:435
unsigned getNumRows() const
Definition: Matrix.h:86
void swapColumns(unsigned column, unsigned otherColumn)
Swap the given columns.
Definition: Matrix.cpp:120
unsigned appendExtraRow()
Add an extra row at the bottom of the matrix and return its position.
Definition: Matrix.cpp:65
void addToColumn(unsigned sourceColumn, unsigned targetColumn, const T &scale)
Add scale multiples of the source column to the target column.
Definition: Matrix.cpp:319
void copyRow(unsigned sourceRow, unsigned targetRow)
Definition: Matrix.cpp:244
void removeColumns(unsigned pos, unsigned count)
Remove the columns having positions pos, pos + 1, ...
Definition: Matrix.cpp:198
void insertColumns(unsigned pos, unsigned count)
Insert columns having positions pos, pos + 1, ...
Definition: Matrix.cpp:152
void removeRow(unsigned pos)
Definition: Matrix.cpp:230
void resizeVertically(unsigned newNRows)
Definition: Matrix.cpp:104
void swapRows(unsigned row, unsigned otherRow)
Swap the given rows.
Definition: Matrix.cpp:110
void reserveRows(unsigned rows)
Reserve enough space to resize to the specified number of rows without reallocations.
Definition: Matrix.cpp:60
void fillRow(unsigned row, const T &value)
Definition: Matrix.cpp:252
void negateRow(unsigned row)
Negate the specified row.
Definition: Matrix.cpp:334
void removeRows(unsigned pos, unsigned count)
Remove the rows having positions pos, pos + 1, ...
Definition: Matrix.cpp:234
bool isBounded() const
Definition: Utils.h:51
OptimumKind getKind() const
Definition: Utils.h:50
This class represents a multi-affine function with the domain as Z^d, where d is the number of domain...
Definition: PWMAFunction.h:41
const PresburgerSpace & getSpace() const
Definition: PWMAFunction.h:170
void removeOutputs(unsigned start, unsigned end)
Remove the specified range of outputs.
unsigned getNumOutputs() const
Definition: PWMAFunction.h:180
ArrayRef< Piece > getAllPieces() const
Return all the pieces of this piece-wise function.
Definition: PWMAFunction.h:204
PresburgerSet getDomain() const
Return the domain of this piece-wise MultiAffineFunction.
A PresburgerRelation represents a union of IntegerRelations that live in the same PresburgerSpace wit...
void setSpace(const PresburgerSpace &oSpace)
Set the space to oSpace.
PresburgerRelation subtract(const PresburgerRelation &set) const
Return the set difference of this set and the given set, i.e., return this \ set.
bool isSubsetOf(const PresburgerRelation &set) const
Return true if this set is a subset of the given set, and false otherwise.
bool isEqual(const PresburgerRelation &set) const
Return true if this set is equal to the given set, and false otherwise.
PresburgerSet unionSet(const PresburgerRelation &set) const
These operations are the same as the ones in PresburgeRelation, they just forward the arguement and r...
PresburgerSpace is the space of all possible values of a tuple of integer valued variables/variables.
void setId(VarKind kind, unsigned pos, Identifier id)
Set the identifier of pos^th variable of the specified kind.
unsigned getNumVarKind(VarKind kind) const
Get the number of vars of the specified kind.
void resetIds()
Reset the stored identifiers in the space.
bool isEqual(const PresburgerSpace &other) const
Returns true if both the spaces are equal including local variables i.e.
bool isUsingIds() const
Returns if identifiers are being used.
void convertVarKind(VarKind srcKind, unsigned srcPos, unsigned num, VarKind dstKind, unsigned dstPos)
Converts variables of the specified kind in the column range [srcPos, srcPos + num) to variables of t...
void removeVarRange(VarKind kind, unsigned varStart, unsigned varLimit)
Removes variables of the specified kind in the column range [varStart, varLimit).
unsigned getVarKindOffset(VarKind kind) const
Return the index at which the specified kind of var starts.
Identifier getId(VarKind kind, unsigned pos) const
Get the identifier of pos^th variable of the specified kind.
VarKind getVarKindAt(unsigned pos) const
Return the VarKind of the var at the specified position.
static PresburgerSpace getSetSpace(unsigned numDims=0, unsigned numSymbols=0, unsigned numLocals=0)
ArrayRef< Identifier > getIds(VarKind kind) const
bool isCompatible(const PresburgerSpace &other) const
Returns true if both the spaces are compatible i.e.
void print(llvm::raw_ostream &os) const
static PresburgerSpace getRelationSpace(unsigned numDomain=0, unsigned numRange=0, unsigned numSymbols=0, unsigned numLocals=0)
void swapVar(VarKind kindA, VarKind kindB, unsigned posA, unsigned posB)
Swaps the posA^th variable of kindA and posB^th variable of kindB.
unsigned insertVar(VarKind kind, unsigned pos, unsigned num=1)
Insert num variables of the specified kind at position pos.
bool isEmpty() const
Returns true if the tableau is empty (has conflicting constraints), false otherwise.
Definition: Simplex.cpp:1070
The Simplex class uses the Normal pivot rule and supports integer emptiness checks as well as detecti...
Definition: Simplex.h:691
std::pair< MaybeOptimum< DynamicAPInt >, MaybeOptimum< DynamicAPInt > > computeIntegerBounds(ArrayRef< DynamicAPInt > coeffs)
Returns a (min, max) pair denoting the minimum and maximum integer values of the given expression.
Definition: Simplex.cpp:2108
bool isMarkedRedundant(unsigned constraintIndex) const
Returns whether the specified constraint has been marked as redundant.
Definition: Simplex.cpp:1409
bool isFlatAlong(ArrayRef< DynamicAPInt > coeffs)
Check if the simplex takes only one rational value along the direction of coeffs.
Definition: Simplex.cpp:2116
bool isBoundedAlongConstraint(unsigned constraintIndex)
Returns whether the perpendicular of the specified constraint is a is a direction along which the pol...
Definition: Simplex.cpp:1399
bool isUnbounded()
Returns true if the polytope is unbounded, i.e., extends to infinity in some direction.
Definition: Simplex.cpp:1471
void detectRedundant(unsigned offset, unsigned count)
Finds a subset of constraints that is redundant, i.e., such that the set of solutions does not change...
Definition: Simplex.cpp:1429
std::optional< SmallVector< Fraction, 8 > > getRationalSample() const
Returns the current sample point, which may contain non-integer (rational) coordinates.
Definition: Simplex.cpp:1571
std::optional< SmallVector< DynamicAPInt, 8 > > findIntegerSample()
Returns an integer sample point if one exists, or std::nullopt otherwise.
Definition: Simplex.cpp:1997
A class to perform symbolic lexicographic optimization, i.e., to find, for every assignment to the sy...
Definition: Simplex.h:572
SymbolicLexOpt computeSymbolicIntegerLexMin()
The lexmin will be stored as a function lexopt from symbols to non-symbols in the result.
Definition: Simplex.cpp:537
BoundType
The type of bound: equal, lower bound or upper bound.
VarKind
Kind of variable.
MaybeLocalRepr computeSingleVarRepr(const IntegerRelation &cst, ArrayRef< bool > foundRepr, unsigned pos, MutableArrayRef< DynamicAPInt > dividend, DynamicAPInt &divisor)
Returns the MaybeLocalRepr struct which contains the indices of the constraints that can be expressed...
Definition: Utils.cpp:228
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
DynamicAPInt ceil(const Fraction &f)
Definition: Fraction.h:79
Fraction abs(const Fraction &f)
Definition: Fraction.h:107
SmallVector< DynamicAPInt, 8 > getDivUpperBound(ArrayRef< DynamicAPInt > dividend, const DynamicAPInt &divisor, unsigned localVarIdx)
If q is defined to be equal to expr floordiv d, this equivalent to saying that q is an integer and q ...
Definition: Utils.cpp:316
SmallVector< DynamicAPInt, 8 > getDivLowerBound(ArrayRef< DynamicAPInt > dividend, const DynamicAPInt &divisor, unsigned localVarIdx)
Definition: Utils.cpp:328
Include the generated interface declarations.
const FrozenRewritePatternSet GreedyRewriteConfig bool * changed
The struct CountsSnapshot stores the count of each VarKind, and also of each constraint type.
MaybeLocalRepr contains the indices of the constraints that can be expressed as a floordiv of an affi...
Definition: Utils.h:97
Example usage: Print .12, 3.4, 56.7 preAlign = ".", minSpacing = 1, .12 .12 3.4 3....
Definition: Utils.h:303
Represents the result of a symbolic lexicographic optimization computation.
Definition: Simplex.h:529
PWMAFunction lexopt
This maps assignments of symbols to the corresponding lexopt.
Definition: Simplex.h:537
PresburgerSet unboundedDomain
Contains all assignments to the symbols that made the lexopt unbounded.
Definition: Simplex.h:541
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.