MLIR  19.0.0git
PresburgerRelation.cpp
Go to the documentation of this file.
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 
16 #include "mlir/Support/LLVM.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SmallBitVector.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include <cassert>
23 #include <functional>
24 #include <optional>
25 #include <utility>
26 #include <vector>
27 
28 using namespace mlir;
29 using namespace presburger;
30 
32  : space(disjunct.getSpaceWithoutLocals()) {
33  unionInPlace(disjunct);
34 }
35 
37  assert(space.getNumLocalVars() == 0 && "no locals should be present");
38  space = oSpace;
39  for (IntegerRelation &disjunct : disjuncts)
40  disjunct.setSpaceExceptLocals(space);
41 }
42 
44  unsigned num) {
45  for (IntegerRelation &cs : disjuncts)
46  cs.insertVar(kind, pos, num);
47  space.insertVar(kind, pos, num);
48 }
49 
50 void PresburgerRelation::convertVarKind(VarKind srcKind, unsigned srcPos,
51  unsigned num, VarKind dstKind,
52  unsigned dstPos) {
53  assert(srcKind != VarKind::Local && dstKind != VarKind::Local &&
54  "srcKind/dstKind cannot be local");
55  assert(srcKind != dstKind && "cannot convert variables to the same kind");
56  assert(srcPos + num <= space.getNumVarKind(srcKind) &&
57  "invalid range for source variables");
58  assert(dstPos <= space.getNumVarKind(dstKind) &&
59  "invalid position for destination variables");
60 
61  space.convertVarKind(srcKind, srcPos, num, dstKind, dstPos);
62 
63  for (IntegerRelation &disjunct : disjuncts)
64  disjunct.convertVarKind(srcKind, srcPos, srcPos + num, dstKind, dstPos);
65 }
66 
68  return disjuncts.size();
69 }
70 
72  return disjuncts;
73 }
74 
75 const IntegerRelation &PresburgerRelation::getDisjunct(unsigned index) const {
76  assert(index < disjuncts.size() && "index out of bounds!");
77  return disjuncts[index];
78 }
79 
80 /// Mutate this set, turning it into the union of this set and the given
81 /// IntegerRelation.
83  assert(space.isCompatible(disjunct.getSpace()) && "Spaces should match");
84  disjuncts.push_back(disjunct);
85 }
86 
87 /// Mutate this set, turning it into the union of this set and the given set.
88 ///
89 /// This is accomplished by simply adding all the disjuncts of the given set
90 /// to this set.
92  assert(space.isCompatible(set.getSpace()) && "Spaces should match");
93 
94  if (isObviouslyEqual(set))
95  return;
96 
97  if (isObviouslyEmpty()) {
98  disjuncts = set.disjuncts;
99  return;
100  }
101  if (set.isObviouslyEmpty())
102  return;
103 
104  if (isObviouslyUniverse())
105  return;
106  if (set.isObviouslyUniverse()) {
107  disjuncts = set.disjuncts;
108  return;
109  }
110 
111  for (const IntegerRelation &disjunct : set.disjuncts)
112  unionInPlace(disjunct);
113 }
114 
115 /// Return the union of this set and the given set.
118  assert(space.isCompatible(set.getSpace()) && "Spaces should match");
119  PresburgerRelation result = *this;
120  result.unionInPlace(set);
121  return result;
122 }
123 
124 /// A point is contained in the union iff any of the parts contain the point.
126  return llvm::any_of(disjuncts, [&](const IntegerRelation &disjunct) {
127  return (disjunct.containsPointNoLocal(point));
128  });
129 }
130 
133  PresburgerRelation result(space);
135  return result;
136 }
137 
139  return PresburgerRelation(space);
140 }
141 
142 // Return the intersection of this set with the given set.
143 //
144 // We directly compute (S_1 or S_2 ...) and (T_1 or T_2 ...)
145 // as (S_1 and T_1) or (S_1 and T_2) or ...
146 //
147 // If S_i or T_j have local variables, then S_i and T_j contains the local
148 // variables of both.
151  assert(space.isCompatible(set.getSpace()) && "Spaces should match");
152 
153  // If the set is empty or the other set is universe,
154  // directly return the set
155  if (isObviouslyEmpty() || set.isObviouslyUniverse())
156  return *this;
157 
158  if (set.isObviouslyEmpty() || isObviouslyUniverse())
159  return set;
160 
161  PresburgerRelation result(getSpace());
162  for (const IntegerRelation &csA : disjuncts) {
163  for (const IntegerRelation &csB : set.disjuncts) {
164  IntegerRelation intersection = csA.intersect(csB);
165  if (!intersection.isEmpty())
166  result.unionInPlace(intersection);
167  }
168  }
169  return result;
170 }
171 
174  assert(space.getRangeSpace().isCompatible(set.getSpace()) &&
175  "Range of `this` must be compatible with range of `set`");
176 
177  PresburgerRelation other = set;
179  return intersect(other);
180 }
181 
184  assert(space.getDomainSpace().isCompatible(set.getSpace()) &&
185  "Domain of `this` must be compatible with range of `set`");
186 
187  PresburgerRelation other = set;
189  other.inverse();
190  return intersect(other);
191 }
192 
195  for (const IntegerRelation &cs : disjuncts)
196  result.unionInPlace(cs.getDomainSet());
197  return result;
198 }
199 
202  for (const IntegerRelation &cs : disjuncts)
203  result.unionInPlace(cs.getRangeSet());
204  return result;
205 }
206 
208  for (IntegerRelation &cs : disjuncts)
209  cs.inverse();
210 
211  if (getNumDisjuncts())
212  setSpace(getDisjunct(0).getSpaceWithoutLocals());
213 }
214 
216  assert(getSpace().getRangeSpace().isCompatible(
217  rel.getSpace().getDomainSpace()) &&
218  "Range of `this` should be compatible with domain of `rel`");
219 
220  PresburgerRelation result =
223  for (const IntegerRelation &csA : disjuncts) {
224  for (const IntegerRelation &csB : rel.disjuncts) {
225  IntegerRelation composition = csA;
226  composition.compose(csB);
227  if (!composition.isEmpty())
228  result.unionInPlace(composition);
229  }
230  }
231  *this = result;
232 }
233 
235  assert(getSpace().getDomainSpace().isCompatible(
236  rel.getSpace().getDomainSpace()) &&
237  "Domain of `this` should be compatible with domain of `rel`");
238 
239  inverse();
240  compose(rel);
241  inverse();
242 }
243 
245  compose(rel);
246 }
247 
249  bool isMin) {
250  SymbolicLexOpt result(rel.getSpace());
251  PWMAFunction &lexopt = result.lexopt;
252  PresburgerSet &unboundedDomain = result.unboundedDomain;
253  for (const IntegerRelation &cs : rel.getAllDisjuncts()) {
254  SymbolicLexOpt s(rel.getSpace());
255  if (isMin) {
256  s = cs.findSymbolicIntegerLexMin();
257  lexopt = lexopt.unionLexMin(s.lexopt);
258  } else {
259  s = cs.findSymbolicIntegerLexMax();
260  lexopt = lexopt.unionLexMax(s.lexopt);
261  }
262  unboundedDomain = unboundedDomain.intersect(s.unboundedDomain);
263  }
264  return result;
265 }
266 
268  return findSymbolicIntegerLexOpt(*this, true);
269 }
270 
272  return findSymbolicIntegerLexOpt(*this, false);
273 }
274 
275 /// Return the coefficients of the ineq in `rel` specified by `idx`.
276 /// `idx` can refer not only to an actual inequality of `rel`, but also
277 /// to either of the inequalities that make up an equality in `rel`.
278 ///
279 /// When 0 <= idx < rel.getNumInequalities(), this returns the coeffs of the
280 /// idx-th inequality of `rel`.
281 ///
282 /// Otherwise, it is then considered to index into the ineqs corresponding to
283 /// eqs of `rel`, and it must hold that
284 ///
285 /// 0 <= idx - rel.getNumInequalities() < 2*getNumEqualities().
286 ///
287 /// For every eq `coeffs == 0` there are two possible ineqs to index into.
288 /// The first is coeffs >= 0 and the second is coeffs <= 0.
290  unsigned idx) {
291  assert(idx < rel.getNumInequalities() + 2 * rel.getNumEqualities() &&
292  "idx out of bounds!");
293  if (idx < rel.getNumInequalities())
294  return llvm::to_vector<8>(rel.getInequality(idx));
295 
296  idx -= rel.getNumInequalities();
297  ArrayRef<MPInt> eqCoeffs = rel.getEquality(idx / 2);
298 
299  if (idx % 2 == 0)
300  return llvm::to_vector<8>(eqCoeffs);
301  return getNegatedCoeffs(eqCoeffs);
302 }
303 
305  if (hasOnlyDivLocals())
306  return *this;
307 
308  // The result is just the union of the reprs of the disjuncts.
309  PresburgerRelation result(getSpace());
310  for (const IntegerRelation &disjunct : disjuncts)
311  result.unionInPlace(disjunct.computeReprWithOnlyDivLocals());
312  return result;
313 }
314 
315 /// Return the set difference b \ s.
316 ///
317 /// In the following, U denotes union, /\ denotes intersection, \ denotes set
318 /// difference and ~ denotes complement.
319 ///
320 /// Let s = (U_i s_i). We want b \ (U_i s_i).
321 ///
322 /// Let s_i = /\_j s_ij, where each s_ij is a single inequality. To compute
323 /// b \ s_i = b /\ ~s_i, we partition s_i based on the first violated
324 /// inequality: ~s_i = (~s_i1) U (s_i1 /\ ~s_i2) U (s_i1 /\ s_i2 /\ ~s_i3) U ...
325 /// And the required result is (b /\ ~s_i1) U (b /\ s_i1 /\ ~s_i2) U ...
326 /// We recurse by subtracting U_{j > i} S_j from each of these parts and
327 /// returning the union of the results. Each equality is handled as a
328 /// conjunction of two inequalities.
329 ///
330 /// Note that the same approach works even if an inequality involves a floor
331 /// division. For example, the complement of x <= 7*floor(x/7) is still
332 /// x > 7*floor(x/7). Since b \ s_i contains the inequalities of both b and s_i
333 /// (or the complements of those inequalities), b \ s_i may contain the
334 /// divisions present in both b and s_i. Therefore, we need to add the local
335 /// division variables of both b and s_i to each part in the result. This means
336 /// adding the local variables of both b and s_i, as well as the corresponding
337 /// division inequalities to each part. Since the division inequalities are
338 /// added to each part, we can skip the parts where the complement of any
339 /// division inequality is added, as these parts will become empty anyway.
340 ///
341 /// As a heuristic, we try adding all the constraints and check if simplex
342 /// says that the intersection is empty. If it is, then subtracting this
343 /// disjuncts is a no-op and we just skip it. Also, in the process we find out
344 /// that some constraints are redundant. These redundant constraints are
345 /// ignored.
346 ///
348  const PresburgerRelation &s) {
349  assert(b.getSpace().isCompatible(s.getSpace()) && "Spaces should match");
350  if (b.isEmptyByGCDTest())
352 
353  if (!s.hasOnlyDivLocals())
355 
356  // Remove duplicate divs up front here to avoid existing
357  // divs disappearing in the call to mergeLocalVars below.
359 
360  PresburgerRelation result =
362  Simplex simplex(b);
363 
364  // This algorithm is more naturally expressed recursively, but we implement
365  // it iteratively here to avoid issues with stack sizes.
366  //
367  // Each level of the recursion has five stack variables.
368  struct Frame {
369  // A snapshot of the simplex state to rollback to.
370  unsigned simplexSnapshot;
371  // A CountsSnapshot of `b` to rollback to.
373  // The IntegerRelation currently being operated on.
374  IntegerRelation sI;
375  // A list of indexes (see getIneqCoeffsFromIdx) of inequalities to be
376  // processed.
377  SmallVector<unsigned, 8> ineqsToProcess;
378  // The index of the last inequality that was processed at this level.
379  // This is empty when we are coming to this level for the first time.
380  std::optional<unsigned> lastIneqProcessed;
381  };
382  SmallVector<Frame, 2> frames;
383 
384  // When we "recurse", we ensure the current frame is stored in `frames` and
385  // increment `level`. When we return, we decrement `level`.
386  unsigned level = 1;
387  while (level > 0) {
388  if (level - 1 >= s.getNumDisjuncts()) {
389  // No more parts to subtract; add to the result and return.
390  result.unionInPlace(b);
391  level = frames.size();
392  continue;
393  }
394 
395  if (level > frames.size()) {
396  // No frame for this level yet, so we have just recursed into this level.
397  IntegerRelation sI = s.getDisjunct(level - 1);
398  // Remove the duplicate divs up front to avoid them possibly disappearing
399  // in the call to mergeLocalVars below.
400  sI.removeDuplicateDivs();
401 
402  // Below, we append some additional constraints and ids to b. We want to
403  // rollback b to its initial state before returning, which we will do by
404  // removing all constraints beyond the original number of inequalities
405  // and equalities, so we store these counts first.
406  IntegerRelation::CountsSnapshot initBCounts = b.getCounts();
407  // Similarly, we also want to rollback simplex to its original state.
408  unsigned initialSnapshot = simplex.getSnapshot();
409 
410  // Add sI's locals to b, after b's locals. Only those locals of sI which
411  // do not already exist in b will be added. (i.e., duplicate divisions
412  // will not be added.) Also add b's locals to sI, in such a way that both
413  // have the same locals in the same order in the end.
414  b.mergeLocalVars(sI);
415 
416  // Find out which inequalities of sI correspond to division inequalities
417  // for the local variables of sI.
418  //
419  // Careful! This has to be done after the merge above; otherwise, the
420  // dividends won't contain the new ids inserted during the merge.
421  std::vector<MaybeLocalRepr> repr(sI.getNumLocalVars());
422  DivisionRepr divs = sI.getLocalReprs(&repr);
423 
424  // Mark which inequalities of sI are division inequalities and add all
425  // such inequalities to b.
426  llvm::SmallBitVector canIgnoreIneq(sI.getNumInequalities() +
427  2 * sI.getNumEqualities());
428  for (unsigned i = initBCounts.getSpace().getNumLocalVars(),
429  e = sI.getNumLocalVars();
430  i < e; ++i) {
431  assert(
432  repr[i] &&
433  "Subtraction is not supported when a representation of the local "
434  "variables of the subtrahend cannot be found!");
435 
436  if (repr[i].kind == ReprKind::Inequality) {
437  unsigned lb = repr[i].repr.inequalityPair.lowerBoundIdx;
438  unsigned ub = repr[i].repr.inequalityPair.upperBoundIdx;
439 
440  b.addInequality(sI.getInequality(lb));
441  b.addInequality(sI.getInequality(ub));
442 
443  assert(lb != ub &&
444  "Upper and lower bounds must be different inequalities!");
445  canIgnoreIneq[lb] = true;
446  canIgnoreIneq[ub] = true;
447  } else {
448  assert(repr[i].kind == ReprKind::Equality &&
449  "ReprKind isn't inequality so should be equality");
450 
451  // Consider the case (x) : (x = 3e + 1), where e is a local.
452  // Its complement is (x) : (x = 3e) or (x = 3e + 2).
453  //
454  // This can be computed by considering the set to be
455  // (x) : (x = 3*(x floordiv 3) + 1).
456  //
457  // Now there are no equalities defining divisions; the division is
458  // defined by the standard division equalities for e = x floordiv 3,
459  // i.e., 0 <= x - 3*e <= 2.
460  // So now as before, we add these division inequalities to b. The
461  // equality is now just an ordinary constraint that must be considered
462  // in the remainder of the algorithm. The division inequalities must
463  // need not be considered, same as above, and they automatically will
464  // not be because they were never a part of sI; we just infer them
465  // from the equality and add them only to b.
466  b.addInequality(
467  getDivLowerBound(divs.getDividend(i), divs.getDenom(i),
469  b.addInequality(
470  getDivUpperBound(divs.getDividend(i), divs.getDenom(i),
472  }
473  }
474 
475  unsigned offset = simplex.getNumConstraints();
476  unsigned numLocalsAdded =
477  b.getNumLocalVars() - initBCounts.getSpace().getNumLocalVars();
478  simplex.appendVariable(numLocalsAdded);
479 
480  unsigned snapshotBeforeIntersect = simplex.getSnapshot();
481  simplex.intersectIntegerRelation(sI);
482 
483  if (simplex.isEmpty()) {
484  // b /\ s_i is empty, so b \ s_i = b. We move directly to i + 1.
485  // We are ignoring level i completely, so we restore the state
486  // *before* going to the next level.
487  b.truncate(initBCounts);
488  simplex.rollback(initialSnapshot);
489  // Recurse. We haven't processed any inequalities and
490  // we don't need to process anything when we return.
491  //
492  // TODO: consider supporting tail recursion directly if this becomes
493  // relevant for performance.
494  frames.push_back(Frame{initialSnapshot, initBCounts, sI,
495  /*ineqsToProcess=*/{},
496  /*lastIneqProcessed=*/{}});
497  ++level;
498  continue;
499  }
500 
501  // Equalities are added to simplex as a pair of inequalities.
502  unsigned totalNewSimplexInequalities =
503  2 * sI.getNumEqualities() + sI.getNumInequalities();
504  // Look for redundant constraints among the constraints of sI. We don't
505  // care about redundant constraints in `b` at this point.
506  //
507  // When there are two copies of a constraint in `simplex`, i.e., among the
508  // constraints of `b` and `sI`, only one of them can be marked redundant.
509  // (Assuming no other constraint makes these redundant.)
510  //
511  // In a case where there is one copy in `b` and one in `sI`, we want the
512  // one in `sI` to be marked, not the one in `b`. Therefore, it's not
513  // enough to ignore the constraints of `b` when checking which
514  // constraints `detectRedundant` has marked redundant; we explicitly tell
515  // `detectRedundant` to only mark constraints from `sI` as being
516  // redundant.
517  simplex.detectRedundant(offset, totalNewSimplexInequalities);
518  for (unsigned j = 0; j < totalNewSimplexInequalities; j++)
519  canIgnoreIneq[j] = simplex.isMarkedRedundant(offset + j);
520  simplex.rollback(snapshotBeforeIntersect);
521 
522  SmallVector<unsigned, 8> ineqsToProcess;
523  ineqsToProcess.reserve(totalNewSimplexInequalities);
524  for (unsigned i = 0; i < totalNewSimplexInequalities; ++i)
525  if (!canIgnoreIneq[i])
526  ineqsToProcess.push_back(i);
527 
528  if (ineqsToProcess.empty()) {
529  // Nothing to process; return. (we have no frame to pop.)
530  level = frames.size();
531  continue;
532  }
533 
534  unsigned simplexSnapshot = simplex.getSnapshot();
536  frames.push_back(Frame{simplexSnapshot, bCounts, sI, ineqsToProcess,
537  /*lastIneqProcessed=*/std::nullopt});
538  // We have completed the initial setup for this level.
539  // Fallthrough to the main recursive part below.
540  }
541 
542  // For each inequality ineq, we first recurse with the part where ineq
543  // is not satisfied, and then add ineq to b and simplex because
544  // ineq must be satisfied by all later parts.
545  if (level == frames.size()) {
546  Frame &frame = frames.back();
547  if (frame.lastIneqProcessed) {
548  // Let the current value of b be b' and
549  // let the initial value of b when we first came to this level be b.
550  //
551  // b' is equal to b /\ s_i1 /\ s_i2 /\ ... /\ s_i{j-1} /\ ~s_ij.
552  // We had previously recursed with the part where s_ij was not
553  // satisfied; all further parts satisfy s_ij, so we rollback to the
554  // state before adding this complement constraint, and add s_ij to b.
555  simplex.rollback(frame.simplexSnapshot);
556  b.truncate(frame.bCounts);
557  SmallVector<MPInt, 8> ineq =
558  getIneqCoeffsFromIdx(frame.sI, *frame.lastIneqProcessed);
559  b.addInequality(ineq);
560  simplex.addInequality(ineq);
561  }
562 
563  if (frame.ineqsToProcess.empty()) {
564  // No ineqs left to process; pop this level's frame and return.
565  frames.pop_back();
566  level = frames.size();
567  continue;
568  }
569 
570  // "Recurse" with the part where the ineq is not satisfied.
571  frame.bCounts = b.getCounts();
572  frame.simplexSnapshot = simplex.getSnapshot();
573 
574  unsigned idx = frame.ineqsToProcess.back();
575  SmallVector<MPInt, 8> ineq =
576  getComplementIneq(getIneqCoeffsFromIdx(frame.sI, idx));
577  b.addInequality(ineq);
578  simplex.addInequality(ineq);
579 
580  frame.ineqsToProcess.pop_back();
581  frame.lastIneqProcessed = idx;
582  ++level;
583  continue;
584  }
585  }
586 
587  // Try to simplify the results.
588  result = result.simplify();
589 
590  return result;
591 }
592 
593 /// Return the complement of this set.
596 }
597 
598 /// Return the result of subtract the given set from this set, i.e.,
599 /// return `this \ set`.
602  assert(space.isCompatible(set.getSpace()) && "Spaces should match");
603  PresburgerRelation result(getSpace());
604 
605  // If we know that the two sets are clearly equal, we can simply return the
606  // empty set.
607  if (isObviouslyEqual(set))
608  return result;
609 
610  // We compute (U_i t_i) \ (U_i set_i) as U_i (t_i \ V_i set_i).
611  for (const IntegerRelation &disjunct : disjuncts)
612  result.unionInPlace(getSetDifference(disjunct, set));
613  return result;
614 }
615 
616 /// T is a subset of S iff T \ S is empty, since if T \ S contains a
617 /// point then this is a point that is contained in T but not S, and
618 /// if T contains a point that is not in S, this also lies in T \ S.
620  return this->subtract(set).isIntegerEmpty();
621 }
622 
623 /// Two sets are equal iff they are subsets of each other.
625  assert(space.isCompatible(set.getSpace()) && "Spaces should match");
626  return this->isSubsetOf(set) && set.isSubsetOf(*this);
627 }
628 
630  if (!space.isCompatible(set.getSpace()))
631  return false;
632 
633  if (getNumDisjuncts() != set.getNumDisjuncts())
634  return false;
635 
636  // Compare each disjunct in this PresburgerRelation with the corresponding
637  // disjunct in the other PresburgerRelation.
638  for (unsigned int i = 0, n = getNumDisjuncts(); i < n; ++i) {
639  if (!getDisjunct(i).isObviouslyEqual(set.getDisjunct(i)))
640  return false;
641  }
642  return true;
643 }
644 
645 /// Return true if the Presburger relation represents the universe set, false
646 /// otherwise. It is a simple check that only check if the relation has at least
647 /// one unconstrained disjunct, indicating the absence of constraints or
648 /// conditions.
650  for (const IntegerRelation &disjunct : getAllDisjuncts()) {
651  if (disjunct.getNumConstraints() == 0)
652  return true;
653  }
654  return false;
655 }
656 
658  return getNumDisjuncts() == 1 && getSpace().getNumLocalVars() == 0;
659 }
660 
661 /// Return true if there is no disjunct, false otherwise.
663  return getNumDisjuncts() == 0;
664 }
665 
666 /// Return true if all the sets in the union are known to be integer empty,
667 /// false otherwise.
669  // The set is empty iff all of the disjuncts are empty.
670  return llvm::all_of(disjuncts, std::mem_fn(&IntegerRelation::isIntegerEmpty));
671 }
672 
674  // A sample exists iff any of the disjuncts contains a sample.
675  for (const IntegerRelation &disjunct : disjuncts) {
676  if (std::optional<SmallVector<MPInt, 8>> opt =
677  disjunct.findIntegerSample()) {
678  sample = std::move(*opt);
679  return true;
680  }
681  }
682  return false;
683 }
684 
685 std::optional<MPInt> PresburgerRelation::computeVolume() const {
686  assert(getNumSymbolVars() == 0 && "Symbols are not yet supported!");
687  // The sum of the volumes of the disjuncts is a valid overapproximation of the
688  // volume of their union, even if they overlap.
689  MPInt result(0);
690  for (const IntegerRelation &disjunct : disjuncts) {
691  std::optional<MPInt> volume = disjunct.computeVolume();
692  if (!volume)
693  return {};
694  result += *volume;
695  }
696  return result;
697 }
698 
699 /// The SetCoalescer class contains all functionality concerning the coalesce
700 /// heuristic. It is built from a `PresburgerRelation` and has the `coalesce()`
701 /// function as its main API. The coalesce heuristic simplifies the
702 /// representation of a PresburgerRelation. In particular, it removes all
703 /// disjuncts which are subsets of other disjuncts in the union and it combines
704 /// sets that overlap and can be combined in a convex way.
706 
707 public:
708  /// Simplifies the representation of a PresburgerSet.
709  PresburgerRelation coalesce();
710 
711  /// Construct a SetCoalescer from a PresburgerSet.
713 
714 private:
715  /// The space of the set the SetCoalescer is coalescing.
716  PresburgerSpace space;
717 
718  /// The current list of `IntegerRelation`s that the currently coalesced set is
719  /// the union of.
721  /// The list of `Simplex`s constructed from the elements of `disjuncts`.
722  SmallVector<Simplex, 2> simplices;
723 
724  /// The list of all inversed equalities during typing. This ensures that
725  /// the constraints exist even after the typing function has concluded.
727 
728  /// `redundantIneqsA` is the inequalities of `a` that are redundant for `b`
729  /// (similarly for `cuttingIneqsA`, `redundantIneqsB`, and `cuttingIneqsB`).
730  SmallVector<ArrayRef<MPInt>, 2> redundantIneqsA;
731  SmallVector<ArrayRef<MPInt>, 2> cuttingIneqsA;
732 
733  SmallVector<ArrayRef<MPInt>, 2> redundantIneqsB;
734  SmallVector<ArrayRef<MPInt>, 2> cuttingIneqsB;
735 
736  /// Given a Simplex `simp` and one of its inequalities `ineq`, check
737  /// that the facet of `simp` where `ineq` holds as an equality is contained
738  /// within `a`.
739  bool isFacetContained(ArrayRef<MPInt> ineq, Simplex &simp);
740 
741  /// Removes redundant constraints from `disjunct`, adds it to `disjuncts` and
742  /// removes the disjuncts at position `i` and `j`. Updates `simplices` to
743  /// reflect the changes. `i` and `j` cannot be equal.
744  void addCoalescedDisjunct(unsigned i, unsigned j,
745  const IntegerRelation &disjunct);
746 
747  /// Checks whether `a` and `b` can be combined in a convex sense, if there
748  /// exist cutting inequalities.
749  ///
750  /// An example of this case:
751  /// ___________ ___________
752  /// / / | / / /
753  /// \ \ | / ==> \ /
754  /// \ \ | / \ /
755  /// \___\|/ \_____/
756  ///
757  ///
758  LogicalResult coalescePairCutCase(unsigned i, unsigned j);
759 
760  /// Types the inequality `ineq` according to its `IneqType` for `simp` into
761  /// `redundantIneqsB` and `cuttingIneqsB`. Returns success, if no separate
762  /// inequalities were encountered. Otherwise, returns failure.
763  LogicalResult typeInequality(ArrayRef<MPInt> ineq, Simplex &simp);
764 
765  /// Types the equality `eq`, i.e. for `eq` == 0, types both `eq` >= 0 and
766  /// -`eq` >= 0 according to their `IneqType` for `simp` into
767  /// `redundantIneqsB` and `cuttingIneqsB`. Returns success, if no separate
768  /// inequalities were encountered. Otherwise, returns failure.
769  LogicalResult typeEquality(ArrayRef<MPInt> eq, Simplex &simp);
770 
771  /// Replaces the element at position `i` with the last element and erases
772  /// the last element for both `disjuncts` and `simplices`.
773  void eraseDisjunct(unsigned i);
774 
775  /// Attempts to coalesce the two IntegerRelations at position `i` and `j`
776  /// in `disjuncts` in-place. Returns whether the disjuncts were
777  /// successfully coalesced. The simplices in `simplices` need to be the ones
778  /// constructed from `disjuncts`. At this point, there are no empty
779  /// disjuncts in `disjuncts` left.
780  LogicalResult coalescePair(unsigned i, unsigned j);
781 };
782 
783 /// Constructs a `SetCoalescer` from a `PresburgerRelation`. Only adds non-empty
784 /// `IntegerRelation`s to the `disjuncts` vector.
785 SetCoalescer::SetCoalescer(const PresburgerRelation &s) : space(s.getSpace()) {
786 
787  disjuncts = s.disjuncts;
788 
789  simplices.reserve(s.getNumDisjuncts());
790  // Note that disjuncts.size() changes during the loop.
791  for (unsigned i = 0; i < disjuncts.size();) {
792  disjuncts[i].removeRedundantConstraints();
793  Simplex simp(disjuncts[i]);
794  if (simp.isEmpty()) {
795  disjuncts[i] = disjuncts[disjuncts.size() - 1];
796  disjuncts.pop_back();
797  continue;
798  }
799  ++i;
800  simplices.push_back(simp);
801  }
802 }
803 
804 /// Simplifies the representation of a PresburgerSet.
806  // For all tuples of IntegerRelations, check whether they can be
807  // coalesced. When coalescing is successful, the contained IntegerRelation
808  // is swapped with the last element of `disjuncts` and subsequently erased
809  // and similarly for simplices.
810  for (unsigned i = 0; i < disjuncts.size();) {
811 
812  // TODO: This does some comparisons two times (index 0 with 1 and index 1
813  // with 0).
814  bool broken = false;
815  for (unsigned j = 0, e = disjuncts.size(); j < e; ++j) {
816  negEqs.clear();
817  redundantIneqsA.clear();
818  redundantIneqsB.clear();
819  cuttingIneqsA.clear();
820  cuttingIneqsB.clear();
821  if (i == j)
822  continue;
823  if (coalescePair(i, j).succeeded()) {
824  broken = true;
825  break;
826  }
827  }
828 
829  // Only if the inner loop was not broken, i is incremented. This is
830  // required as otherwise, if a coalescing occurs, the IntegerRelation
831  // now at position i is not compared.
832  if (!broken)
833  ++i;
834  }
835 
836  PresburgerRelation newSet = PresburgerRelation::getEmpty(space);
837  for (const IntegerRelation &disjunct : disjuncts)
838  newSet.unionInPlace(disjunct);
839 
840  return newSet;
841 }
842 
843 /// Given a Simplex `simp` and one of its inequalities `ineq`, check
844 /// that all inequalities of `cuttingIneqsB` are redundant for the facet of
845 /// `simp` where `ineq` holds as an equality is contained within `a`.
846 bool SetCoalescer::isFacetContained(ArrayRef<MPInt> ineq, Simplex &simp) {
847  SimplexRollbackScopeExit scopeExit(simp);
848  simp.addEquality(ineq);
849  return llvm::all_of(cuttingIneqsB, [&simp](ArrayRef<MPInt> curr) {
850  return simp.isRedundantInequality(curr);
851  });
852 }
853 
854 void SetCoalescer::addCoalescedDisjunct(unsigned i, unsigned j,
855  const IntegerRelation &disjunct) {
856  assert(i != j && "The indices must refer to different disjuncts");
857  unsigned n = disjuncts.size();
858  if (j == n - 1) {
859  // This case needs special handling since position `n` - 1 is removed
860  // from the vector, hence the `IntegerRelation` at position `n` - 2 is
861  // lost otherwise.
862  disjuncts[i] = disjuncts[n - 2];
863  disjuncts.pop_back();
864  disjuncts[n - 2] = disjunct;
865  disjuncts[n - 2].removeRedundantConstraints();
866 
867  simplices[i] = simplices[n - 2];
868  simplices.pop_back();
869  simplices[n - 2] = Simplex(disjuncts[n - 2]);
870 
871  } else {
872  // Other possible edge cases are correct since for `j` or `i` == `n` -
873  // 2, the `IntegerRelation` at position `n` - 2 should be lost. The
874  // case `i` == `n` - 1 makes the first following statement a noop.
875  // Hence, in this case the same thing is done as above, but with `j`
876  // rather than `i`.
877  disjuncts[i] = disjuncts[n - 1];
878  disjuncts[j] = disjuncts[n - 2];
879  disjuncts.pop_back();
880  disjuncts[n - 2] = disjunct;
881  disjuncts[n - 2].removeRedundantConstraints();
882 
883  simplices[i] = simplices[n - 1];
884  simplices[j] = simplices[n - 2];
885  simplices.pop_back();
886  simplices[n - 2] = Simplex(disjuncts[n - 2]);
887  }
888 }
889 
890 /// Given two polyhedra `a` and `b` at positions `i` and `j` in
891 /// `disjuncts` and `redundantIneqsA` being the inequalities of `a` that
892 /// are redundant for `b` (similarly for `cuttingIneqsA`, `redundantIneqsB`,
893 /// and `cuttingIneqsB`), Checks whether the facets of all cutting
894 /// inequalites of `a` are contained in `b`. If so, a new polyhedron
895 /// consisting of all redundant inequalites of `a` and `b` and all
896 /// equalities of both is created.
897 ///
898 /// An example of this case:
899 /// ___________ ___________
900 /// / / | / / /
901 /// \ \ | / ==> \ /
902 /// \ \ | / \ /
903 /// \___\|/ \_____/
904 ///
905 ///
906 LogicalResult SetCoalescer::coalescePairCutCase(unsigned i, unsigned j) {
907  /// All inequalities of `b` need to be redundant. We already know that the
908  /// redundant ones are, so only the cutting ones remain to be checked.
909  Simplex &simp = simplices[i];
910  IntegerRelation &disjunct = disjuncts[i];
911  if (llvm::any_of(cuttingIneqsA, [this, &simp](ArrayRef<MPInt> curr) {
912  return !isFacetContained(curr, simp);
913  }))
914  return failure();
915  IntegerRelation newSet(disjunct.getSpace());
916 
917  for (ArrayRef<MPInt> curr : redundantIneqsA)
918  newSet.addInequality(curr);
919 
920  for (ArrayRef<MPInt> curr : redundantIneqsB)
921  newSet.addInequality(curr);
922 
923  addCoalescedDisjunct(i, j, newSet);
924  return success();
925 }
926 
927 LogicalResult SetCoalescer::typeInequality(ArrayRef<MPInt> ineq,
928  Simplex &simp) {
929  Simplex::IneqType type = simp.findIneqType(ineq);
930  if (type == Simplex::IneqType::Redundant)
931  redundantIneqsB.push_back(ineq);
932  else if (type == Simplex::IneqType::Cut)
933  cuttingIneqsB.push_back(ineq);
934  else
935  return failure();
936  return success();
937 }
938 
939 LogicalResult SetCoalescer::typeEquality(ArrayRef<MPInt> eq, Simplex &simp) {
940  if (typeInequality(eq, simp).failed())
941  return failure();
942  negEqs.push_back(getNegatedCoeffs(eq));
943  ArrayRef<MPInt> inv(negEqs.back());
944  if (typeInequality(inv, simp).failed())
945  return failure();
946  return success();
947 }
948 
949 void SetCoalescer::eraseDisjunct(unsigned i) {
950  assert(simplices.size() == disjuncts.size() &&
951  "simplices and disjuncts must be equally as long");
952  disjuncts[i] = disjuncts.back();
953  disjuncts.pop_back();
954  simplices[i] = simplices.back();
955  simplices.pop_back();
956 }
957 
958 LogicalResult SetCoalescer::coalescePair(unsigned i, unsigned j) {
959 
960  IntegerRelation &a = disjuncts[i];
961  IntegerRelation &b = disjuncts[j];
962  /// Handling of local ids is not yet implemented, so these cases are
963  /// skipped.
964  /// TODO: implement local id support.
965  if (a.getNumLocalVars() != 0 || b.getNumLocalVars() != 0)
966  return failure();
967  Simplex &simpA = simplices[i];
968  Simplex &simpB = simplices[j];
969 
970  // Organize all inequalities and equalities of `a` according to their type
971  // for `b` into `redundantIneqsA` and `cuttingIneqsA` (and vice versa for
972  // all inequalities of `b` according to their type in `a`). If a separate
973  // inequality is encountered during typing, the two IntegerRelations
974  // cannot be coalesced.
975  for (int k = 0, e = a.getNumInequalities(); k < e; ++k)
976  if (typeInequality(a.getInequality(k), simpB).failed())
977  return failure();
978 
979  for (int k = 0, e = a.getNumEqualities(); k < e; ++k)
980  if (typeEquality(a.getEquality(k), simpB).failed())
981  return failure();
982 
983  std::swap(redundantIneqsA, redundantIneqsB);
984  std::swap(cuttingIneqsA, cuttingIneqsB);
985 
986  for (int k = 0, e = b.getNumInequalities(); k < e; ++k)
987  if (typeInequality(b.getInequality(k), simpA).failed())
988  return failure();
989 
990  for (int k = 0, e = b.getNumEqualities(); k < e; ++k)
991  if (typeEquality(b.getEquality(k), simpA).failed())
992  return failure();
993 
994  // If there are no cutting inequalities of `a`, `b` is contained
995  // within `a`.
996  if (cuttingIneqsA.empty()) {
997  eraseDisjunct(j);
998  return success();
999  }
1000 
1001  // Try to apply the cut case
1002  if (coalescePairCutCase(i, j).succeeded())
1003  return success();
1004 
1005  // Swap the vectors to compare the pair (j,i) instead of (i,j).
1006  std::swap(redundantIneqsA, redundantIneqsB);
1007  std::swap(cuttingIneqsA, cuttingIneqsB);
1008 
1009  // If there are no cutting inequalities of `a`, `b` is contained
1010  // within `a`.
1011  if (cuttingIneqsA.empty()) {
1012  eraseDisjunct(i);
1013  return success();
1014  }
1015 
1016  // Try to apply the cut case
1017  if (coalescePairCutCase(j, i).succeeded())
1018  return success();
1019 
1020  return failure();
1021 }
1022 
1023 PresburgerRelation PresburgerRelation::coalesce() const {
1024  return SetCoalescer(*this).coalesce();
1025 }
1026 
1028  return llvm::all_of(disjuncts, [](const IntegerRelation &rel) {
1029  return rel.hasOnlyDivLocals();
1030  });
1031 }
1032 
1034  PresburgerRelation origin = *this;
1036  for (IntegerRelation &disjunct : origin.disjuncts) {
1037  disjunct.simplify();
1038  if (!disjunct.isObviouslyEmpty())
1039  result.unionInPlace(disjunct);
1040  }
1041  return result;
1042 }
1043 
1045  return llvm::any_of(getAllDisjuncts(), [&](IntegerRelation disjunct) {
1046  return disjunct.isFullDim();
1047  });
1048 }
1049 
1050 void PresburgerRelation::print(raw_ostream &os) const {
1051  os << "Number of Disjuncts: " << getNumDisjuncts() << "\n";
1052  for (const IntegerRelation &disjunct : disjuncts) {
1053  disjunct.print(os);
1054  os << '\n';
1055  }
1056 }
1057 
1058 void PresburgerRelation::dump() const { print(llvm::errs()); }
1059 
1061  PresburgerSet result(space);
1063  return result;
1064 }
1065 
1067  return PresburgerSet(space);
1068 }
1069 
1071  : PresburgerRelation(disjunct) {}
1072 
1074  : PresburgerRelation(set) {}
1075 
1078 }
1079 
1082 }
1083 
1086 }
1087 
1090 }
1091 
1094 }
static SymbolicLexOpt findSymbolicIntegerLexOpt(const PresburgerRelation &rel, bool isMin)
static SmallVector< MPInt, 8 > getIneqCoeffsFromIdx(const IntegerRelation &rel, unsigned idx)
Return the coefficients of the ineq in rel specified by idx.
static PresburgerRelation getSetDifference(IntegerRelation b, const PresburgerRelation &s)
Return the set difference b \ s.
Class storing division representation of local variables of a constraint system.
Definition: Utils.h:118
MPInt & getDenom(unsigned i)
Definition: Utils.h:149
MutableArrayRef< MPInt > getDividend(unsigned i)
Definition: Utils.h:140
An IntegerPolyhedron represents the set of points from a PresburgerSpace that satisfy a list of affin...
static IntegerPolyhedron getUniverse(const PresburgerSpace &space)
Return a system with no constraints, i.e., one which is satisfied by all points.
An IntegerRelation represents the set of points from a PresburgerSpace that satisfy a list of affine ...
ArrayRef< MPInt > getEquality(unsigned idx) const
void compose(const IntegerRelation &rel)
Let the relation this be R1, and the relation rel be R2.
PresburgerSpace getSpaceWithoutLocals() const
Returns a copy of the space without locals.
void addInequality(ArrayRef< MPInt > inEq)
Adds an inequality (>= 0) from the coefficients specified in inEq.
void truncate(const CountsSnapshot &counts)
bool isEmptyByGCDTest() const
Runs the GCD test on all equality constraints.
void simplify()
Simplify the constraint system by removing canonicalizing constraints and removing redundant constrai...
void print(raw_ostream &os) const
bool isIntegerEmpty() const
Returns true if the set of constraints is found to have no solution, false if a solution exists.
IntegerRelation intersect(IntegerRelation other) const
Return the intersection of the two relations.
ArrayRef< MPInt > getInequality(unsigned idx) const
std::optional< SmallVector< MPInt, 8 > > containsPointNoLocal(ArrayRef< MPInt > point) const
Given the values of non-local vars, return a satisfying assignment to the local if one exists,...
static IntegerRelation getUniverse(const PresburgerSpace &space)
Return a system with no constraints, i.e., one which is satisfied by all points.
bool isObviouslyEmpty() const
Performs GCD checks and invalid constraint checks.
bool isEmpty() const
Checks for emptiness by performing variable elimination on all variables, running the GCD test on eac...
DivisionRepr getLocalReprs(std::vector< MaybeLocalRepr > *repr=nullptr) const
Returns a DivisonRepr representing the division representation of local variables in the constraint s...
bool hasOnlyDivLocals() const
Check whether all local ids have a division representation.
unsigned mergeLocalVars(IntegerRelation &other)
Adds additional local vars to the sets such that they both have the union of the local vars in each s...
const PresburgerSpace & getSpace() const
Returns a reference to the underlying space.
unsigned getVarKindOffset(VarKind kind) const
Return the index at which the specified kind of vars starts.
This class provides support for multi-precision arithmetic.
Definition: MPInt.h:87
This class represents a piece-wise MultiAffineFunction.
Definition: PWMAFunction.h:151
PWMAFunction unionLexMax(const PWMAFunction &func)
PWMAFunction unionLexMin(const PWMAFunction &func)
Return a function defined on the union of the domains of this and func, such that when only one of th...
A PresburgerRelation represents a union of IntegerRelations that live in the same PresburgerSpace wit...
bool containsPoint(ArrayRef< MPInt > point) const
Return true if the set contains the given point, and false otherwise.
void setSpace(const PresburgerSpace &oSpace)
Set the space to oSpace.
PresburgerRelation intersect(const PresburgerRelation &set) const
Return the intersection of this set and the given set.
bool hasOnlyDivLocals() const
Check whether all local ids in all disjuncts have a div representation.
PresburgerRelation subtract(const PresburgerRelation &set) const
Return the set difference of this set and the given set, i.e., return this \ set.
PresburgerRelation(const IntegerRelation &disjunct)
PresburgerSet getRangeSet() const
Return a set corresponding to the range of the relation.
bool isConvexNoLocals() const
Return true if the set is consist of a single disjunct, without any local variables,...
PresburgerRelation computeReprWithOnlyDivLocals() const
Compute an equivalent representation of the same relation, such that all local ids in all disjuncts h...
bool isSubsetOf(const PresburgerRelation &set) const
Return true if this set is a subset of the given set, and false otherwise.
bool isIntegerEmpty() const
Return true if all the sets in the union are known to be integer empty false otherwise.
PresburgerRelation intersectRange(const PresburgerSet &set) const
Return the range intersection of the given set with this relation.
void unionInPlace(const IntegerRelation &disjunct)
Mutate this set, turning it into the union of this set and the given disjunct.
void convertVarKind(VarKind srcKind, unsigned srcPos, unsigned num, VarKind dstKind, unsigned dstPos)
Converts variables of the specified kind in the column range [srcPos, srcPos + num) to variables of t...
PresburgerRelation intersectDomain(const PresburgerSet &set) const
Return the domain intersection of the given set with this relation.
std::optional< MPInt > computeVolume() const
Compute an overapproximation of the number of integer points in the disjunct.
bool isEqual(const PresburgerRelation &set) const
Return true if this set is equal to the given set, and false otherwise.
static PresburgerRelation getEmpty(const PresburgerSpace &space)
Return an empty set of the specified type that contains no points.
void applyDomain(const PresburgerRelation &rel)
Apply the domain of given relation rel to this relation.
unsigned getNumDisjuncts() const
Return the number of disjuncts in the union.
void applyRange(const PresburgerRelation &rel)
Same as compose, provided for uniformity with applyDomain.
bool isObviouslyEmpty() const
Return true if there is no disjunct, false otherwise.
bool isObviouslyUniverse() const
Return true if the set is known to have one unconstrained disjunct, false otherwise.
PresburgerRelation coalesce() const
Simplifies the representation of a PresburgerRelation.
static PresburgerRelation getUniverse(const PresburgerSpace &space)
Return a universe set of the specified type that contains all points.
const IntegerRelation & getDisjunct(unsigned index) const
Return the disjunct at the specified index.
ArrayRef< IntegerRelation > getAllDisjuncts() const
Return a reference to the list of disjuncts.
SmallVector< IntegerRelation, 2 > disjuncts
The list of disjuncts that this set is the union of.
PresburgerRelation simplify() const
Simplify each disjunct, canonicalizing each disjunct and removing redundencies.
void compose(const PresburgerRelation &rel)
Compose this relation with the given relation rel in-place.
const PresburgerSpace & getSpace() const
void print(raw_ostream &os) const
Print the set's internal state.
void inverse()
Invert the relation, i.e.
PresburgerSet getDomainSet() const
Return a set corresponding to the domain of the relation.
SymbolicLexOpt findSymbolicIntegerLexMax() const
Compute the symbolic integer lexmax of the relation, i.e.
void insertVarInPlace(VarKind kind, unsigned pos, unsigned num=1)
PresburgerRelation unionSet(const PresburgerRelation &set) const
Return the union of this set and the given set.
bool isObviouslyEqual(const PresburgerRelation &set) const
Perform a quick equality check on this and other.
SymbolicLexOpt findSymbolicIntegerLexMin() const
Compute the symbolic integer lexmin of the relation, i.e.
bool isFullDim() const
Return whether the given PresburgerRelation is full-dimensional.
bool findIntegerSample(SmallVectorImpl< MPInt > &sample)
Find an integer sample from the given set.
PresburgerRelation complement() const
Return the complement of this set.
PresburgerSet intersect(const PresburgerRelation &set) const
PresburgerSet(const IntegerPolyhedron &disjunct)
Create a set from a relation.
PresburgerSet unionSet(const PresburgerRelation &set) const
These operations are the same as the ones in PresburgeRelation, they just forward the arguement and r...
PresburgerSet subtract(const PresburgerRelation &set) const
static PresburgerSet getEmpty(const PresburgerSpace &space)
Return an empty set of the specified type that contains no points.
static PresburgerSet getUniverse(const PresburgerSpace &space)
Return a universe set of the specified type that contains all points.
PresburgerSpace is the space of all possible values of a tuple of integer valued variables/variables.
PresburgerSpace getRangeSpace() const
unsigned getNumVarKind(VarKind kind) const
Get the number of vars of the specified kind.
PresburgerSpace getDomainSpace() const
Get the domain/range space of this space.
void convertVarKind(VarKind srcKind, unsigned srcPos, unsigned num, VarKind dstKind, unsigned dstPos)
Converts variables of the specified kind in the column range [srcPos, srcPos + num) to variables of t...
bool isCompatible(const PresburgerSpace &other) const
Returns true if both the spaces are compatible i.e.
static PresburgerSpace getRelationSpace(unsigned numDomain=0, unsigned numRange=0, unsigned numSymbols=0, unsigned numLocals=0)
unsigned insertVar(VarKind kind, unsigned pos, unsigned num=1)
Insert num variables of the specified kind at position pos.
bool isEmpty() const
Returns true if the tableau is empty (has conflicting constraints), false otherwise.
Definition: Simplex.cpp:1066
void appendVariable(unsigned count=1)
Add new variables to the end of the list of variables.
Definition: Simplex.cpp:1315
void intersectIntegerRelation(const IntegerRelation &rel)
Add all the constraints from the given IntegerRelation.
Definition: Simplex.cpp:1330
unsigned getSnapshot() const
Get a snapshot of the current state.
Definition: Simplex.cpp:1132
void addEquality(ArrayRef< MPInt > coeffs)
Add an equality to the tableau.
Definition: Simplex.cpp:1119
void rollback(unsigned snapshot)
Rollback to a snapshot. This invalidates all later snapshots.
Definition: Simplex.cpp:1285
unsigned getNumConstraints() const
Returns the number of constraints in the tableau.
Definition: Simplex.cpp:1128
Takes a snapshot of the simplex state on construction and rolls back to the snapshot on destruction.
Definition: Simplex.h:878
The Simplex class uses the Normal pivot rule and supports integer emptiness checks as well as detecti...
Definition: Simplex.h:695
bool isMarkedRedundant(unsigned constraintIndex) const
Returns whether the specified constraint has been marked as redundant.
Definition: Simplex.cpp:1403
void addInequality(ArrayRef< MPInt > coeffs) final
Add an inequality to the tableau.
Definition: Simplex.cpp:1106
bool isRedundantInequality(ArrayRef< MPInt > coeffs)
Check if the specified inequality already holds in the polytope.
Definition: Simplex.cpp:2201
void detectRedundant(unsigned offset, unsigned count)
Finds a subset of constraints that is redundant, i.e., such that the set of solutions does not change...
Definition: Simplex.cpp:1423
IneqType findIneqType(ArrayRef< MPInt > coeffs)
Returns the type of the inequality with coefficients coeffs.
Definition: Simplex.cpp:2186
The SetCoalescer class contains all functionality concerning the coalesce heuristic.
SetCoalescer(const PresburgerRelation &s)
Construct a SetCoalescer from a PresburgerSet.
PresburgerRelation coalesce()
Simplifies the representation of a PresburgerSet.
VarKind
Kind of variable.
SmallVector< MPInt, 8 > getDivLowerBound(ArrayRef< MPInt > dividend, const MPInt &divisor, unsigned localVarIdx)
Definition: Utils.cpp:332
SmallVector< MPInt, 8 > getDivUpperBound(ArrayRef< MPInt > dividend, const MPInt &divisor, unsigned localVarIdx)
If q is defined to be equal to expr floordiv d, this equivalent to saying that q is an integer and q ...
Definition: Utils.cpp:321
SmallVector< MPInt, 8 > getNegatedCoeffs(ArrayRef< MPInt > coeffs)
Return coeffs with all the elements negated.
Definition: Utils.cpp:373
SmallVector< MPInt, 8 > getComplementIneq(ArrayRef< MPInt > ineq)
Return the complement of the given inequality.
Definition: Utils.cpp:381
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
Definition: LogicalResult.h:68
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
bool failed() const
Returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:44
The struct CountsSnapshot stores the count of each VarKind, and also of each constraint type.
Represents the result of a symbolic lexicographic optimization computation.
Definition: Simplex.h:533
PWMAFunction lexopt
This maps assignments of symbols to the corresponding lexopt.
Definition: Simplex.h:541
PresburgerSet unboundedDomain
Contains all assignments to the symbols that made the lexopt unbounded.
Definition: Simplex.h:545
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.