1 //===- PresburgerRelation.cpp - MLIR PresburgerRelation 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 #include "mlir/Analysis/Presburger/PresburgerRelation.h"
10 #include "mlir/Analysis/Presburger/Simplex.h"
11 #include "mlir/Analysis/Presburger/Utils.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/ADT/ScopeExit.h"
14 #include "llvm/ADT/SmallBitVector.h"
15 
16 using namespace mlir;
17 using namespace presburger;
18 
19 PresburgerRelation::PresburgerRelation(const IntegerRelation &disjunct)
20     : PresburgerSpace(disjunct) {
21   unionInPlace(disjunct);
22 }
23 
24 unsigned PresburgerRelation::getNumDisjuncts() const {
25   return integerRelations.size();
26 }
27 
28 ArrayRef<IntegerRelation> PresburgerRelation::getAllDisjuncts() const {
29   return integerRelations;
30 }
31 
32 const IntegerRelation &PresburgerRelation::getDisjunct(unsigned index) const {
33   assert(index < integerRelations.size() && "index out of bounds!");
34   return integerRelations[index];
35 }
36 
37 /// Mutate this set, turning it into the union of this set and the given
38 /// IntegerRelation.
39 void PresburgerRelation::unionInPlace(const IntegerRelation &disjunct) {
40   assert(PresburgerSpace::isEqual(disjunct) && "Spaces should match");
41   integerRelations.push_back(disjunct);
42 }
43 
44 /// Mutate this set, turning it into the union of this set and the given set.
45 ///
46 /// This is accomplished by simply adding all the disjuncts of the given set
47 /// to this set.
48 void PresburgerRelation::unionInPlace(const PresburgerRelation &set) {
49   assert(PresburgerSpace::isEqual(set) && "Spaces should match");
50   for (const IntegerRelation &disjunct : set.integerRelations)
51     unionInPlace(disjunct);
52 }
53 
54 /// Return the union of this set and the given set.
55 PresburgerRelation
56 PresburgerRelation::unionSet(const PresburgerRelation &set) const {
57   assert(PresburgerSpace::isEqual(set) && "Spaces should match");
58   PresburgerRelation result = *this;
59   result.unionInPlace(set);
60   return result;
61 }
62 
63 /// A point is contained in the union iff any of the parts contain the point.
64 bool PresburgerRelation::containsPoint(ArrayRef<int64_t> point) const {
65   return llvm::any_of(integerRelations, [&](const IntegerRelation &disjunct) {
66     return (disjunct.containsPoint(point));
67   });
68 }
69 
70 PresburgerRelation PresburgerRelation::getUniverse(unsigned numDomain,
71                                                    unsigned numRange,
72                                                    unsigned numSymbols) {
73   PresburgerRelation result(numDomain, numRange, numSymbols);
74   result.unionInPlace(
75       IntegerRelation::getUniverse(numDomain, numRange, numSymbols));
76   return result;
77 }
78 
79 PresburgerRelation PresburgerRelation::getEmpty(unsigned numDomain,
80                                                 unsigned numRange,
81                                                 unsigned numSymbols) {
82   return PresburgerRelation(numDomain, numRange, numSymbols);
83 }
84 
85 // Return the intersection of this set with the given set.
86 //
87 // We directly compute (S_1 or S_2 ...) and (T_1 or T_2 ...)
88 // as (S_1 and T_1) or (S_1 and T_2) or ...
89 //
90 // If S_i or T_j have local variables, then S_i and T_j contains the local
91 // variables of both.
92 PresburgerRelation
93 PresburgerRelation::intersect(const PresburgerRelation &set) const {
94   assert(PresburgerSpace::isEqual(set) && "Spaces should match");
95 
96   PresburgerRelation result(getNumDomainIds(), getNumRangeIds(),
97                             getNumSymbolIds());
98   for (const IntegerRelation &csA : integerRelations) {
99     for (const IntegerRelation &csB : set.integerRelations) {
100       IntegerRelation csACopy = csA, csBCopy = csB;
101       csACopy.mergeLocalIds(csBCopy);
102       csACopy.append(csBCopy);
103       if (!csACopy.isEmpty())
104         result.unionInPlace(csACopy);
105     }
106   }
107   return result;
108 }
109 
110 /// Return `coeffs` with all the elements negated.
111 static SmallVector<int64_t, 8> getNegatedCoeffs(ArrayRef<int64_t> coeffs) {
112   SmallVector<int64_t, 8> negatedCoeffs;
113   negatedCoeffs.reserve(coeffs.size());
114   for (int64_t coeff : coeffs)
115     negatedCoeffs.emplace_back(-coeff);
116   return negatedCoeffs;
117 }
118 
119 /// Return the complement of the given inequality.
120 ///
121 /// The complement of a_1 x_1 + ... + a_n x_ + c >= 0 is
122 /// a_1 x_1 + ... + a_n x_ + c < 0, i.e., -a_1 x_1 - ... - a_n x_ - c - 1 >= 0,
123 /// since all the variables are constrained to be integers.
124 static SmallVector<int64_t, 8> getComplementIneq(ArrayRef<int64_t> ineq) {
125   SmallVector<int64_t, 8> coeffs;
126   coeffs.reserve(ineq.size());
127   for (int64_t coeff : ineq)
128     coeffs.emplace_back(-coeff);
129   --coeffs.back();
130   return coeffs;
131 }
132 
133 /// Return the set difference b \ s and accumulate the result into `result`.
134 /// `simplex` must correspond to b.
135 ///
136 /// In the following, U denotes union, ^ denotes intersection, \ denotes set
137 /// difference and ~ denotes complement.
138 /// Let b be the IntegerRelation and s = (U_i s_i) be the set. We want
139 /// b \ (U_i s_i).
140 ///
141 /// Let s_i = ^_j s_ij, where each s_ij is a single inequality. To compute
142 /// b \ s_i = b ^ ~s_i, we partition s_i based on the first violated inequality:
143 /// ~s_i = (~s_i1) U (s_i1 ^ ~s_i2) U (s_i1 ^ s_i2 ^ ~s_i3) U ...
144 /// And the required result is (b ^ ~s_i1) U (b ^ s_i1 ^ ~s_i2) U ...
145 /// We recurse by subtracting U_{j > i} S_j from each of these parts and
146 /// returning the union of the results. Each equality is handled as a
147 /// conjunction of two inequalities.
148 ///
149 /// Note that the same approach works even if an inequality involves a floor
150 /// division. For example, the complement of x <= 7*floor(x/7) is still
151 /// x > 7*floor(x/7). Since b \ s_i contains the inequalities of both b and s_i
152 /// (or the complements of those inequalities), b \ s_i may contain the
153 /// divisions present in both b and s_i. Therefore, we need to add the local
154 /// division variables of both b and s_i to each part in the result. This means
155 /// adding the local variables of both b and s_i, as well as the corresponding
156 /// division inequalities to each part. Since the division inequalities are
157 /// added to each part, we can skip the parts where the complement of any
158 /// division inequality is added, as these parts will become empty anyway.
159 ///
160 /// As a heuristic, we try adding all the constraints and check if simplex
161 /// says that the intersection is empty. If it is, then subtracting this
162 /// disjuncts is a no-op and we just skip it. Also, in the process we find out
163 /// that some constraints are redundant. These redundant constraints are
164 /// ignored.
165 ///
166 /// b and simplex are callee saved, i.e., their values on return are
167 /// semantically equivalent to their values when the function is called.
168 static void subtractRecursively(IntegerRelation &b, Simplex &simplex,
169                                 const PresburgerRelation &s, unsigned i,
170                                 PresburgerRelation &result) {
171   if (i == s.getNumDisjuncts()) {
172     result.unionInPlace(b);
173     return;
174   }
175   IntegerRelation sI = s.getDisjunct(i);
176 
177   // Below, we append some additional constraints and ids to b. We want to
178   // rollback b to its initial state before returning, which we will do by
179   // removing all constraints beyond the original number of inequalities
180   // and equalities, so we store these counts first.
181   const unsigned bInitNumIneqs = b.getNumInequalities();
182   const unsigned bInitNumEqs = b.getNumEqualities();
183   const unsigned bInitNumLocals = b.getNumLocalIds();
184   // Similarly, we also want to rollback simplex to its original state.
185   const unsigned initialSnapshot = simplex.getSnapshot();
186 
187   auto restoreState = [&]() {
188     b.removeIdRange(IdKind::Local, bInitNumLocals, b.getNumLocalIds());
189     b.removeInequalityRange(bInitNumIneqs, b.getNumInequalities());
190     b.removeEqualityRange(bInitNumEqs, b.getNumEqualities());
191     simplex.rollback(initialSnapshot);
192   };
193 
194   // Automatically restore the original state when we return.
195   auto stateRestorer = llvm::make_scope_exit(restoreState);
196 
197   // Find out which inequalities of sI correspond to division inequalities for
198   // the local variables of sI.
199   std::vector<MaybeLocalRepr> repr(sI.getNumLocalIds());
200   sI.getLocalReprs(repr);
201 
202   // Add sI's locals to b, after b's locals. Also add b's locals to sI, before
203   // sI's locals.
204   b.mergeLocalIds(sI);
205 
206   // Mark which inequalities of sI are division inequalities and add all such
207   // inequalities to b.
208   llvm::SmallBitVector isDivInequality(sI.getNumInequalities());
209   for (MaybeLocalRepr &maybeInequality : repr) {
210     assert(maybeInequality.kind == ReprKind::Inequality &&
211            "Subtraction is not supported when a representation of the local "
212            "variables of the subtrahend cannot be found!");
213     auto lb = maybeInequality.repr.inequalityPair.lowerBoundIdx;
214     auto ub = maybeInequality.repr.inequalityPair.upperBoundIdx;
215 
216     b.addInequality(sI.getInequality(lb));
217     b.addInequality(sI.getInequality(ub));
218 
219     assert(lb != ub &&
220            "Upper and lower bounds must be different inequalities!");
221     isDivInequality[lb] = true;
222     isDivInequality[ub] = true;
223   }
224 
225   unsigned offset = simplex.getNumConstraints();
226   unsigned numLocalsAdded = b.getNumLocalIds() - bInitNumLocals;
227   simplex.appendVariable(numLocalsAdded);
228 
229   unsigned snapshotBeforeIntersect = simplex.getSnapshot();
230   simplex.intersectIntegerRelation(sI);
231 
232   if (simplex.isEmpty()) {
233     // b ^ s_i is empty, so b \ s_i = b. We move directly to i + 1.
234     // We are ignoring level i completely, so we restore the state
235     // *before* going to level i + 1.
236     restoreState();
237     subtractRecursively(b, simplex, s, i + 1, result);
238 
239     // We already restored the state above and the recursive call should have
240     // restored to the same state before returning, so we don't need to restore
241     // the state again.
242     stateRestorer.release();
243     return;
244   }
245 
246   simplex.detectRedundant();
247 
248   // Equalities are added to simplex as a pair of inequalities.
249   unsigned totalNewSimplexInequalities =
250       2 * sI.getNumEqualities() + sI.getNumInequalities();
251   llvm::SmallBitVector isMarkedRedundant(totalNewSimplexInequalities);
252   for (unsigned j = 0; j < totalNewSimplexInequalities; j++)
253     isMarkedRedundant[j] = simplex.isMarkedRedundant(offset + j);
254 
255   simplex.rollback(snapshotBeforeIntersect);
256 
257   // Recurse with the part b ^ ~ineq. Note that b is modified throughout
258   // subtractRecursively. At the time this function is called, the current b is
259   // actually equal to b ^ s_i1 ^ s_i2 ^ ... ^ s_ij, and ineq is the next
260   // inequality, s_{i,j+1}. This function recurses into the next level i + 1
261   // with the part b ^ s_i1 ^ s_i2 ^ ... ^ s_ij ^ ~s_{i,j+1}.
262   auto recurseWithInequality = [&, i](ArrayRef<int64_t> ineq) {
263     size_t snapshot = simplex.getSnapshot();
264     b.addInequality(ineq);
265     simplex.addInequality(ineq);
266     subtractRecursively(b, simplex, s, i + 1, result);
267     b.removeInequality(b.getNumInequalities() - 1);
268     simplex.rollback(snapshot);
269   };
270 
271   // For each inequality ineq, we first recurse with the part where ineq
272   // is not satisfied, and then add the ineq to b and simplex because
273   // ineq must be satisfied by all later parts.
274   auto processInequality = [&](ArrayRef<int64_t> ineq) {
275     recurseWithInequality(getComplementIneq(ineq));
276     b.addInequality(ineq);
277     simplex.addInequality(ineq);
278   };
279 
280   // Process all the inequalities, ignoring redundant inequalities and division
281   // inequalities. The result is correct whether or not we ignore these, but
282   // ignoring them makes the result simpler.
283   for (unsigned j = 0, e = sI.getNumInequalities(); j < e; j++) {
284     if (isMarkedRedundant[j])
285       continue;
286     if (isDivInequality[j])
287       continue;
288     processInequality(sI.getInequality(j));
289   }
290 
291   offset = sI.getNumInequalities();
292   for (unsigned j = 0, e = sI.getNumEqualities(); j < e; ++j) {
293     ArrayRef<int64_t> coeffs = sI.getEquality(j);
294     // For each equality, process the positive and negative inequalities that
295     // make up this equality. If Simplex found an inequality to be redundant, we
296     // skip it as above to make the result simpler. Divisions are always
297     // represented in terms of inequalities and not equalities, so we do not
298     // check for division inequalities here.
299     if (!isMarkedRedundant[offset + 2 * j])
300       processInequality(coeffs);
301     if (!isMarkedRedundant[offset + 2 * j + 1])
302       processInequality(getNegatedCoeffs(coeffs));
303   }
304 }
305 
306 /// Return the set difference disjunct \ set.
307 ///
308 /// The disjunct here is modified in subtractRecursively, so it cannot be a
309 /// const reference even though it is restored to its original state before
310 /// returning from that function.
311 static PresburgerRelation getSetDifference(IntegerRelation disjunct,
312                                            const PresburgerRelation &set) {
313   assert(disjunct.PresburgerSpace::isEqual(set) && "Spaces should match");
314   if (disjunct.isEmptyByGCDTest())
315     return PresburgerRelation::getEmpty(disjunct.getNumDomainIds(),
316                                         disjunct.getNumRangeIds(),
317                                         disjunct.getNumSymbolIds());
318 
319   PresburgerRelation result = PresburgerRelation::getEmpty(
320       disjunct.getNumDomainIds(), disjunct.getNumRangeIds(),
321       disjunct.getNumSymbolIds());
322   Simplex simplex(disjunct);
323   subtractRecursively(disjunct, simplex, set, 0, result);
324   return result;
325 }
326 
327 /// Return the complement of this set.
328 PresburgerRelation PresburgerRelation::complement() const {
329   return getSetDifference(IntegerRelation::getUniverse(getNumDomainIds(),
330                                                        getNumRangeIds(),
331                                                        getNumSymbolIds()),
332                           *this);
333 }
334 
335 /// Return the result of subtract the given set from this set, i.e.,
336 /// return `this \ set`.
337 PresburgerRelation
338 PresburgerRelation::subtract(const PresburgerRelation &set) const {
339   assert(PresburgerSpace::isEqual(set) && "Spaces should match");
340   PresburgerRelation result(getNumDomainIds(), getNumRangeIds(),
341                             getNumSymbolIds());
342   // We compute (U_i t_i) \ (U_i set_i) as U_i (t_i \ V_i set_i).
343   for (const IntegerRelation &disjunct : integerRelations)
344     result.unionInPlace(getSetDifference(disjunct, set));
345   return result;
346 }
347 
348 /// T is a subset of S iff T \ S is empty, since if T \ S contains a
349 /// point then this is a point that is contained in T but not S, and
350 /// if T contains a point that is not in S, this also lies in T \ S.
351 bool PresburgerRelation::isSubsetOf(const PresburgerRelation &set) const {
352   return this->subtract(set).isIntegerEmpty();
353 }
354 
355 /// Two sets are equal iff they are subsets of each other.
356 bool PresburgerRelation::isEqual(const PresburgerRelation &set) const {
357   assert(PresburgerSpace::isEqual(set) && "Spaces should match");
358   return this->isSubsetOf(set) && set.isSubsetOf(*this);
359 }
360 
361 /// Return true if all the sets in the union are known to be integer empty,
362 /// false otherwise.
363 bool PresburgerRelation::isIntegerEmpty() const {
364   // The set is empty iff all of the disjuncts are empty.
365   return std::all_of(integerRelations.begin(), integerRelations.end(),
366                      [](const IntegerRelation &disjunct) {
367                        return disjunct.isIntegerEmpty();
368                      });
369 }
370 
371 bool PresburgerRelation::findIntegerSample(SmallVectorImpl<int64_t> &sample) {
372   // A sample exists iff any of the disjuncts contains a sample.
373   for (const IntegerRelation &disjunct : integerRelations) {
374     if (Optional<SmallVector<int64_t, 8>> opt = disjunct.findIntegerSample()) {
375       sample = std::move(*opt);
376       return true;
377     }
378   }
379   return false;
380 }
381 
382 Optional<uint64_t> PresburgerRelation::computeVolume() const {
383   assert(getNumSymbolIds() == 0 && "Symbols are not yet supported!");
384   // The sum of the volumes of the disjuncts is a valid overapproximation of the
385   // volume of their union, even if they overlap.
386   uint64_t result = 0;
387   for (const IntegerRelation &disjunct : integerRelations) {
388     Optional<uint64_t> volume = disjunct.computeVolume();
389     if (!volume)
390       return {};
391     result += *volume;
392   }
393   return result;
394 }
395 
396 /// The SetCoalescer class contains all functionality concerning the coalesce
397 /// heuristic. It is built from a `PresburgerRelation` and has the `coalesce()`
398 /// function as its main API. The coalesce heuristic simplifies the
399 /// representation of a PresburgerRelation. In particular, it removes all
400 /// disjuncts which are subsets of other disjuncts in the union and it combines
401 /// sets that overlap and can be combined in a convex way.
402 class presburger::SetCoalescer {
403 
404 public:
405   /// Simplifies the representation of a PresburgerSet.
406   PresburgerRelation coalesce();
407 
408   /// Construct a SetCoalescer from a PresburgerSet.
409   SetCoalescer(const PresburgerRelation &s);
410 
411 private:
412   /// The dimensionality of the set the SetCoalescer is coalescing.
413   unsigned numDomainIds;
414   unsigned numRangeIds;
415   unsigned numSymbolIds;
416 
417   /// The current list of `IntegerRelation`s that the currently coalesced set is
418   /// the union of.
419   SmallVector<IntegerRelation, 2> disjuncts;
420   /// The list of `Simplex`s constructed from the elements of `disjuncts`.
421   SmallVector<Simplex, 2> simplices;
422 
423   /// The list of all inversed equalities during typing. This ensures that
424   /// the constraints exist even after the typing function has concluded.
425   SmallVector<SmallVector<int64_t, 2>, 2> negEqs;
426 
427   /// `redundantIneqsA` is the inequalities of `a` that are redundant for `b`
428   /// (similarly for `cuttingIneqsA`, `redundantIneqsB`, and `cuttingIneqsB`).
429   SmallVector<ArrayRef<int64_t>, 2> redundantIneqsA;
430   SmallVector<ArrayRef<int64_t>, 2> cuttingIneqsA;
431 
432   SmallVector<ArrayRef<int64_t>, 2> redundantIneqsB;
433   SmallVector<ArrayRef<int64_t>, 2> cuttingIneqsB;
434 
435   /// Given a Simplex `simp` and one of its inequalities `ineq`, check
436   /// that the facet of `simp` where `ineq` holds as an equality is contained
437   /// within `a`.
438   bool isFacetContained(ArrayRef<int64_t> ineq, Simplex &simp);
439 
440   /// Adds `disjunct` to `disjuncts` and removes the disjuncts at position `i`
441   /// and `j`. Updates `simplices` to reflect the changes. `i` and `j` cannot
442   /// be equal.
443   void addCoalescedDisjunct(unsigned i, unsigned j,
444                             const IntegerRelation &disjunct);
445 
446   /// Checks whether `a` and `b` can be combined in a convex sense, if there
447   /// exist cutting inequalities.
448   ///
449   /// An example of this case:
450   ///    ___________        ___________
451   ///   /   /  |   /       /          /
452   ///   \   \  |  /   ==>  \         /
453   ///    \   \ | /          \       /
454   ///     \___\|/            \_____/
455   ///
456   ///
457   LogicalResult coalescePairCutCase(unsigned i, unsigned j);
458 
459   /// Types the inequality `ineq` according to its `IneqType` for `simp` into
460   /// `redundantIneqsB` and `cuttingIneqsB`. Returns success, if no separate
461   /// inequalities were encountered. Otherwise, returns failure.
462   LogicalResult typeInequality(ArrayRef<int64_t> ineq, Simplex &simp);
463 
464   /// Types the equality `eq`, i.e. for `eq` == 0, types both `eq` >= 0 and
465   /// -`eq` >= 0 according to their `IneqType` for `simp` into
466   /// `redundantIneqsB` and `cuttingIneqsB`. Returns success, if no separate
467   /// inequalities were encountered. Otherwise, returns failure.
468   LogicalResult typeEquality(ArrayRef<int64_t> eq, Simplex &simp);
469 
470   /// Replaces the element at position `i` with the last element and erases
471   /// the last element for both `disjuncts` and `simplices`.
472   void eraseDisjunct(unsigned i);
473 
474   /// Attempts to coalesce the two IntegerRelations at position `i` and `j`
475   /// in `disjuncts` in-place. Returns whether the disjuncts were
476   /// successfully coalesced. The simplices in `simplices` need to be the ones
477   /// constructed from `disjuncts`. At this point, there are no empty
478   /// disjuncts in `disjuncts` left.
479   LogicalResult coalescePair(unsigned i, unsigned j);
480 };
481 
482 /// Constructs a `SetCoalescer` from a `PresburgerRelation`. Only adds non-empty
483 /// `IntegerRelation`s to the `disjuncts` vector.
484 SetCoalescer::SetCoalescer(const PresburgerRelation &s) {
485 
486   disjuncts = s.integerRelations;
487 
488   simplices.reserve(s.getNumDisjuncts());
489   // Note that disjuncts.size() changes during the loop.
490   for (unsigned i = 0; i < disjuncts.size();) {
491     Simplex simp(disjuncts[i]);
492     if (simp.isEmpty()) {
493       disjuncts[i] = disjuncts[disjuncts.size() - 1];
494       disjuncts.pop_back();
495       continue;
496     }
497     ++i;
498     simplices.push_back(simp);
499   }
500   numDomainIds = s.getNumDomainIds();
501   numRangeIds = s.getNumRangeIds();
502   numSymbolIds = s.getNumSymbolIds();
503 }
504 
505 /// Simplifies the representation of a PresburgerSet.
506 PresburgerRelation SetCoalescer::coalesce() {
507   // For all tuples of IntegerRelations, check whether they can be
508   // coalesced. When coalescing is successful, the contained IntegerRelation
509   // is swapped with the last element of `disjuncts` and subsequently erased
510   // and similarly for simplices.
511   for (unsigned i = 0; i < disjuncts.size();) {
512 
513     // TODO: This does some comparisons two times (index 0 with 1 and index 1
514     // with 0).
515     bool broken = false;
516     for (unsigned j = 0, e = disjuncts.size(); j < e; ++j) {
517       negEqs.clear();
518       redundantIneqsA.clear();
519       redundantIneqsB.clear();
520       cuttingIneqsA.clear();
521       cuttingIneqsB.clear();
522       if (i == j)
523         continue;
524       if (coalescePair(i, j).succeeded()) {
525         broken = true;
526         break;
527       }
528     }
529 
530     // Only if the inner loop was not broken, i is incremented. This is
531     // required as otherwise, if a coalescing occurs, the IntegerRelation
532     // now at position i is not compared.
533     if (!broken)
534       ++i;
535   }
536 
537   PresburgerRelation newSet =
538       PresburgerRelation::getEmpty(numDomainIds, numRangeIds, numSymbolIds);
539   for (unsigned i = 0, e = disjuncts.size(); i < e; ++i)
540     newSet.unionInPlace(disjuncts[i]);
541 
542   return newSet;
543 }
544 
545 /// Given a Simplex `simp` and one of its inequalities `ineq`, check
546 /// that all inequalities of `cuttingIneqsB` are redundant for the facet of
547 /// `simp` where `ineq` holds as an equality is contained within `a`.
548 bool SetCoalescer::isFacetContained(ArrayRef<int64_t> ineq, Simplex &simp) {
549   unsigned snapshot = simp.getSnapshot();
550   simp.addEquality(ineq);
551   if (llvm::any_of(cuttingIneqsB, [&simp](ArrayRef<int64_t> curr) {
552         return !simp.isRedundantInequality(curr);
553       })) {
554     simp.rollback(snapshot);
555     return false;
556   }
557   simp.rollback(snapshot);
558   return true;
559 }
560 
561 void SetCoalescer::addCoalescedDisjunct(unsigned i, unsigned j,
562                                         const IntegerRelation &disjunct) {
563   assert(i != j && "The indices must refer to different disjuncts");
564   unsigned n = disjuncts.size();
565   if (j == n - 1) {
566     // This case needs special handling since position `n` - 1 is removed
567     // from the vector, hence the `IntegerRelation` at position `n` - 2 is
568     // lost otherwise.
569     disjuncts[i] = disjuncts[n - 2];
570     disjuncts.pop_back();
571     disjuncts[n - 2] = disjunct;
572 
573     simplices[i] = simplices[n - 2];
574     simplices.pop_back();
575     simplices[n - 2] = Simplex(disjunct);
576 
577   } else {
578     // Other possible edge cases are correct since for `j` or `i` == `n` -
579     // 2, the `IntegerRelation` at position `n` - 2 should be lost. The
580     // case `i` == `n` - 1 makes the first following statement a noop.
581     // Hence, in this case the same thing is done as above, but with `j`
582     // rather than `i`.
583     disjuncts[i] = disjuncts[n - 1];
584     disjuncts[j] = disjuncts[n - 2];
585     disjuncts.pop_back();
586     disjuncts[n - 2] = disjunct;
587 
588     simplices[i] = simplices[n - 1];
589     simplices[j] = simplices[n - 2];
590     simplices.pop_back();
591     simplices[n - 2] = Simplex(disjunct);
592   }
593 }
594 
595 /// Given two polyhedra `a` and `b` at positions `i` and `j` in
596 /// `disjuncts` and `redundantIneqsA` being the inequalities of `a` that
597 /// are redundant for `b` (similarly for `cuttingIneqsA`, `redundantIneqsB`,
598 /// and `cuttingIneqsB`), Checks whether the facets of all cutting
599 /// inequalites of `a` are contained in `b`. If so, a new polyhedron
600 /// consisting of all redundant inequalites of `a` and `b` and all
601 /// equalities of both is created.
602 ///
603 /// An example of this case:
604 ///    ___________        ___________
605 ///   /   /  |   /       /          /
606 ///   \   \  |  /   ==>  \         /
607 ///    \   \ | /          \       /
608 ///     \___\|/            \_____/
609 ///
610 ///
611 LogicalResult SetCoalescer::coalescePairCutCase(unsigned i, unsigned j) {
612   /// All inequalities of `b` need to be redundant. We already know that the
613   /// redundant ones are, so only the cutting ones remain to be checked.
614   Simplex &simp = simplices[i];
615   IntegerRelation &disjunct = disjuncts[i];
616   if (llvm::any_of(cuttingIneqsA, [this, &simp](ArrayRef<int64_t> curr) {
617         return !isFacetContained(curr, simp);
618       }))
619     return failure();
620   IntegerRelation newSet(disjunct.getNumDomainIds(), disjunct.getNumRangeIds(),
621                          disjunct.getNumSymbolIds(), disjunct.getNumLocalIds());
622 
623   for (ArrayRef<int64_t> curr : redundantIneqsA)
624     newSet.addInequality(curr);
625 
626   for (ArrayRef<int64_t> curr : redundantIneqsB)
627     newSet.addInequality(curr);
628 
629   addCoalescedDisjunct(i, j, newSet);
630   return success();
631 }
632 
633 LogicalResult SetCoalescer::typeInequality(ArrayRef<int64_t> ineq,
634                                            Simplex &simp) {
635   Simplex::IneqType type = simp.findIneqType(ineq);
636   if (type == Simplex::IneqType::Redundant)
637     redundantIneqsB.push_back(ineq);
638   else if (type == Simplex::IneqType::Cut)
639     cuttingIneqsB.push_back(ineq);
640   else
641     return failure();
642   return success();
643 }
644 
645 LogicalResult SetCoalescer::typeEquality(ArrayRef<int64_t> eq, Simplex &simp) {
646   if (typeInequality(eq, simp).failed())
647     return failure();
648   negEqs.push_back(getNegatedCoeffs(eq));
649   ArrayRef<int64_t> inv(negEqs.back());
650   if (typeInequality(inv, simp).failed())
651     return failure();
652   return success();
653 }
654 
655 void SetCoalescer::eraseDisjunct(unsigned i) {
656   assert(simplices.size() == disjuncts.size() &&
657          "simplices and disjuncts must be equally as long");
658   disjuncts[i] = disjuncts.back();
659   disjuncts.pop_back();
660   simplices[i] = simplices.back();
661   simplices.pop_back();
662 }
663 
664 LogicalResult SetCoalescer::coalescePair(unsigned i, unsigned j) {
665 
666   IntegerRelation &a = disjuncts[i];
667   IntegerRelation &b = disjuncts[j];
668   /// Handling of local ids is not yet implemented, so these cases are
669   /// skipped.
670   /// TODO: implement local id support.
671   if (a.getNumLocalIds() != 0 || b.getNumLocalIds() != 0)
672     return failure();
673   Simplex &simpA = simplices[i];
674   Simplex &simpB = simplices[j];
675 
676   // Organize all inequalities and equalities of `a` according to their type
677   // for `b` into `redundantIneqsA` and `cuttingIneqsA` (and vice versa for
678   // all inequalities of `b` according to their type in `a`). If a separate
679   // inequality is encountered during typing, the two IntegerRelations
680   // cannot be coalesced.
681   for (int k = 0, e = a.getNumInequalities(); k < e; ++k)
682     if (typeInequality(a.getInequality(k), simpB).failed())
683       return failure();
684 
685   for (int k = 0, e = a.getNumEqualities(); k < e; ++k)
686     if (typeEquality(a.getEquality(k), simpB).failed())
687       return failure();
688 
689   std::swap(redundantIneqsA, redundantIneqsB);
690   std::swap(cuttingIneqsA, cuttingIneqsB);
691 
692   for (int k = 0, e = b.getNumInequalities(); k < e; ++k)
693     if (typeInequality(b.getInequality(k), simpA).failed())
694       return failure();
695 
696   for (int k = 0, e = b.getNumEqualities(); k < e; ++k)
697     if (typeEquality(b.getEquality(k), simpA).failed())
698       return failure();
699 
700   // If there are no cutting inequalities of `a`, `b` is contained
701   // within `a`.
702   if (cuttingIneqsA.empty()) {
703     eraseDisjunct(j);
704     return success();
705   }
706 
707   // Try to apply the cut case
708   if (coalescePairCutCase(i, j).succeeded())
709     return success();
710 
711   // Swap the vectors to compare the pair (j,i) instead of (i,j).
712   std::swap(redundantIneqsA, redundantIneqsB);
713   std::swap(cuttingIneqsA, cuttingIneqsB);
714 
715   // If there are no cutting inequalities of `a`, `b` is contained
716   // within `a`.
717   if (cuttingIneqsA.empty()) {
718     eraseDisjunct(i);
719     return success();
720   }
721 
722   // Try to apply the cut case
723   if (coalescePairCutCase(j, i).succeeded())
724     return success();
725 
726   return failure();
727 }
728 
729 PresburgerRelation PresburgerRelation::coalesce() const {
730   return SetCoalescer(*this).coalesce();
731 }
732 
733 void PresburgerRelation::print(raw_ostream &os) const {
734   os << "Number of Disjuncts: " << getNumDisjuncts() << "\n";
735   for (const IntegerRelation &disjunct : integerRelations) {
736     disjunct.print(os);
737     os << '\n';
738   }
739 }
740 
741 void PresburgerRelation::dump() const { print(llvm::errs()); }
742 
743 PresburgerSet PresburgerSet::getUniverse(unsigned numDims,
744                                          unsigned numSymbols) {
745   PresburgerSet result(numDims, numSymbols);
746   result.unionInPlace(IntegerPolyhedron::getUniverse(numDims, numSymbols));
747   return result;
748 }
749 
750 PresburgerSet PresburgerSet::getEmpty(unsigned numDims, unsigned numSymbols) {
751   return PresburgerSet(numDims, numSymbols);
752 }
753 
754 PresburgerSet::PresburgerSet(const IntegerPolyhedron &disjunct)
755     : PresburgerRelation(disjunct) {}
756 
757 PresburgerSet::PresburgerSet(const PresburgerRelation &set)
758     : PresburgerRelation(set) {}
759 
760 PresburgerSet PresburgerSet::unionSet(const PresburgerRelation &set) const {
761   return PresburgerSet(PresburgerRelation::unionSet(set));
762 }
763 
764 PresburgerSet PresburgerSet::intersect(const PresburgerRelation &set) const {
765   return PresburgerSet(PresburgerRelation::intersect(set));
766 }
767 
768 PresburgerSet PresburgerSet::complement() const {
769   return PresburgerSet(PresburgerRelation::complement());
770 }
771 
772 PresburgerSet PresburgerSet::subtract(const PresburgerRelation &set) const {
773   return PresburgerSet(PresburgerRelation::subtract(set));
774 }
775 
776 PresburgerSet PresburgerSet::coalesce() const {
777   return PresburgerSet(PresburgerRelation::coalesce());
778 }
779