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