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