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