diff --git a/mlir/include/mlir/Analysis/Presburger/Simplex.h b/mlir/include/mlir/Analysis/Presburger/Simplex.h --- a/mlir/include/mlir/Analysis/Presburger/Simplex.h +++ b/mlir/include/mlir/Analysis/Presburger/Simplex.h @@ -488,6 +488,8 @@ public: enum class Direction { Up, Down }; + enum class IneqType { Redundant, Cut, Separate }; + Simplex() = delete; explicit Simplex(unsigned nVar) : SimplexBase(nVar, /*mustUseBigM=*/false) {} explicit Simplex(const IntegerPolyhedron &constraints) @@ -555,6 +557,14 @@ /// otherwise. This should only be called for bounded sets. Optional> findIntegerSample(); + /// returns the type of the inequality `coeffs`. + /// + /// Possible types are: + /// Redundant The inequality is satisfied in the polytope + /// Cut The inequality is satisfied by some points, but not by others + /// Separate The inequality is not satisfied by any point + Simplex::IneqType ineqType(ArrayRef coeffs); + /// Check if the specified inequality already holds in the polytope. bool isRedundantInequality(ArrayRef coeffs); diff --git a/mlir/lib/Analysis/Presburger/PresburgerSet.cpp b/mlir/lib/Analysis/Presburger/PresburgerSet.cpp --- a/mlir/lib/Analysis/Presburger/PresburgerSet.cpp +++ b/mlir/lib/Analysis/Presburger/PresburgerSet.cpp @@ -418,7 +418,32 @@ if (j == i || isRedundant[j]) continue; - if (simplex.isRationalSubsetOf(integerPolyhedrons[j])) { + for (unsigned l = 0, e = integerPolyhedrons[j].getNumEqualities(); l < e; + ++l) + if (!simplex.isRedundantEquality(integerPolyhedrons[j].getEquality(l))) + continue; + + // type all inequalities + SmallVector, 2> redundant_ineqs; + SmallVector, 2> cutting_ineqs; + SmallVector, 2> separate_ineqs; + + for (unsigned l = 0, e = integerPolyhedrons[j].getNumInequalities(); + l < e; ++l) { + Simplex::IneqType type = + simplex.ineqType(integerPolyhedrons[j].getInequality(l)); + if (type == Simplex::IneqType::Redundant) { + redundant_ineqs.push_back(integerPolyhedrons[j].getInequality(l)); + } else if (type == Simplex::IneqType::Cut) { + cutting_ineqs.push_back(integerPolyhedrons[j].getInequality(l)); + } else { + separate_ineqs.push_back(integerPolyhedrons[j].getInequality(l)); + } + } + + // If no separate and cutting inequalities exist, this can be + // coalesced. + if (separate_ineqs.size() == 0 && cutting_ineqs.size() == 0) { isRedundant[i] = true; break; } diff --git a/mlir/lib/Analysis/Presburger/Simplex.cpp b/mlir/lib/Analysis/Presburger/Simplex.cpp --- a/mlir/lib/Analysis/Presburger/Simplex.cpp +++ b/mlir/lib/Analysis/Presburger/Simplex.cpp @@ -1582,6 +1582,31 @@ return true; } +/// returns the type of the inequality `coeffs`. Possible types are: +/// Redundant The inequality is satisfied in the polytope +/// Cut The inequality is satisfied by some points, but not by others +/// Separate The inequality is not satisfied by any point +/// +/// Internally, this computes the minimum and the maximum `coeffs` can take. If +/// the minimum exists and it is >= 0, the inequality holds for all points in +/// the polytope, so `coeffs` is redundant. If the minimum does not exists or +/// is <= 0 and the maximum does not exists or is >= 0, the points in between +/// the minimum and `coeffs` do not satisfy the inequality, the points in +/// between `coeffs` and the maximum satisfy the inequality. Hence, it is a cut +/// inequality. In any other case, separate is returned. +Simplex::IneqType Simplex::ineqType(ArrayRef coeffs) { + Optional minimum = computeOptimum(Direction::Down, coeffs); + if (minimum && *minimum >= Fraction(0, 1)) { + return IneqType::Redundant; + } + Optional maximum = computeOptimum(Direction::Up, coeffs); + if ((!minimum || *minimum <= Fraction(0, 1)) && + (!maximum || *maximum >= Fraction(0, 1))) { + return IneqType::Cut; + } + return IneqType::Separate; +} + /// Computes the minimum value `coeffs` can take. If the value is greater than /// or equal to zero, the polytope entirely lies in the half-space defined by /// `coeffs >= 0`. diff --git a/mlir/unittests/Analysis/Presburger/SimplexTest.cpp b/mlir/unittests/Analysis/Presburger/SimplexTest.cpp --- a/mlir/unittests/Analysis/Presburger/SimplexTest.cpp +++ b/mlir/unittests/Analysis/Presburger/SimplexTest.cpp @@ -462,6 +462,28 @@ EXPECT_FALSE(simplex.isRedundantInequality({0, 1, -1})); // y >= 1. } +TEST(SimplexTest, ineqType) { + Simplex simplex(2); + simplex.addInequality({0, -1, 2}); // y <= 2. + simplex.addInequality({1, 0, 0}); // x >= 0. + simplex.addEquality({-1, 1, 0}); // y = x. + + EXPECT_TRUE(simplex.ineqType({-1, 0, 2}) == + Simplex::IneqType::Redundant); // x <= 2. + EXPECT_TRUE(simplex.ineqType({0, 1, 0}) == + Simplex::IneqType::Redundant); // y >= 0. + + EXPECT_TRUE(simplex.ineqType({0, 1, -1}) == + Simplex::IneqType::Cut); // y >= 1. + EXPECT_TRUE(simplex.ineqType({-1, 0, 1}) == + Simplex::IneqType::Cut); // x <= 1. + EXPECT_TRUE(simplex.ineqType({0, 1, -2}) == + Simplex::IneqType::Cut); // y >= 2. + + EXPECT_TRUE(simplex.ineqType({-1, 0, -1}) == + Simplex::IneqType::Separate); // x <= -1. +} + TEST(SimplexTest, isRedundantEquality) { Simplex simplex(2); simplex.addInequality({0, -1, 2}); // y <= 2.