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 /// Given an IntegerRelation `p` and one of its inequalities `ineq`, check
397 /// that all inequalities of `cuttingIneqs` are redundant for the facet of `p`
398 /// where `ineq` holds as an equality. `simp` must be the Simplex constructed
399 /// from `p`.
400 static bool isFacetContained(ArrayRef<int64_t> ineq, Simplex &simp,
401                              IntegerRelation &p,
402                              ArrayRef<ArrayRef<int64_t>> cuttingIneqs) {
403   unsigned snapshot = simp.getSnapshot();
404   simp.addEquality(ineq);
405   if (llvm::any_of(cuttingIneqs, [&simp](ArrayRef<int64_t> curr) {
406         return !simp.isRedundantInequality(curr);
407       })) {
408     simp.rollback(snapshot);
409     return false;
410   }
411   simp.rollback(snapshot);
412   return true;
413 }
414 
415 /// Adds `disjunct` to `disjuncts` and removes the disjuncts at position `i` and
416 /// `j`. Updates `simplices` to reflect the changes. `i` and `j` cannot be
417 /// equal.
418 static void addCoalescedDisjunct(SmallVectorImpl<IntegerRelation> &disjuncts,
419                                  unsigned i, unsigned j,
420                                  const IntegerRelation &disjunct,
421                                  SmallVectorImpl<Simplex> &simplices) {
422   assert(i != j && "The indices must refer to different disjuncts");
423 
424   unsigned n = disjuncts.size();
425   if (j == n - 1) {
426     // This case needs special handling since position `n` - 1 is removed from
427     // the vector, hence the `IntegerRelation` at position `n` - 2 is lost
428     // otherwise.
429     disjuncts[i] = disjuncts[n - 2];
430     disjuncts.pop_back();
431     disjuncts[n - 2] = disjunct;
432 
433     simplices[i] = simplices[n - 2];
434     simplices.pop_back();
435     simplices[n - 2] = Simplex(disjunct);
436 
437   } else {
438     // Other possible edge cases are correct since for `j` or `i` == `n` - 2,
439     // the `IntegerRelation` at position `n` - 2 should be lost. The case
440     // `i` == `n` - 1 makes the first following statement a noop. Hence, in this
441     // case the same thing is done as above, but with `j` rather than `i`.
442     disjuncts[i] = disjuncts[n - 1];
443     disjuncts[j] = disjuncts[n - 2];
444     disjuncts.pop_back();
445     disjuncts[n - 2] = disjunct;
446 
447     simplices[i] = simplices[n - 1];
448     simplices[j] = simplices[n - 2];
449     simplices.pop_back();
450     simplices[n - 2] = Simplex(disjunct);
451   }
452 }
453 
454 /// Given two disjuncts `a` and `b` at positions `i` and `j` in `disjuncts`
455 /// and `redundantIneqsA` being the inequalities of `a` that are redundant for
456 /// `b` (similarly for `cuttingIneqsA`, `redundantIneqsB`, and `cuttingIneqsB`),
457 /// checks whether the facets of all cutting inequalites of `a` are contained in
458 /// `b`. If so, a new disjunct consisting of all redundant inequalites of `a`
459 /// and `b` and all equalities of both is created.
460 ///
461 /// An example of this case:
462 ///    ___________        ___________
463 ///   /   /  |   /       /          /
464 ///   \   \  |  /   ==>  \         /
465 ///    \   \ | /          \       /
466 ///     \___\|/            \_____/
467 ///
468 ///
469 static LogicalResult
470 coalescePairCutCase(SmallVectorImpl<IntegerRelation> &disjuncts,
471                     SmallVectorImpl<Simplex> &simplices, unsigned i, unsigned j,
472                     ArrayRef<ArrayRef<int64_t>> redundantIneqsA,
473                     ArrayRef<ArrayRef<int64_t>> cuttingIneqsA,
474                     ArrayRef<ArrayRef<int64_t>> redundantIneqsB,
475                     ArrayRef<ArrayRef<int64_t>> cuttingIneqsB) {
476   /// All inequalities of `b` need to be redundant. We already know that the
477   /// redundant ones are, so only the cutting ones remain to be checked.
478   Simplex &simp = simplices[i];
479   IntegerRelation &disjunct = disjuncts[i];
480   if (llvm::any_of(cuttingIneqsA, [&simp, &disjunct,
481                                    &cuttingIneqsB](ArrayRef<int64_t> curr) {
482         return !isFacetContained(curr, simp, disjunct, cuttingIneqsB);
483       }))
484     return failure();
485   IntegerRelation newSet(disjunct.getNumDomainIds(), disjunct.getNumRangeIds(),
486                          disjunct.getNumSymbolIds(), disjunct.getNumLocalIds());
487 
488   for (ArrayRef<int64_t> curr : redundantIneqsA)
489     newSet.addInequality(curr);
490 
491   for (ArrayRef<int64_t> curr : redundantIneqsB)
492     newSet.addInequality(curr);
493 
494   addCoalescedDisjunct(disjuncts, i, j, newSet, simplices);
495   return success();
496 }
497 
498 /// Types the inequality `ineq` according to its `IneqType` for `simp` into
499 /// `redundantIneqs` and `cuttingIneqs`. Returns success, if no separate
500 /// inequalities were encountered. Otherwise, returns failure.
501 static LogicalResult
502 typeInequality(ArrayRef<int64_t> ineq, Simplex &simp,
503                SmallVectorImpl<ArrayRef<int64_t>> &redundantIneqs,
504                SmallVectorImpl<ArrayRef<int64_t>> &cuttingIneqs) {
505   Simplex::IneqType type = simp.findIneqType(ineq);
506   if (type == Simplex::IneqType::Redundant)
507     redundantIneqs.push_back(ineq);
508   else if (type == Simplex::IneqType::Cut)
509     cuttingIneqs.push_back(ineq);
510   else
511     return failure();
512   return success();
513 }
514 
515 /// Types the equality `eq`, i.e. for `eq` == 0, types both `eq` >= 0 and -`eq`
516 /// >= 0 according to their `IneqType` for `simp` into `redundantIneqs` and
517 /// `cuttingIneqs`. Returns success, if no separate inequalities were
518 /// encountered. Otherwise, returns failure.
519 static LogicalResult
520 typeEquality(ArrayRef<int64_t> eq, Simplex &simp,
521              SmallVectorImpl<ArrayRef<int64_t>> &redundantIneqs,
522              SmallVectorImpl<ArrayRef<int64_t>> &cuttingIneqs,
523              SmallVectorImpl<SmallVector<int64_t, 2>> &negEqs) {
524   if (typeInequality(eq, simp, redundantIneqs, cuttingIneqs).failed())
525     return failure();
526   negEqs.push_back(getNegatedCoeffs(eq));
527   ArrayRef<int64_t> inv(negEqs.back());
528   if (typeInequality(inv, simp, redundantIneqs, cuttingIneqs).failed())
529     return failure();
530   return success();
531 }
532 
533 /// Replaces the element at position `i` with the last element and erases the
534 /// last element for both `disjuncts` and `simplices`.
535 static void eraseDisjunct(unsigned i,
536                           SmallVectorImpl<IntegerRelation> &disjuncts,
537                           SmallVectorImpl<Simplex> &simplices) {
538   assert(simplices.size() == disjuncts.size() &&
539          "simplices and disjuncts must be equally as long");
540   disjuncts[i] = disjuncts.back();
541   disjuncts.pop_back();
542   simplices[i] = simplices.back();
543   simplices.pop_back();
544 }
545 
546 /// Attempts to coalesce the two IntegerRelations at position `i` and `j` in
547 /// `disjuncts` in-place. Returns whether the disjuncts were successfully
548 /// coalesced. The simplices in `simplices` need to be the ones constructed from
549 /// `disjuncts`. At this point, there are no empty disjuncts in
550 /// `disjuncts` left.
551 static LogicalResult coalescePair(unsigned i, unsigned j,
552                                   SmallVectorImpl<IntegerRelation> &disjuncts,
553                                   SmallVectorImpl<Simplex> &simplices) {
554 
555   IntegerRelation &a = disjuncts[i];
556   IntegerRelation &b = disjuncts[j];
557   /// Handling of local ids is not yet implemented, so these cases are skipped.
558   /// TODO: implement local id support.
559   if (a.getNumLocalIds() != 0 || b.getNumLocalIds() != 0)
560     return failure();
561   Simplex &simpA = simplices[i];
562   Simplex &simpB = simplices[j];
563 
564   SmallVector<ArrayRef<int64_t>, 2> redundantIneqsA;
565   SmallVector<ArrayRef<int64_t>, 2> cuttingIneqsA;
566   SmallVector<SmallVector<int64_t, 2>, 2> negEqs;
567 
568   // Organize all inequalities and equalities of `a` according to their type for
569   // `b` into `redundantIneqsA` and `cuttingIneqsA` (and vice versa for all
570   // inequalities of `b` according to their type in `a`). If a separate
571   // inequality is encountered during typing, the two IntegerRelations cannot
572   // be coalesced.
573   for (int k = 0, e = a.getNumInequalities(); k < e; ++k)
574     if (typeInequality(a.getInequality(k), simpB, redundantIneqsA,
575                        cuttingIneqsA)
576             .failed())
577       return failure();
578 
579   for (int k = 0, e = a.getNumEqualities(); k < e; ++k)
580     if (typeEquality(a.getEquality(k), simpB, redundantIneqsA, cuttingIneqsA,
581                      negEqs)
582             .failed())
583       return failure();
584 
585   SmallVector<ArrayRef<int64_t>, 2> redundantIneqsB;
586   SmallVector<ArrayRef<int64_t>, 2> cuttingIneqsB;
587   for (int k = 0, e = b.getNumInequalities(); k < e; ++k)
588     if (typeInequality(b.getInequality(k), simpA, redundantIneqsB,
589                        cuttingIneqsB)
590             .failed())
591       return failure();
592 
593   for (int k = 0, e = b.getNumEqualities(); k < e; ++k)
594     if (typeEquality(b.getEquality(k), simpA, redundantIneqsB, cuttingIneqsB,
595                      negEqs)
596             .failed())
597       return failure();
598 
599   // If there are no cutting inequalities of `a`, `b` is contained
600   // within `a` (and vice versa for `b`).
601   if (cuttingIneqsA.empty()) {
602     eraseDisjunct(j, disjuncts, simplices);
603     return success();
604   }
605 
606   if (cuttingIneqsB.empty()) {
607     eraseDisjunct(i, disjuncts, simplices);
608     return success();
609   }
610 
611   // Try to apply the cut case
612   if (coalescePairCutCase(disjuncts, simplices, i, j, redundantIneqsA,
613                           cuttingIneqsA, redundantIneqsB, cuttingIneqsB)
614           .succeeded())
615     return success();
616 
617   if (coalescePairCutCase(disjuncts, simplices, j, i, redundantIneqsB,
618                           cuttingIneqsB, redundantIneqsA, cuttingIneqsA)
619           .succeeded())
620     return success();
621 
622   return failure();
623 }
624 
625 PresburgerRelation PresburgerRelation::coalesce() const {
626   PresburgerRelation newSet = PresburgerRelation::getEmpty(
627       getNumDomainIds(), getNumRangeIds(), getNumSymbolIds());
628   SmallVector<IntegerRelation, 2> disjuncts = integerRelations;
629   SmallVector<Simplex, 2> simplices;
630 
631   simplices.reserve(getNumDisjuncts());
632   // Note that disjuncts.size() changes during the loop.
633   for (unsigned i = 0; i < disjuncts.size();) {
634     Simplex simp(disjuncts[i]);
635     if (simp.isEmpty()) {
636       disjuncts[i] = disjuncts[disjuncts.size() - 1];
637       disjuncts.pop_back();
638       continue;
639     }
640     ++i;
641     simplices.push_back(simp);
642   }
643 
644   // For all tuples of IntegerRelations, check whether they can be coalesced.
645   // When coalescing is successful, the contained IntegerRelation is swapped
646   // with the last element of `disjuncts` and subsequently erased and
647   // similarly for simplices.
648   for (unsigned i = 0; i < disjuncts.size();) {
649 
650     // TODO: This does some comparisons two times (index 0 with 1 and index 1
651     // with 0).
652     bool broken = false;
653     for (unsigned j = 0, e = disjuncts.size(); j < e; ++j) {
654       if (i == j)
655         continue;
656       if (coalescePair(i, j, disjuncts, simplices).succeeded()) {
657         broken = true;
658         break;
659       }
660     }
661 
662     // Only if the inner loop was not broken, i is incremented. This is
663     // required as otherwise, if a coalescing occurs, the IntegerRelation
664     // now at position i is not compared.
665     if (!broken)
666       ++i;
667   }
668 
669   for (unsigned i = 0, e = disjuncts.size(); i < e; ++i)
670     newSet.unionInPlace(disjuncts[i]);
671 
672   return newSet;
673 }
674 
675 void PresburgerRelation::print(raw_ostream &os) const {
676   os << "Number of Disjuncts: " << getNumDisjuncts() << "\n";
677   for (const IntegerRelation &disjunct : integerRelations) {
678     disjunct.print(os);
679     os << '\n';
680   }
681 }
682 
683 void PresburgerRelation::dump() const { print(llvm::errs()); }
684 
685 PresburgerSet PresburgerSet::getUniverse(unsigned numDims,
686                                          unsigned numSymbols) {
687   PresburgerSet result(numDims, numSymbols);
688   result.unionInPlace(IntegerPolyhedron::getUniverse(numDims, numSymbols));
689   return result;
690 }
691 
692 PresburgerSet PresburgerSet::getEmpty(unsigned numDims, unsigned numSymbols) {
693   return PresburgerSet(numDims, numSymbols);
694 }
695 
696 PresburgerSet::PresburgerSet(const IntegerPolyhedron &disjunct)
697     : PresburgerRelation(disjunct) {}
698 
699 PresburgerSet::PresburgerSet(const PresburgerRelation &set)
700     : PresburgerRelation(set) {}
701 
702 PresburgerSet PresburgerSet::unionSet(const PresburgerRelation &set) const {
703   return PresburgerSet(PresburgerRelation::unionSet(set));
704 }
705 
706 PresburgerSet PresburgerSet::intersect(const PresburgerRelation &set) const {
707   return PresburgerSet(PresburgerRelation::intersect(set));
708 }
709 
710 PresburgerSet PresburgerSet::complement() const {
711   return PresburgerSet(PresburgerRelation::complement());
712 }
713 
714 PresburgerSet PresburgerSet::subtract(const PresburgerRelation &set) const {
715   return PresburgerSet(PresburgerRelation::subtract(set));
716 }
717 
718 PresburgerSet PresburgerSet::coalesce() const {
719   return PresburgerSet(PresburgerRelation::coalesce());
720 }
721