diff --git a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h --- a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h +++ b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h @@ -128,6 +128,11 @@ /// If there are locals, they will be merged. IntegerRelation intersect(IntegerRelation other) const; + /// Return the intersection of the two relations by directly adding the + /// current relation's constraint to the other relation. This specialized + /// version does not perform additional checks or modifications. + IntegerRelation intersectAddConstraint(IntegerRelation other) const; + /// Return whether `this` and `other` are equal. This is integer-exact /// and somewhat expensive, since it uses the integer emptiness check /// (see IntegerRelation::findIntegerSample()). diff --git a/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h b/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h --- a/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h +++ b/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h @@ -110,6 +110,13 @@ /// false otherwise. bool isIntegerEmpty() const; + /// Return true if the set is known to be the universe set, false otherwise. + bool isUniverse() const; + + /// Return true if the set is consist of a single disjunct, without any local + /// variables, false otherwise. + bool isConvexNoLocals() const; + /// Find an integer sample from the given set. This should not be called if /// any of the disjuncts in the union are unbounded. bool findIntegerSample(SmallVectorImpl &sample); diff --git a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp --- a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp +++ b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp @@ -75,6 +75,13 @@ return result; } +IntegerRelation +IntegerRelation::intersectAddConstraint(IntegerRelation other) const { + IntegerRelation result = *this; + result.append(other); + return result; +} + bool IntegerRelation::isEqual(const IntegerRelation &other) const { assert(space.isCompatible(other.getSpace()) && "Spaces must be compatible."); return PresburgerRelation(*this).isEqual(PresburgerRelation(other)); diff --git a/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp b/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp --- a/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp +++ b/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp @@ -97,6 +97,27 @@ PresburgerRelation::intersect(const PresburgerRelation &set) const { assert(space.isCompatible(set.getSpace()) && "Spaces should match"); + if ((getNumDisjuncts() == 0 || set.isUniverse()) && + space.isEqual(set.getSpace())) + return *this; + + if ((set.getNumDisjuncts() == 0 || isUniverse()) && + space.isEqual(set.getSpace())) + return set; + + // Special case, where both relation are convex, without any divs and such + // that either one of it contains a single constraint. Simply add constraint + // to the other relation. + if (isConvexNoLocals() && set.isConvexNoLocals() && + space.isEqual(set.getSpace()) && + (getDisjunct(0).getNumConstraints() == 1 || + set.getDisjunct(0).getNumConstraints() == 1)) { + PresburgerRelation result(getSpace()); + result.unionInPlace(getDisjunct(0)); + result.getDisjunct(0).intersectAddConstraint(set.getDisjunct(0)); + return result; + } + PresburgerRelation result(getSpace()); for (const IntegerRelation &csA : disjuncts) { for (const IntegerRelation &csB : set.disjuncts) { @@ -453,6 +474,24 @@ return this->isSubsetOf(set) && set.isSubsetOf(*this); } +/// Return true if the Presburger relation is known to represent the universe +/// set, false otherwise. A Presburger relation is considered to be the universe +/// set if it contains at least one disjunct that is unconstrained, i.e., it +/// does not have any constraints or conditions. +bool PresburgerRelation::isUniverse() const { + for (auto &disjunct : getAllDisjuncts()) { + if (disjunct.getNumConstraints() == 0) + return true; + } + return false; +} + +bool PresburgerRelation::isConvexNoLocals() const { + if (getNumDisjuncts() == 1 && getSpace().getNumLocalVars() == 0) + return true; + return false; +} + /// Return true if all the sets in the union are known to be integer empty, /// false otherwise. bool PresburgerRelation::isIntegerEmpty() const {