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