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