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