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