#include "mlir/Analysis/Presburger/PresburgerRelation.h"
#include "mlir/Analysis/Presburger/IntegerRelation.h"
#include "mlir/Analysis/Presburger/PWMAFunction.h"
#include "mlir/Analysis/Presburger/PresburgerSpace.h"
#include "mlir/Analysis/Presburger/Simplex.h"
#include "mlir/Analysis/Presburger/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/LogicalResult.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <functional>
#include <optional>
#include <utility>
#include <vector>
using namespace mlir;
using namespace presburger;
PresburgerRelation::PresburgerRelation(const IntegerRelation &disjunct)
: space(disjunct.getSpaceWithoutLocals()) {
unionInPlace(disjunct);
}
void PresburgerRelation::setSpace(const PresburgerSpace &oSpace) {
assert(space.getNumLocalVars() == 0 && "no locals should be present");
space = oSpace;
for (IntegerRelation &disjunct : disjuncts)
disjunct.setSpaceExceptLocals(space);
}
void PresburgerRelation::insertVarInPlace(VarKind kind, unsigned pos,
unsigned num) {
for (IntegerRelation &cs : disjuncts)
cs.insertVar(kind, pos, num);
space.insertVar(kind, pos, num);
}
void PresburgerRelation::convertVarKind(VarKind srcKind, unsigned srcPos,
unsigned num, VarKind dstKind,
unsigned dstPos) {
assert(srcKind != VarKind::Local && dstKind != VarKind::Local &&
"srcKind/dstKind cannot be local");
assert(srcKind != dstKind && "cannot convert variables to the same kind");
assert(srcPos + num <= space.getNumVarKind(srcKind) &&
"invalid range for source variables");
assert(dstPos <= space.getNumVarKind(dstKind) &&
"invalid position for destination variables");
space.convertVarKind(srcKind, srcPos, num, dstKind, dstPos);
for (IntegerRelation &disjunct : disjuncts)
disjunct.convertVarKind(srcKind, srcPos, srcPos + num, dstKind, dstPos);
}
unsigned PresburgerRelation::getNumDisjuncts() const {
return disjuncts.size();
}
ArrayRef<IntegerRelation> PresburgerRelation::getAllDisjuncts() const {
return disjuncts;
}
const IntegerRelation &PresburgerRelation::getDisjunct(unsigned index) const {
assert(index < disjuncts.size() && "index out of bounds!");
return disjuncts[index];
}
void PresburgerRelation::unionInPlace(const IntegerRelation &disjunct) {
assert(space.isCompatible(disjunct.getSpace()) && "Spaces should match");
disjuncts.emplace_back(disjunct);
}
void PresburgerRelation::unionInPlace(const PresburgerRelation &set) {
assert(space.isCompatible(set.getSpace()) && "Spaces should match");
if (isObviouslyEqual(set))
return;
if (isObviouslyEmpty()) {
disjuncts = set.disjuncts;
return;
}
if (set.isObviouslyEmpty())
return;
if (isObviouslyUniverse())
return;
if (set.isObviouslyUniverse()) {
disjuncts = set.disjuncts;
return;
}
for (const IntegerRelation &disjunct : set.disjuncts)
unionInPlace(disjunct);
}
PresburgerRelation
PresburgerRelation::unionSet(const PresburgerRelation &set) const {
assert(space.isCompatible(set.getSpace()) && "Spaces should match");
PresburgerRelation result = *this;
result.unionInPlace(set);
return result;
}
bool PresburgerRelation::containsPoint(ArrayRef<DynamicAPInt> point) const {
return llvm::any_of(disjuncts, [&point](const IntegerRelation &disjunct) {
return disjunct.containsPointNoLocal(point);
});
}
PresburgerRelation
PresburgerRelation::getUniverse(const PresburgerSpace &space) {
PresburgerRelation result(space);
result.unionInPlace(IntegerRelation::getUniverse(space));
return result;
}
PresburgerRelation PresburgerRelation::getEmpty(const PresburgerSpace &space) {
return PresburgerRelation(space);
}
PresburgerRelation
PresburgerRelation::intersect(const PresburgerRelation &set) const {
assert(space.isCompatible(set.getSpace()) && "Spaces should match");
if (isObviouslyEmpty() || set.isObviouslyUniverse())
return *this;
if (set.isObviouslyEmpty() || isObviouslyUniverse())
return set;
PresburgerRelation result(getSpace());
for (const IntegerRelation &csA : disjuncts) {
for (const IntegerRelation &csB : set.disjuncts) {
IntegerRelation intersection = csA.intersect(csB);
if (!intersection.isEmpty())
result.unionInPlace(intersection);
}
}
return result;
}
PresburgerRelation
PresburgerRelation::intersectRange(const PresburgerSet &set) const {
assert(space.getRangeSpace().isCompatible(set.getSpace()) &&
"Range of `this` must be compatible with range of `set`");
PresburgerRelation other = set;
other.insertVarInPlace(VarKind::Domain, 0, getNumDomainVars());
return intersect(other);
}
PresburgerRelation
PresburgerRelation::intersectDomain(const PresburgerSet &set) const {
assert(space.getDomainSpace().isCompatible(set.getSpace()) &&
"Domain of `this` must be compatible with range of `set`");
PresburgerRelation other = set;
other.insertVarInPlace(VarKind::Domain, 0, getNumRangeVars());
other.inverse();
return intersect(other);
}
PresburgerSet PresburgerRelation::getDomainSet() const {
PresburgerSet result = PresburgerSet::getEmpty(space.getDomainSpace());
for (const IntegerRelation &cs : disjuncts)
result.unionInPlace(cs.getDomainSet());
return result;
}
PresburgerSet PresburgerRelation::getRangeSet() const {
PresburgerSet result = PresburgerSet::getEmpty(space.getRangeSpace());
for (const IntegerRelation &cs : disjuncts)
result.unionInPlace(cs.getRangeSet());
return result;
}
void PresburgerRelation::inverse() {
for (IntegerRelation &cs : disjuncts)
cs.inverse();
if (getNumDisjuncts())
setSpace(getDisjunct(0).getSpaceWithoutLocals());
}
void PresburgerRelation::compose(const PresburgerRelation &rel) {
assert(getSpace().getRangeSpace().isCompatible(
rel.getSpace().getDomainSpace()) &&
"Range of `this` should be compatible with domain of `rel`");
PresburgerRelation result =
PresburgerRelation::getEmpty(PresburgerSpace::getRelationSpace(
getNumDomainVars(), rel.getNumRangeVars(), getNumSymbolVars()));
for (const IntegerRelation &csA : disjuncts) {
for (const IntegerRelation &csB : rel.disjuncts) {
IntegerRelation composition = csA;
composition.compose(csB);
if (!composition.isEmpty())
result.unionInPlace(composition);
}
}
*this = result;
}
void PresburgerRelation::applyDomain(const PresburgerRelation &rel) {
assert(getSpace().getDomainSpace().isCompatible(
rel.getSpace().getDomainSpace()) &&
"Domain of `this` should be compatible with domain of `rel`");
inverse();
compose(rel);
inverse();
}
void PresburgerRelation::applyRange(const PresburgerRelation &rel) {
compose(rel);
}
static SymbolicLexOpt findSymbolicIntegerLexOpt(const PresburgerRelation &rel,
bool isMin) {
SymbolicLexOpt result(rel.getSpace());
PWMAFunction &lexopt = result.lexopt;
PresburgerSet &unboundedDomain = result.unboundedDomain;
for (const IntegerRelation &cs : rel.getAllDisjuncts()) {
SymbolicLexOpt s(rel.getSpace());
if (isMin) {
s = cs.findSymbolicIntegerLexMin();
lexopt = lexopt.unionLexMin(s.lexopt);
} else {
s = cs.findSymbolicIntegerLexMax();
lexopt = lexopt.unionLexMax(s.lexopt);
}
unboundedDomain = unboundedDomain.intersect(s.unboundedDomain);
}
return result;
}
SymbolicLexOpt PresburgerRelation::findSymbolicIntegerLexMin() const {
return findSymbolicIntegerLexOpt(*this, true);
}
SymbolicLexOpt PresburgerRelation::findSymbolicIntegerLexMax() const {
return findSymbolicIntegerLexOpt(*this, false);
}
static SmallVector<DynamicAPInt, 8>
getIneqCoeffsFromIdx(const IntegerRelation &rel, unsigned idx) {
assert(idx < rel.getNumInequalities() + 2 * rel.getNumEqualities() &&
"idx out of bounds!");
if (idx < rel.getNumInequalities())
return llvm::to_vector<8>(rel.getInequality(idx));
idx -= rel.getNumInequalities();
ArrayRef<DynamicAPInt> eqCoeffs = rel.getEquality(idx / 2);
if (idx % 2 == 0)
return llvm::to_vector<8>(eqCoeffs);
return getNegatedCoeffs(eqCoeffs);
}
PresburgerRelation PresburgerRelation::computeReprWithOnlyDivLocals() const {
if (hasOnlyDivLocals())
return *this;
PresburgerRelation result(getSpace());
for (const IntegerRelation &disjunct : disjuncts)
result.unionInPlace(disjunct.computeReprWithOnlyDivLocals());
return result;
}
static PresburgerRelation getSetDifference(IntegerRelation b,
const PresburgerRelation &s) {
assert(b.getSpace().isCompatible(s.getSpace()) && "Spaces should match");
if (b.isEmptyByGCDTest())
return PresburgerRelation::getEmpty(b.getSpaceWithoutLocals());
if (!s.hasOnlyDivLocals())
return getSetDifference(b, s.computeReprWithOnlyDivLocals());
b.removeDuplicateDivs();
PresburgerRelation result =
PresburgerRelation::getEmpty(b.getSpaceWithoutLocals());
Simplex simplex(b);
struct Frame {
unsigned simplexSnapshot;
IntegerRelation::CountsSnapshot bCounts;
IntegerRelation sI;
SmallVector<unsigned, 8> ineqsToProcess;
std::optional<unsigned> lastIneqProcessed;
Frame(unsigned simplexSnapshot,
const IntegerRelation::CountsSnapshot &bCounts,
const IntegerRelation &sI, ArrayRef<unsigned> ineqsToProcess = {},
std::optional<unsigned> lastIneqProcessed = std::nullopt)
: simplexSnapshot(simplexSnapshot), bCounts(bCounts), sI(sI),
ineqsToProcess(ineqsToProcess), lastIneqProcessed(lastIneqProcessed) {
}
};
SmallVector<Frame, 2> frames;
unsigned level = 1;
while (level > 0) {
if (level - 1 >= s.getNumDisjuncts()) {
result.unionInPlace(b);
level = frames.size();
continue;
}
if (level > frames.size()) {
IntegerRelation sI = s.getDisjunct(level - 1);
sI.removeDuplicateDivs();
IntegerRelation::CountsSnapshot initBCounts = b.getCounts();
unsigned initialSnapshot = simplex.getSnapshot();
b.mergeLocalVars(sI);
std::vector<MaybeLocalRepr> repr(sI.getNumLocalVars());
DivisionRepr divs = sI.getLocalReprs(&repr);
llvm::SmallBitVector canIgnoreIneq(sI.getNumInequalities() +
2 * sI.getNumEqualities());
for (unsigned i = initBCounts.getSpace().getNumLocalVars(),
e = sI.getNumLocalVars();
i < e; ++i) {
assert(
repr[i] &&
"Subtraction is not supported when a representation of the local "
"variables of the subtrahend cannot be found!");
if (repr[i].kind == ReprKind::Inequality) {
unsigned lb = repr[i].repr.inequalityPair.lowerBoundIdx;
unsigned ub = repr[i].repr.inequalityPair.upperBoundIdx;
b.addInequality(sI.getInequality(lb));
b.addInequality(sI.getInequality(ub));
assert(lb != ub &&
"Upper and lower bounds must be different inequalities!");
canIgnoreIneq[lb] = true;
canIgnoreIneq[ub] = true;
} else {
assert(repr[i].kind == ReprKind::Equality &&
"ReprKind isn't inequality so should be equality");
b.addInequality(
getDivLowerBound(divs.getDividend(i), divs.getDenom(i),
sI.getVarKindOffset(VarKind::Local) + i));
b.addInequality(
getDivUpperBound(divs.getDividend(i), divs.getDenom(i),
sI.getVarKindOffset(VarKind::Local) + i));
}
}
unsigned offset = simplex.getNumConstraints();
unsigned numLocalsAdded =
b.getNumLocalVars() - initBCounts.getSpace().getNumLocalVars();
simplex.appendVariable(numLocalsAdded);
unsigned snapshotBeforeIntersect = simplex.getSnapshot();
simplex.intersectIntegerRelation(sI);
if (simplex.isEmpty()) {
b.truncate(initBCounts);
simplex.rollback(initialSnapshot);
frames.emplace_back(Frame{initialSnapshot, initBCounts, sI});
++level;
continue;
}
unsigned totalNewSimplexInequalities =
2 * sI.getNumEqualities() + sI.getNumInequalities();
simplex.detectRedundant(offset, totalNewSimplexInequalities);
for (unsigned j = 0; j < totalNewSimplexInequalities; j++)
canIgnoreIneq[j] = simplex.isMarkedRedundant(offset + j);
simplex.rollback(snapshotBeforeIntersect);
SmallVector<unsigned, 8> ineqsToProcess;
ineqsToProcess.reserve(totalNewSimplexInequalities);
for (unsigned i = 0; i < totalNewSimplexInequalities; ++i)
if (!canIgnoreIneq[i])
ineqsToProcess.emplace_back(i);
if (ineqsToProcess.empty()) {
level = frames.size();
continue;
}
unsigned simplexSnapshot = simplex.getSnapshot();
IntegerRelation::CountsSnapshot bCounts = b.getCounts();
frames.emplace_back(Frame{simplexSnapshot, bCounts, sI, ineqsToProcess});
}
if (level == frames.size()) {
Frame &frame = frames.back();
if (frame.lastIneqProcessed) {
simplex.rollback(frame.simplexSnapshot);
b.truncate(frame.bCounts);
SmallVector<DynamicAPInt, 8> ineq =
getIneqCoeffsFromIdx(frame.sI, *frame.lastIneqProcessed);
b.addInequality(ineq);
simplex.addInequality(ineq);
}
if (frame.ineqsToProcess.empty()) {
frames.pop_back();
level = frames.size();
continue;
}
frame.bCounts = b.getCounts();
frame.simplexSnapshot = simplex.getSnapshot();
unsigned idx = frame.ineqsToProcess.back();
SmallVector<DynamicAPInt, 8> ineq =
getComplementIneq(getIneqCoeffsFromIdx(frame.sI, idx));
b.addInequality(ineq);
simplex.addInequality(ineq);
frame.ineqsToProcess.pop_back();
frame.lastIneqProcessed = idx;
++level;
continue;
}
}
result = result.simplify();
return result;
}
PresburgerRelation PresburgerRelation::complement() const {
return getSetDifference(IntegerRelation::getUniverse(getSpace()), *this);
}
PresburgerRelation
PresburgerRelation::subtract(const PresburgerRelation &set) const {
assert(space.isCompatible(set.getSpace()) && "Spaces should match");
PresburgerRelation result(getSpace());
if (isObviouslyEqual(set))
return result;
for (const IntegerRelation &disjunct : disjuncts)
result.unionInPlace(getSetDifference(disjunct, set));
return result;
}
bool PresburgerRelation::isSubsetOf(const PresburgerRelation &set) const {
return this->subtract(set).isIntegerEmpty();
}
bool PresburgerRelation::isEqual(const PresburgerRelation &set) const {
assert(space.isCompatible(set.getSpace()) && "Spaces should match");
return this->isSubsetOf(set) && set.isSubsetOf(*this);
}
bool PresburgerRelation::isObviouslyEqual(const PresburgerRelation &set) const {
if (!space.isCompatible(set.getSpace()))
return false;
if (getNumDisjuncts() != set.getNumDisjuncts())
return false;
for (unsigned int i = 0, n = getNumDisjuncts(); i < n; ++i) {
if (!getDisjunct(i).isObviouslyEqual(set.getDisjunct(i)))
return false;
}
return true;
}
bool PresburgerRelation::isObviouslyUniverse() const {
for (const IntegerRelation &disjunct : getAllDisjuncts()) {
if (disjunct.getNumConstraints() == 0)
return true;
}
return false;
}
bool PresburgerRelation::isConvexNoLocals() const {
return getNumDisjuncts() == 1 && getSpace().getNumLocalVars() == 0;
}
bool PresburgerRelation::isObviouslyEmpty() const {
return getNumDisjuncts() == 0;
}
bool PresburgerRelation::isIntegerEmpty() const {
return llvm::all_of(disjuncts, std::mem_fn(&IntegerRelation::isIntegerEmpty));
}
bool PresburgerRelation::findIntegerSample(
SmallVectorImpl<DynamicAPInt> &sample) {
for (const IntegerRelation &disjunct : disjuncts) {
if (std::optional<SmallVector<DynamicAPInt, 8>> opt =
disjunct.findIntegerSample()) {
sample = std::move(*opt);
return true;
}
}
return false;
}
std::optional<DynamicAPInt> PresburgerRelation::computeVolume() const {
assert(getNumSymbolVars() == 0 && "Symbols are not yet supported!");
DynamicAPInt result(0);
for (const IntegerRelation &disjunct : disjuncts) {
std::optional<DynamicAPInt> volume = disjunct.computeVolume();
if (!volume)
return {};
result += *volume;
}
return result;
}
class presburger::SetCoalescer {
public:
PresburgerRelation coalesce();
SetCoalescer(const PresburgerRelation &s);
private:
PresburgerSpace space;
SmallVector<IntegerRelation, 2> disjuncts;
SmallVector<Simplex, 2> simplices;
SmallVector<SmallVector<DynamicAPInt, 2>, 2> negEqs;
SmallVector<ArrayRef<DynamicAPInt>, 2> redundantIneqsA;
SmallVector<ArrayRef<DynamicAPInt>, 2> cuttingIneqsA;
SmallVector<ArrayRef<DynamicAPInt>, 2> redundantIneqsB;
SmallVector<ArrayRef<DynamicAPInt>, 2> cuttingIneqsB;
bool isFacetContained(ArrayRef<DynamicAPInt> ineq, Simplex &simp);
void addCoalescedDisjunct(unsigned i, unsigned j,
const IntegerRelation &disjunct);
LogicalResult coalescePairCutCase(unsigned i, unsigned j);
LogicalResult typeInequality(ArrayRef<DynamicAPInt> ineq, Simplex &simp);
LogicalResult typeEquality(ArrayRef<DynamicAPInt> eq, Simplex &simp);
void eraseDisjunct(unsigned i);
LogicalResult coalescePair(unsigned i, unsigned j);
};
SetCoalescer::SetCoalescer(const PresburgerRelation &s) : space(s.getSpace()) {
disjuncts = s.disjuncts;
simplices.reserve(s.getNumDisjuncts());
for (unsigned i = 0; i < disjuncts.size();) {
disjuncts[i].removeRedundantConstraints();
Simplex simp(disjuncts[i]);
if (simp.isEmpty()) {
disjuncts[i] = disjuncts[disjuncts.size() - 1];
disjuncts.pop_back();
continue;
}
++i;
simplices.emplace_back(simp);
}
}
PresburgerRelation SetCoalescer::coalesce() {
for (unsigned i = 0; i < disjuncts.size();) {
bool broken = false;
for (unsigned j = 0, e = disjuncts.size(); j < e; ++j) {
negEqs.clear();
redundantIneqsA.clear();
redundantIneqsB.clear();
cuttingIneqsA.clear();
cuttingIneqsB.clear();
if (i == j)
continue;
if (coalescePair(i, j).succeeded()) {
broken = true;
break;
}
}
if (!broken)
++i;
}
PresburgerRelation newSet = PresburgerRelation::getEmpty(space);
for (const IntegerRelation &disjunct : disjuncts)
newSet.unionInPlace(disjunct);
return newSet;
}
bool SetCoalescer::isFacetContained(ArrayRef<DynamicAPInt> ineq,
Simplex &simp) {
SimplexRollbackScopeExit scopeExit(simp);
simp.addEquality(ineq);
return llvm::all_of(cuttingIneqsB, [&simp](ArrayRef<DynamicAPInt> curr) {
return simp.isRedundantInequality(curr);
});
}
void SetCoalescer::addCoalescedDisjunct(unsigned i, unsigned j,
const IntegerRelation &disjunct) {
assert(i != j && "The indices must refer to different disjuncts");
unsigned n = disjuncts.size();
if (j == n - 1) {
disjuncts[i] = disjuncts[n - 2];
disjuncts.pop_back();
disjuncts[n - 2] = disjunct;
disjuncts[n - 2].removeRedundantConstraints();
simplices[i] = simplices[n - 2];
simplices.pop_back();
simplices[n - 2] = Simplex(disjuncts[n - 2]);
} else {
disjuncts[i] = disjuncts[n - 1];
disjuncts[j] = disjuncts[n - 2];
disjuncts.pop_back();
disjuncts[n - 2] = disjunct;
disjuncts[n - 2].removeRedundantConstraints();
simplices[i] = simplices[n - 1];
simplices[j] = simplices[n - 2];
simplices.pop_back();
simplices[n - 2] = Simplex(disjuncts[n - 2]);
}
}
LogicalResult SetCoalescer::coalescePairCutCase(unsigned i, unsigned j) {
Simplex &simp = simplices[i];
IntegerRelation &disjunct = disjuncts[i];
if (llvm::any_of(cuttingIneqsA, [this, &simp](ArrayRef<DynamicAPInt> curr) {
return !isFacetContained(curr, simp);
}))
return failure();
IntegerRelation newSet(disjunct.getSpace());
for (ArrayRef<DynamicAPInt> curr : redundantIneqsA)
newSet.addInequality(curr);
for (ArrayRef<DynamicAPInt> curr : redundantIneqsB)
newSet.addInequality(curr);
addCoalescedDisjunct(i, j, newSet);
return success();
}
LogicalResult SetCoalescer::typeInequality(ArrayRef<DynamicAPInt> ineq,
Simplex &simp) {
Simplex::IneqType type = simp.findIneqType(ineq);
if (type == Simplex::IneqType::Redundant)
redundantIneqsB.emplace_back(ineq);
else if (type == Simplex::IneqType::Cut)
cuttingIneqsB.emplace_back(ineq);
else
return failure();
return success();
}
LogicalResult SetCoalescer::typeEquality(ArrayRef<DynamicAPInt> eq,
Simplex &simp) {
if (typeInequality(eq, simp).failed())
return failure();
negEqs.emplace_back(getNegatedCoeffs(eq));
ArrayRef<DynamicAPInt> inv(negEqs.back());
return typeInequality(inv, simp);
}
void SetCoalescer::eraseDisjunct(unsigned i) {
assert(simplices.size() == disjuncts.size() &&
"simplices and disjuncts must be equally as long");
disjuncts[i] = disjuncts.back();
disjuncts.pop_back();
simplices[i] = simplices.back();
simplices.pop_back();
}
LogicalResult SetCoalescer::coalescePair(unsigned i, unsigned j) {
IntegerRelation &a = disjuncts[i];
IntegerRelation &b = disjuncts[j];
if (a.getNumLocalVars() != 0 || b.getNumLocalVars() != 0)
return failure();
Simplex &simpA = simplices[i];
Simplex &simpB = simplices[j];
for (int k = 0, e = a.getNumInequalities(); k < e; ++k)
if (typeInequality(a.getInequality(k), simpB).failed())
return failure();
for (int k = 0, e = a.getNumEqualities(); k < e; ++k)
if (typeEquality(a.getEquality(k), simpB).failed())
return failure();
std::swap(redundantIneqsA, redundantIneqsB);
std::swap(cuttingIneqsA, cuttingIneqsB);
for (int k = 0, e = b.getNumInequalities(); k < e; ++k)
if (typeInequality(b.getInequality(k), simpA).failed())
return failure();
for (int k = 0, e = b.getNumEqualities(); k < e; ++k)
if (typeEquality(b.getEquality(k), simpA).failed())
return failure();
if (cuttingIneqsA.empty()) {
eraseDisjunct(j);
return success();
}
if (coalescePairCutCase(i, j).succeeded())
return success();
std::swap(redundantIneqsA, redundantIneqsB);
std::swap(cuttingIneqsA, cuttingIneqsB);
if (cuttingIneqsA.empty()) {
eraseDisjunct(i);
return success();
}
return coalescePairCutCase(j, i);
}
PresburgerRelation PresburgerRelation::coalesce() const {
return SetCoalescer(*this).coalesce();
}
bool PresburgerRelation::hasOnlyDivLocals() const {
return llvm::all_of(disjuncts, [](const IntegerRelation &rel) {
return rel.hasOnlyDivLocals();
});
}
PresburgerRelation PresburgerRelation::simplify() const {
PresburgerRelation origin = *this;
PresburgerRelation result = PresburgerRelation(getSpace());
for (IntegerRelation &disjunct : origin.disjuncts) {
disjunct.simplify();
if (!disjunct.isObviouslyEmpty())
result.unionInPlace(disjunct);
}
return result;
}
bool PresburgerRelation::isFullDim() const {
return llvm::any_of(getAllDisjuncts(), [](IntegerRelation disjunct) {
return disjunct.isFullDim();
});
}
void PresburgerRelation::print(raw_ostream &os) const {
os << "Number of Disjuncts: " << getNumDisjuncts() << "\n";
for (const IntegerRelation &disjunct : disjuncts) {
disjunct.print(os);
os << '\n';
}
}
void PresburgerRelation::dump() const { print(llvm::errs()); }
PresburgerSet PresburgerSet::getUniverse(const PresburgerSpace &space) {
PresburgerSet result(space);
result.unionInPlace(IntegerPolyhedron::getUniverse(space));
return result;
}
PresburgerSet PresburgerSet::getEmpty(const PresburgerSpace &space) {
return PresburgerSet(space);
}
PresburgerSet::PresburgerSet(const IntegerPolyhedron &disjunct)
: PresburgerRelation(disjunct) {}
PresburgerSet::PresburgerSet(const PresburgerRelation &set)
: PresburgerRelation(set) {}
PresburgerSet PresburgerSet::unionSet(const PresburgerRelation &set) const {
return PresburgerSet(PresburgerRelation::unionSet(set));
}
PresburgerSet PresburgerSet::intersect(const PresburgerRelation &set) const {
return PresburgerSet(PresburgerRelation::intersect(set));
}
PresburgerSet PresburgerSet::complement() const {
return PresburgerSet(PresburgerRelation::complement());
}
PresburgerSet PresburgerSet::subtract(const PresburgerRelation &set) const {
return PresburgerSet(PresburgerRelation::subtract(set));
}
PresburgerSet PresburgerSet::coalesce() const {
return PresburgerSet(PresburgerRelation::coalesce());
}