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