[Mlir-commits] [mlir] [MLIR][Presburger] Helper functions to compute the constant term of a generating function (PR #77819)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sat Jan 13 05:15:44 PST 2024


https://github.com/Abhinav271828 updated https://github.com/llvm/llvm-project/pull/77819

>From e14460853a105da0b19dac35f4725840f217ab27 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Thu, 11 Jan 2024 22:02:02 +0530
Subject: [PATCH 01/18] New constructor

---
 mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h | 2 ++
 mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp        | 6 ++++++
 2 files changed, 8 insertions(+)

diff --git a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
index f8ce8524e41b21..e656c7e3fb00c1 100644
--- a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
+++ b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
@@ -39,6 +39,8 @@ class QuasiPolynomial : public PresburgerSpace {
   QuasiPolynomial(unsigned numVars, SmallVector<Fraction> coeffs = {},
                   std::vector<std::vector<SmallVector<Fraction>>> aff = {});
 
+  QuasiPolynomial(unsigned numVars, Fraction constant);
+
   // Find the number of inputs (numDomain) to the polynomial.
   // numSymbols is set to zero.
   unsigned getNumInputs() const {
diff --git a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
index feed683a203cff..24878dd47a2acf 100644
--- a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
+++ b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
@@ -36,6 +36,12 @@ QuasiPolynomial::QuasiPolynomial(
 #endif // NDEBUG
 }
 
+/// Define a quasipolynomial which is a single constant.
+QuasiPolynomial::QuasiPolynomial(unsigned numVars, Fraction constant)
+    : PresburgerSpace(/*numDomain=*/numVars, /*numRange=*/1, /*numSymbols=*/0,
+                      /*numLocals=*/0),
+      coefficients({constant}), affine({{}}) {}
+
 QuasiPolynomial QuasiPolynomial::operator+(const QuasiPolynomial &x) const {
   assert(getNumInputs() == x.getNumInputs() &&
          "two quasi-polynomials with different numbers of symbols cannot "

>From f247ebcec062002164177489bbd4e9b7987acce4 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Thu, 11 Jan 2024 22:12:46 +0530
Subject: [PATCH 02/18] Functions

---
 .../mlir/Analysis/Presburger/Barvinok.h       |  8 ++
 mlir/lib/Analysis/Presburger/Barvinok.cpp     | 92 +++++++++++++++++++
 2 files changed, 100 insertions(+)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 213af636e5964d..d67c999083e5c0 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -27,6 +27,7 @@
 #include "mlir/Analysis/Presburger/GeneratingFunction.h"
 #include "mlir/Analysis/Presburger/IntegerRelation.h"
 #include "mlir/Analysis/Presburger/Matrix.h"
+#include "mlir/Analysis/Presburger/QuasiPolynomial.h"
 #include <optional>
 
 namespace mlir {
@@ -83,6 +84,13 @@ ConeH getDual(ConeV cone);
 GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign,
                                                     ConeH cone);
 
+/// Find the coefficient of a given power of s in a rational function
+/// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials,
+/// and those in Q are Fractions.
+QuasiPolynomial getCoefficientInRationalFunction(unsigned power,
+                                                 std::vector<QuasiPolynomial>,
+                                                 std::vector<Fraction>);
+
 } // namespace detail
 } // namespace presburger
 } // namespace mlir
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 0bdc9015c3d647..d4cd867aa31578 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -144,3 +144,95 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
                             std::vector({numerator}),
                             std::vector({denominator}));
 }
+
+/// We use a recursive procedure to find a vector not orthogonal
+/// to a given set. Let the inputs be {x_1, ..., x_k}, all vectors of length n.
+///
+/// In the following,
+/// vs[:i] means the elements of vs up to and including the i'th one,
+/// <vs, us> means the dot product of v and u,
+/// vs ++ [v] means the vector vs with the new element v appended to it.
+///
+/// Suppose we have a vector vs which is not orthogonal to
+/// any of {x_1[:n-1], ..., x_k[:n-1]}.
+/// Then we need v s.t. <x_i, vs++[v]> != 0 for all i.
+/// => <x_i[:n-1], vs> + x_i[-1]*v != 0
+/// => v != - <x_i[:n-1], vs> / x_i[-1]
+/// We compute this value for all i, and then
+/// set v to be the maximum element of this set + 1. Thus
+/// v is outside the set as desired, and we append it to vs.
+///
+/// The base case is given in one dimension,
+/// where the vector [1] is not orthogonal to any
+/// of the input vectors (since they are all nonzero).
+Point getNonOrthogonalVector(std::vector<Point> vectors) {
+  unsigned dim = vectors[0].size();
+
+  SmallVector<Fraction> newPoint = {Fraction(1, 1)};
+  std::vector<Fraction> lowerDimDotProducts;
+  Fraction dotProduct;
+  Fraction maxDisallowedValue = Fraction(-1, 0),
+           disallowedValue = Fraction(0, 1);
+  Fraction newValue;
+
+  for (unsigned d = 2; d <= dim; d++) {
+    lowerDimDotProducts.clear();
+
+    // Compute the set of dot products <x_i[:d-1], vs> for each i.
+    for (Point vector : vectors) {
+      dotProduct = Fraction(0, 1);
+      for (unsigned i = 0; i < d - 1; i++)
+        dotProduct = dotProduct + vector[i] * newPoint[i];
+      lowerDimDotProducts.push_back(dotProduct);
+    }
+
+    // Compute - <x_i[:n-1], vs> / x_i[-1] for each i,
+    // and find the biggest such value.
+    for (unsigned i = 0; i < vectors.size(); i++) {
+      if (vectors[i][d - 1] == 0)
+        continue;
+      disallowedValue = - lowerDimDotProducts[i] / vectors[i][d - 1];
+      if (maxDisallowedValue < disallowedValue)
+        maxDisallowedValue = disallowedValue;
+    }
+
+    newValue = Fraction(ceil(maxDisallowedValue + Fraction(1, 1)), 1);
+    newPoint.append(1, newValue);
+  }
+  return newPoint;
+}
+
+/// We use the following recursive formula to find the coefficient of
+/// s^power in the rational function given by P(s)/Q(s).
+///
+/// Let P[i] denote the coefficient of s^i in the polynomial P(s).
+/// (P/Q)[r] =
+/// if (r == 0) then
+///   P[0]/Q[0]
+/// else
+///   (P[r] - {Σ_{i=1}^r (P/Q)[r-i] * Q[i])}/(Q[0])
+/// We therefore recursively call `getCoefficientInRationalFuncion` on
+/// all i \in [0, power).
+///
+/// https://math.ucdavis.edu/~deloera/researchsummary/
+/// barvinokalgorithm-latte1.pdf, p. 1285
+QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
+    unsigned power, std::vector<QuasiPolynomial> num,
+    std::vector<Fraction> den) {
+  if (power == 0)
+    return (num[0] / den[0]);
+
+  unsigned numParam = num[0].getNumInputs();
+
+  QuasiPolynomial t(numParam, Fraction(0, 1));
+
+  // The coefficient of s^power in the numerator.
+  if (power < num.size())
+    t = num[power];
+
+  unsigned limit = power + 1 < den.size() ? power + 1 : den.size();
+  for (unsigned i = 1; i < limit; ++i)
+    t = t - getCoefficientInRationalFunction(power - i, num, den) *
+                QuasiPolynomial(numParam, den[i]);
+  return (t / den[0]).simplify();
+}
\ No newline at end of file

>From 97701e5992c6ddb00e114e48fba1ffdd0edddcb8 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Thu, 11 Jan 2024 22:26:54 +0530
Subject: [PATCH 03/18] Functions

---
 mlir/include/mlir/Analysis/Presburger/Barvinok.h    | 6 ++++++
 mlir/lib/Analysis/Presburger/Barvinok.cpp           | 9 +++++----
 mlir/unittests/Analysis/Presburger/BarvinokTest.cpp | 2 ++
 3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index d67c999083e5c0..88ec1d33f98140 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -84,6 +84,12 @@ ConeH getDual(ConeV cone);
 GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign,
                                                     ConeH cone);
 
+/// Find a vector that is not orthogonal to any of the given vectors,
+/// i.e., has nonzero dot product with those of the given vectors
+/// that are not null.
+/// If any of the vectors is null, it is ignored.
+Point getNonOrthonalVector(std::vector<Point> vectors);
+
 /// Find the coefficient of a given power of s in a rational function
 /// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials,
 /// and those in Q are Fractions.
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index d4cd867aa31578..8cbabd18925c0b 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -165,7 +165,8 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
 /// The base case is given in one dimension,
 /// where the vector [1] is not orthogonal to any
 /// of the input vectors (since they are all nonzero).
-Point getNonOrthogonalVector(std::vector<Point> vectors) {
+Point mlir::presburger::detail::getNonOrthonalVector(
+    std::vector<Point> vectors) {
   unsigned dim = vectors[0].size();
 
   SmallVector<Fraction> newPoint = {Fraction(1, 1)};
@@ -179,7 +180,7 @@ Point getNonOrthogonalVector(std::vector<Point> vectors) {
     lowerDimDotProducts.clear();
 
     // Compute the set of dot products <x_i[:d-1], vs> for each i.
-    for (Point vector : vectors) {
+    for (const Point &vector : vectors) {
       dotProduct = Fraction(0, 1);
       for (unsigned i = 0; i < d - 1; i++)
         dotProduct = dotProduct + vector[i] * newPoint[i];
@@ -188,10 +189,10 @@ Point getNonOrthogonalVector(std::vector<Point> vectors) {
 
     // Compute - <x_i[:n-1], vs> / x_i[-1] for each i,
     // and find the biggest such value.
-    for (unsigned i = 0; i < vectors.size(); i++) {
+    for (unsigned i = 0, e = vectors.size(); i < e; ++i) {
       if (vectors[i][d - 1] == 0)
         continue;
-      disallowedValue = - lowerDimDotProducts[i] / vectors[i][d - 1];
+      disallowedValue = -lowerDimDotProducts[i] / vectors[i][d - 1];
       if (maxDisallowedValue < disallowedValue)
         maxDisallowedValue = disallowedValue;
     }
diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
index 2936d95c802e9c..3c90868b0d9021 100644
--- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
@@ -82,3 +82,5 @@ TEST(BarvinokTest, unimodularConeGeneratingFunction) {
           1, {1}, {makeFracMatrix(2, 3, {{-83, -100, -41}, {-22, -27, -15}})},
           {{{8, 47, -17}, {-7, -41, 15}, {1, 5, -2}}}));
 }
+
+TEST(BarvinokTest, non)
\ No newline at end of file

>From db3a96dc0b44c534ee63b98db02bca97ae8a129c Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Thu, 11 Jan 2024 22:27:34 +0530
Subject: [PATCH 04/18] Typo

---
 mlir/include/mlir/Analysis/Presburger/Barvinok.h    | 2 +-
 mlir/lib/Analysis/Presburger/Barvinok.cpp           | 2 +-
 mlir/unittests/Analysis/Presburger/BarvinokTest.cpp | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 88ec1d33f98140..81259e0b9f87b9 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -88,7 +88,7 @@ GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign,
 /// i.e., has nonzero dot product with those of the given vectors
 /// that are not null.
 /// If any of the vectors is null, it is ignored.
-Point getNonOrthonalVector(std::vector<Point> vectors);
+Point getNonOrthogonalVector(std::vector<Point> vectors);
 
 /// Find the coefficient of a given power of s in a rational function
 /// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials,
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 8cbabd18925c0b..007437ef5069f1 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -165,7 +165,7 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
 /// The base case is given in one dimension,
 /// where the vector [1] is not orthogonal to any
 /// of the input vectors (since they are all nonzero).
-Point mlir::presburger::detail::getNonOrthonalVector(
+Point mlir::presburger::detail::getNonOrthogonalVector(
     std::vector<Point> vectors) {
   unsigned dim = vectors[0].size();
 
diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
index 3c90868b0d9021..ccbd0d9a60191e 100644
--- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
@@ -83,4 +83,4 @@ TEST(BarvinokTest, unimodularConeGeneratingFunction) {
           {{{8, 47, -17}, {-7, -41, 15}, {1, 5, -2}}}));
 }
 
-TEST(BarvinokTest, non)
\ No newline at end of file
+TEST(BarvinokTest, getNonOrthonalVector)
\ No newline at end of file

>From 497fb4f49bd0a71033204c1ee4eba3faa85e0302 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Thu, 11 Jan 2024 22:33:09 +0530
Subject: [PATCH 05/18] Test:

---
 .../Analysis/Presburger/BarvinokTest.cpp         | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
index ccbd0d9a60191e..70eeb4e93e52fe 100644
--- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
@@ -83,4 +83,18 @@ TEST(BarvinokTest, unimodularConeGeneratingFunction) {
           {{{8, 47, -17}, {-7, -41, 15}, {1, 5, -2}}}));
 }
 
-TEST(BarvinokTest, getNonOrthonalVector)
\ No newline at end of file
+TEST(BarvinokTest, getNonOrthogonalVector) {
+  std::vector<Point> vectors = {Point({1, 2, 3, 4}), Point({-1, 0, 1, 1}),
+                                Point({2, 7, 0, 0}), Point({0, 0, 0, 0})};
+  Point nonOrth = getNonOrthogonalVector(vectors);
+
+  for (unsigned i = 0; i < 3; i++)
+    EXPECT_FALSE(dotProduct(nonOrth, vectors[i]) == 0);
+
+  vectors = {Point({0, 1, 3}), Point({-2, -1, 1}), Point({6, 3, 0}),
+             Point({0, 0, -3}), Point({5, 0, -1})};
+  nonOrth = getNonOrthogonalVector(vectors);
+
+  for (const Point &vector : vectors)
+    EXPECT_FALSE(dotProduct(nonOrth, vector) == 0);
+}
\ No newline at end of file

>From 368b5a5545147562f23b93df7f7a1ccd5c8d368e Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Fri, 12 Jan 2024 00:43:11 +0530
Subject: [PATCH 06/18] DPize

---
 mlir/lib/Analysis/Presburger/Barvinok.cpp | 28 ++++++++++++++---------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 007437ef5069f1..7572267c87a8ee 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -220,20 +220,26 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
 QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
     unsigned power, std::vector<QuasiPolynomial> num,
     std::vector<Fraction> den) {
-  if (power == 0)
-    return (num[0] / den[0]);
 
   unsigned numParam = num[0].getNumInputs();
+  unsigned limit;
 
-  QuasiPolynomial t(numParam, Fraction(0, 1));
+  std::vector<QuasiPolynomial> coefficients(power + 1,
+                                            QuasiPolynomial(numParam, 0));
 
-  // The coefficient of s^power in the numerator.
-  if (power < num.size())
-    t = num[power];
+  coefficients[0] = num[0] / den[0];
 
-  unsigned limit = power + 1 < den.size() ? power + 1 : den.size();
-  for (unsigned i = 1; i < limit; ++i)
-    t = t - getCoefficientInRationalFunction(power - i, num, den) *
-                QuasiPolynomial(numParam, den[i]);
-  return (t / den[0]).simplify();
+  for (unsigned i = 1; i <= power; i++) {
+    if (i < num.size())
+      coefficients[i] = num[i];
+
+    limit = i + 1 < den.size() ? i + 1 : den.size();
+
+    for (unsigned j = 1; j < limit; j++)
+      coefficients[i] = coefficients[i] -
+                        coefficients[i - j] * QuasiPolynomial(numParam, den[j]);
+
+    coefficients[i] = coefficients[i] / den[0];
+  }
+  return (coefficients[power]).simplify();
 }
\ No newline at end of file

>From ae433d22eba348ab5e60f1c524cac83af0da6a58 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Fri, 12 Jan 2024 00:43:22 +0530
Subject: [PATCH 07/18] Tests

---
 .../Analysis/Presburger/BarvinokTest.cpp      | 42 ++++++++++++++++++-
 mlir/unittests/Analysis/Presburger/Utils.h    | 14 +++++++
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
index 70eeb4e93e52fe..072a24262604cb 100644
--- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
@@ -83,6 +83,9 @@ TEST(BarvinokTest, unimodularConeGeneratingFunction) {
           {{{8, 47, -17}, {-7, -41, 15}, {1, 5, -2}}}));
 }
 
+// The following vectors are randomly generated.
+// We then check that the output of the function has nonzero
+// dot product with all non-null vectors.
 TEST(BarvinokTest, getNonOrthogonalVector) {
   std::vector<Point> vectors = {Point({1, 2, 3, 4}), Point({-1, 0, 1, 1}),
                                 Point({2, 7, 0, 0}), Point({0, 0, 0, 0})};
@@ -97,4 +100,41 @@ TEST(BarvinokTest, getNonOrthogonalVector) {
 
   for (const Point &vector : vectors)
     EXPECT_FALSE(dotProduct(nonOrth, vector) == 0);
-}
\ No newline at end of file
+}
+
+Fraction getC(QuasiPolynomial q) {
+  Fraction t = 0;
+  for (const Fraction &c : q.getCoefficients())
+    t += c;
+
+  return t;
+}
+
+// The following polynomials are randomly generated and the
+// coefficients are computed by hand.
+// Although the function allows the coefficients of the numerator
+// to be arbitrary quasipolynomials, we stick to constants for simplicity,
+// as the relevant arithmetic operations on quasipolynomials
+// are tested separately.
+TEST(BarvinokTest, getCoefficientInRationalFunction) {
+  std::vector<QuasiPolynomial> numerator = {
+      QuasiPolynomial(0, 2), QuasiPolynomial(0, 3), QuasiPolynomial(0, 5)};
+
+  std::vector<Fraction> denominator = {Fraction(1), Fraction(0), Fraction(4),
+                                       Fraction(3)};
+
+  QuasiPolynomial coeff =
+      getCoefficientInRationalFunction(1, numerator, denominator);
+
+  EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(coeff, 3);
+
+  numerator = {QuasiPolynomial(0, -1), QuasiPolynomial(0, 4),
+               QuasiPolynomial(0, -2), QuasiPolynomial(0, 5),
+               QuasiPolynomial(0, 6)};
+
+  denominator = {Fraction(8), Fraction(4), Fraction(0), Fraction(-2)};
+
+  coeff = getCoefficientInRationalFunction(3, numerator, denominator);
+
+  EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(coeff, Fraction(55, 64));
+}
diff --git a/mlir/unittests/Analysis/Presburger/Utils.h b/mlir/unittests/Analysis/Presburger/Utils.h
index 6b00898a7e2749..2c05fe7e2057f9 100644
--- a/mlir/unittests/Analysis/Presburger/Utils.h
+++ b/mlir/unittests/Analysis/Presburger/Utils.h
@@ -128,6 +128,20 @@ inline void EXPECT_EQ_REPR_QUASIPOLYNOMIAL(QuasiPolynomial a,
   }
 }
 
+// Check the constant term of the quasipolynomial against a constant.
+inline void EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(QuasiPolynomial qp,
+                                                 Fraction f) {
+  SmallVector<Fraction> coeffs = qp.getCoefficients();
+  std::vector<std::vector<SmallVector<Fraction>>> aff = qp.getAffine();
+
+  Fraction t = 0;
+  for (unsigned i = 0, e = coeffs.size(); i < e; ++i) {
+    if (aff[i].size() == 0)
+      t += coeffs[i];
+  }
+  EXPECT_EQ(t, f);
+}
+
 /// lhs and rhs represent non-negative integers or positive infinity. The
 /// infinity case corresponds to when the Optional is empty.
 inline bool infinityOrUInt64LE(std::optional<MPInt> lhs,

>From 738c47609ea1d5825070d7521c8329bf8d0c97b8 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Fri, 12 Jan 2024 19:09:56 +0530
Subject: [PATCH 08/18] Fix doc, small refactors

---
 .../mlir/Analysis/Presburger/Barvinok.h       |  7 ++---
 mlir/lib/Analysis/Presburger/Barvinok.cpp     | 26 ++++++++++---------
 2 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 81259e0b9f87b9..07cfea6f8610d6 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -91,11 +91,12 @@ GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign,
 Point getNonOrthogonalVector(std::vector<Point> vectors);
 
 /// Find the coefficient of a given power of s in a rational function
-/// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials,
+/// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials
+/// over d parameters (distinct from s).
 /// and those in Q are Fractions.
 QuasiPolynomial getCoefficientInRationalFunction(unsigned power,
-                                                 std::vector<QuasiPolynomial>,
-                                                 std::vector<Fraction>);
+                                                 ArrayRef<QuasiPolynomial> num,
+                                                 ArrayRef<Fraction> den);
 
 } // namespace detail
 } // namespace presburger
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 7572267c87a8ee..1ed0f98c9748dc 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -8,6 +8,7 @@
 
 #include "mlir/Analysis/Presburger/Barvinok.h"
 #include "llvm/ADT/Sequence.h"
+#include <algorithm>
 
 using namespace mlir;
 using namespace presburger;
@@ -149,17 +150,17 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
 /// to a given set. Let the inputs be {x_1, ..., x_k}, all vectors of length n.
 ///
 /// In the following,
-/// vs[:i] means the elements of vs up to and including the i'th one,
-/// <vs, us> means the dot product of v and u,
+/// vs[:i] means the elements of vs up to (not including) the i'th one,
+/// <vs, us> means the dot product of vs and us,
 /// vs ++ [v] means the vector vs with the new element v appended to it.
 ///
 /// Suppose we have a vector vs which is not orthogonal to
 /// any of {x_1[:n-1], ..., x_k[:n-1]}.
 /// Then we need v s.t. <x_i, vs++[v]> != 0 for all i.
-/// => <x_i[:n-1], vs> + x_i[-1]*v != 0
-/// => v != - <x_i[:n-1], vs> / x_i[-1]
+/// => <x_i[:n-1], vs> + x_i[n-1]*v != 0
+/// => v != - <x_i[:n-1], vs> / x_i[n-1]
 /// We compute this value for all i, and then
-/// set v to be the maximum element of this set + 1. Thus
+/// set v to be the maximum element of this set plus one. Thus
 /// v is outside the set as desired, and we append it to vs.
 ///
 /// The base case is given in one dimension,
@@ -212,30 +213,31 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
 ///   P[0]/Q[0]
 /// else
 ///   (P[r] - {Σ_{i=1}^r (P/Q)[r-i] * Q[i])}/(Q[0])
-/// We therefore recursively call `getCoefficientInRationalFuncion` on
+/// We therefore recursively call `getCoefficientInRationalFunction` on
 /// all i \in [0, power).
 ///
 /// https://math.ucdavis.edu/~deloera/researchsummary/
 /// barvinokalgorithm-latte1.pdf, p. 1285
 QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
-    unsigned power, std::vector<QuasiPolynomial> num,
-    std::vector<Fraction> den) {
+    unsigned power, ArrayRef<QuasiPolynomial> num, ArrayRef<Fraction> den) {
 
   unsigned numParam = num[0].getNumInputs();
-  unsigned limit;
+  for (const QuasiPolynomial &qp : num)
+    assert(numParam == qp.getNumInputs() &&
+           "the quasipolynomials should all belong to the same space!");
 
   std::vector<QuasiPolynomial> coefficients(power + 1,
                                             QuasiPolynomial(numParam, 0));
 
   coefficients[0] = num[0] / den[0];
 
-  for (unsigned i = 1; i <= power; i++) {
+  for (unsigned i = 1; i <= power; ++i) {
     if (i < num.size())
       coefficients[i] = num[i];
 
-    limit = i + 1 < den.size() ? i + 1 : den.size();
+    unsigned limit = fmin(i, den.size() - 1);
 
-    for (unsigned j = 1; j < limit; j++)
+    for (unsigned j = 1; j <= limit; ++j)
       coefficients[i] = coefficients[i] -
                         coefficients[i - j] * QuasiPolynomial(numParam, den[j]);
 

>From ecfb7b998e921788a48d5d6ba37f8d9513c33f88 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Fri, 12 Jan 2024 19:13:06 +0530
Subject: [PATCH 09/18] Add getConstantTerm() to QP

---
 .../mlir/Analysis/Presburger/QuasiPolynomial.h     |  3 +++
 mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp   | 10 ++++++++++
 .../unittests/Analysis/Presburger/BarvinokTest.cpp |  4 ++--
 mlir/unittests/Analysis/Presburger/Utils.h         | 14 --------------
 4 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
index e656c7e3fb00c1..b56ad57db06664 100644
--- a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
+++ b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
@@ -62,6 +62,9 @@ class QuasiPolynomial : public PresburgerSpace {
   // Removes terms which evaluate to zero from the expression.
   QuasiPolynomial simplify();
 
+  // Find the constant term of the expression.
+  Fraction getConstantTerm();
+
 private:
   SmallVector<Fraction> coefficients;
   std::vector<std::vector<SmallVector<Fraction>>> affine;
diff --git a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
index 24878dd47a2acf..49c6944b012515 100644
--- a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
+++ b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
@@ -119,3 +119,13 @@ QuasiPolynomial QuasiPolynomial::simplify() {
   }
   return QuasiPolynomial(getNumInputs(), newCoeffs, newAffine);
 }
+
+// Check the constant term of the quasipolynomial against a constant.
+Fraction QuasiPolynomial::getConstantTerm() {
+  Fraction t = 0;
+  for (unsigned i = 0, e = coefficients.size(); i < e; ++i) {
+    if (affine[i].size() == 0)
+      t += coefficients[i];
+  }
+  return t;
+}
diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
index 072a24262604cb..6852be1157cc73 100644
--- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp
@@ -126,7 +126,7 @@ TEST(BarvinokTest, getCoefficientInRationalFunction) {
   QuasiPolynomial coeff =
       getCoefficientInRationalFunction(1, numerator, denominator);
 
-  EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(coeff, 3);
+  EXPECT_EQ(coeff.getConstantTerm(), 3);
 
   numerator = {QuasiPolynomial(0, -1), QuasiPolynomial(0, 4),
                QuasiPolynomial(0, -2), QuasiPolynomial(0, 5),
@@ -136,5 +136,5 @@ TEST(BarvinokTest, getCoefficientInRationalFunction) {
 
   coeff = getCoefficientInRationalFunction(3, numerator, denominator);
 
-  EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(coeff, Fraction(55, 64));
+  EXPECT_EQ(coeff.getConstantTerm(), Fraction(55, 64));
 }
diff --git a/mlir/unittests/Analysis/Presburger/Utils.h b/mlir/unittests/Analysis/Presburger/Utils.h
index 2c05fe7e2057f9..6b00898a7e2749 100644
--- a/mlir/unittests/Analysis/Presburger/Utils.h
+++ b/mlir/unittests/Analysis/Presburger/Utils.h
@@ -128,20 +128,6 @@ inline void EXPECT_EQ_REPR_QUASIPOLYNOMIAL(QuasiPolynomial a,
   }
 }
 
-// Check the constant term of the quasipolynomial against a constant.
-inline void EXPECT_CONSTANT_TERM_QUASIPOLYNOMIAL(QuasiPolynomial qp,
-                                                 Fraction f) {
-  SmallVector<Fraction> coeffs = qp.getCoefficients();
-  std::vector<std::vector<SmallVector<Fraction>>> aff = qp.getAffine();
-
-  Fraction t = 0;
-  for (unsigned i = 0, e = coeffs.size(); i < e; ++i) {
-    if (aff[i].size() == 0)
-      t += coeffs[i];
-  }
-  EXPECT_EQ(t, f);
-}
-
 /// lhs and rhs represent non-negative integers or positive infinity. The
 /// infinity case corresponds to when the Optional is empty.
 inline bool infinityOrUInt64LE(std::optional<MPInt> lhs,

>From 0e41f51efe332e93890efb22fbf090b602b61d28 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Fri, 12 Jan 2024 19:18:48 +0530
Subject: [PATCH 10/18] Fix doc

---
 mlir/lib/Analysis/Presburger/Barvinok.cpp | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 1ed0f98c9748dc..377b8efeedb167 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -147,21 +147,28 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
 }
 
 /// We use a recursive procedure to find a vector not orthogonal
-/// to a given set. Let the inputs be {x_1, ..., x_k}, all vectors of length n.
+/// to a given set, ignoring the null vectors.
+/// Let the inputs be {x_1, ..., x_k}, all vectors of length n.
 ///
 /// In the following,
 /// vs[:i] means the elements of vs up to (not including) the i'th one,
 /// <vs, us> means the dot product of vs and us,
 /// vs ++ [v] means the vector vs with the new element v appended to it.
 ///
-/// Suppose we have a vector vs which is not orthogonal to
-/// any of {x_1[:n-1], ..., x_k[:n-1]}.
-/// Then we need v s.t. <x_i, vs++[v]> != 0 for all i.
-/// => <x_i[:n-1], vs> + x_i[n-1]*v != 0
-/// => v != - <x_i[:n-1], vs> / x_i[n-1]
-/// We compute this value for all i, and then
+/// We proceed iteratively; for steps i = 2, ... n, we construct a vector
+/// which is not orthogonal to any of {x_1[:i], ..., x_n[:i]}, ignoring
+/// the null vectors.
+/// At step i = 2, we let vs = [1]. Clearly this is not orthogonal to
+/// any vector in the set {x_1[0], ..., x_n[0]}, except the null ones,
+/// which we ignore.
+/// At step i = k + 1, we need a number v
+/// s.t. <x_i[:k+1], vs++[v]> != 0 for all i.
+/// => <x_i[:k], vs> + x_i[k]*v != 0
+/// => v != - <x_i[:k], vs> / x_i[k]
+/// We compute this value for all x_i, and then
 /// set v to be the maximum element of this set plus one. Thus
-/// v is outside the set as desired, and we append it to vs.
+/// v is outside the set as desired, and we append it to vs
+/// to obtain the result of the k+1'th step.
 ///
 /// The base case is given in one dimension,
 /// where the vector [1] is not orthogonal to any

>From 7d8545dbd0706c77f7d161000f7a328fe0bf9624 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 13 Jan 2024 13:57:54 +0530
Subject: [PATCH 11/18] Fix doc

---
 .../mlir/Analysis/Presburger/Barvinok.h       |  7 ++--
 .../Analysis/Presburger/QuasiPolynomial.h     |  1 -
 mlir/lib/Analysis/Presburger/Barvinok.cpp     | 32 ++++++++-----------
 .../Analysis/Presburger/QuasiPolynomial.cpp   |  1 -
 4 files changed, 18 insertions(+), 23 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 07cfea6f8610d6..72cbca71ba5a94 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -91,9 +91,10 @@ GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign,
 Point getNonOrthogonalVector(std::vector<Point> vectors);
 
 /// Find the coefficient of a given power of s in a rational function
-/// given by P(s)/Q(s), where the coefficients in P are QuasiPolynomials
-/// over d parameters (distinct from s).
-/// and those in Q are Fractions.
+/// given by P(s)/Q(s), where
+/// P is a polynomial, in which the coefficients are QuasiPolynomials
+/// over d parameters (distinct from s), and
+/// and Q is a polynomial with Fraction coefficients.
 QuasiPolynomial getCoefficientInRationalFunction(unsigned power,
                                                  ArrayRef<QuasiPolynomial> num,
                                                  ArrayRef<Fraction> den);
diff --git a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
index b56ad57db06664..d03446f50264fa 100644
--- a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
+++ b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
@@ -62,7 +62,6 @@ class QuasiPolynomial : public PresburgerSpace {
   // Removes terms which evaluate to zero from the expression.
   QuasiPolynomial simplify();
 
-  // Find the constant term of the expression.
   Fraction getConstantTerm();
 
 private:
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 377b8efeedb167..aacfc45e8b9bf1 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -146,33 +146,29 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
                             std::vector({denominator}));
 }
 
-/// We use a recursive procedure to find a vector not orthogonal
+/// We use an iterative procedure to find a vector not orthogonal
 /// to a given set, ignoring the null vectors.
 /// Let the inputs be {x_1, ..., x_k}, all vectors of length n.
 ///
 /// In the following,
-/// vs[:i] means the elements of vs up to (not including) the i'th one,
+/// vs[:i] means the elements of vs up to and including the i'th one,
 /// <vs, us> means the dot product of vs and us,
 /// vs ++ [v] means the vector vs with the new element v appended to it.
 ///
-/// We proceed iteratively; for steps i = 2, ... n, we construct a vector
+/// We proceed iteratively; for steps d = 0, ... n-1, we construct a vector
 /// which is not orthogonal to any of {x_1[:i], ..., x_n[:i]}, ignoring
 /// the null vectors.
-/// At step i = 2, we let vs = [1]. Clearly this is not orthogonal to
+/// At step d = 0, we let vs = [1]. Clearly this is not orthogonal to
 /// any vector in the set {x_1[0], ..., x_n[0]}, except the null ones,
 /// which we ignore.
-/// At step i = k + 1, we need a number v
-/// s.t. <x_i[:k+1], vs++[v]> != 0 for all i.
-/// => <x_i[:k], vs> + x_i[k]*v != 0
-/// => v != - <x_i[:k], vs> / x_i[k]
+/// At step d = t + 1, we need a number v
+/// s.t. <x_i[:t+1], vs++[v]> != 0 for all i.
+/// => <x_i[:t], vs> + x_i[t+1]*v != 0
+/// => v != - <x_i[:t], vs> / x_i[t+1]
 /// We compute this value for all x_i, and then
 /// set v to be the maximum element of this set plus one. Thus
 /// v is outside the set as desired, and we append it to vs
-/// to obtain the result of the k+1'th step.
-///
-/// The base case is given in one dimension,
-/// where the vector [1] is not orthogonal to any
-/// of the input vectors (since they are all nonzero).
+/// to obtain the result of the t+1'th step.
 Point mlir::presburger::detail::getNonOrthogonalVector(
     std::vector<Point> vectors) {
   unsigned dim = vectors[0].size();
@@ -184,23 +180,23 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
            disallowedValue = Fraction(0, 1);
   Fraction newValue;
 
-  for (unsigned d = 2; d <= dim; d++) {
+  for (unsigned d = 1; d < dim; ++d) {
     lowerDimDotProducts.clear();
 
     // Compute the set of dot products <x_i[:d-1], vs> for each i.
     for (const Point &vector : vectors) {
       dotProduct = Fraction(0, 1);
-      for (unsigned i = 0; i < d - 1; i++)
+      for (unsigned i = 0; i < d; i++)
         dotProduct = dotProduct + vector[i] * newPoint[i];
       lowerDimDotProducts.push_back(dotProduct);
     }
 
-    // Compute - <x_i[:n-1], vs> / x_i[-1] for each i,
+    // Compute - <x_i[:d-1], vs> / x_i[d] for each i,
     // and find the biggest such value.
     for (unsigned i = 0, e = vectors.size(); i < e; ++i) {
-      if (vectors[i][d - 1] == 0)
+      if (vectors[i][d] == 0)
         continue;
-      disallowedValue = -lowerDimDotProducts[i] / vectors[i][d - 1];
+      disallowedValue = -lowerDimDotProducts[i] / vectors[i][d];
       if (maxDisallowedValue < disallowedValue)
         maxDisallowedValue = disallowedValue;
     }
diff --git a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
index 49c6944b012515..f6ee7c8638c197 100644
--- a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
+++ b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
@@ -120,7 +120,6 @@ QuasiPolynomial QuasiPolynomial::simplify() {
   return QuasiPolynomial(getNumInputs(), newCoeffs, newAffine);
 }
 
-// Check the constant term of the quasipolynomial against a constant.
 Fraction QuasiPolynomial::getConstantTerm() {
   Fraction t = 0;
   for (unsigned i = 0, e = coefficients.size(); i < e; ++i) {

>From c2b367caddc32b76c1c9e0679589835a1ef6d4b6 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 13 Jan 2024 18:14:39 +0530
Subject: [PATCH 12/18] Minor fixes

---
 mlir/lib/Analysis/Presburger/Barvinok.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index aacfc45e8b9bf1..233fe0412fe05b 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -223,6 +223,7 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
 /// barvinokalgorithm-latte1.pdf, p. 1285
 QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
     unsigned power, ArrayRef<QuasiPolynomial> num, ArrayRef<Fraction> den) {
+  assert(den.size() != 0 && "division by empty denominator in rational function!");
 
   unsigned numParam = num[0].getNumInputs();
   for (const QuasiPolynomial &qp : num)
@@ -238,7 +239,7 @@ QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
     if (i < num.size())
       coefficients[i] = num[i];
 
-    unsigned limit = fmin(i, den.size() - 1);
+    unsigned limit = std::min<unsigned long>(i, den.size() - 1);
 
     for (unsigned j = 1; j <= limit; ++j)
       coefficients[i] = coefficients[i] -
@@ -246,5 +247,5 @@ QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
 
     coefficients[i] = coefficients[i] / den[0];
   }
-  return (coefficients[power]).simplify();
+  return coefficients[power].simplify();
 }
\ No newline at end of file

>From 47040199c2b5f432e04006b692133b66c8745b42 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 13 Jan 2024 18:20:38 +0530
Subject: [PATCH 13/18] Formatting

---
 mlir/lib/Analysis/Presburger/Barvinok.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 233fe0412fe05b..2935d219af5e1d 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -156,7 +156,7 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
 /// vs ++ [v] means the vector vs with the new element v appended to it.
 ///
 /// We proceed iteratively; for steps d = 0, ... n-1, we construct a vector
-/// which is not orthogonal to any of {x_1[:i], ..., x_n[:i]}, ignoring
+/// which is not orthogonal to any of {x_1[:d], ..., x_n[:d]}, ignoring
 /// the null vectors.
 /// At step d = 0, we let vs = [1]. Clearly this is not orthogonal to
 /// any vector in the set {x_1[0], ..., x_n[0]}, except the null ones,
@@ -223,7 +223,8 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
 /// barvinokalgorithm-latte1.pdf, p. 1285
 QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
     unsigned power, ArrayRef<QuasiPolynomial> num, ArrayRef<Fraction> den) {
-  assert(den.size() != 0 && "division by empty denominator in rational function!");
+  assert(den.size() != 0 &&
+         "division by empty denominator in rational function!");
 
   unsigned numParam = num[0].getNumInputs();
   for (const QuasiPolynomial &qp : num)

>From 5866969daef2dae0205fa5772f8186a171275839 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 13 Jan 2024 18:21:47 +0530
Subject: [PATCH 14/18] Fix doc

---
 mlir/lib/Analysis/Presburger/Barvinok.cpp | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 2935d219af5e1d..d7a77cc3ff19fa 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -161,14 +161,14 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
 /// At step d = 0, we let vs = [1]. Clearly this is not orthogonal to
 /// any vector in the set {x_1[0], ..., x_n[0]}, except the null ones,
 /// which we ignore.
-/// At step d = t + 1, we need a number v
-/// s.t. <x_i[:t+1], vs++[v]> != 0 for all i.
-/// => <x_i[:t], vs> + x_i[t+1]*v != 0
-/// => v != - <x_i[:t], vs> / x_i[t+1]
+/// At step d > 0 , we need a number v
+/// s.t. <x_i[:d], vs++[v]> != 0 for all i.
+/// => <x_i[:d-1], vs> + x_i[d]*v != 0
+/// => v != - <x_i[:d-1], vs> / x_i[d]
 /// We compute this value for all x_i, and then
 /// set v to be the maximum element of this set plus one. Thus
 /// v is outside the set as desired, and we append it to vs
-/// to obtain the result of the t+1'th step.
+/// to obtain the result of the d'th step.
 Point mlir::presburger::detail::getNonOrthogonalVector(
     std::vector<Point> vectors) {
   unsigned dim = vectors[0].size();
@@ -223,8 +223,7 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
 /// barvinokalgorithm-latte1.pdf, p. 1285
 QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
     unsigned power, ArrayRef<QuasiPolynomial> num, ArrayRef<Fraction> den) {
-  assert(den.size() != 0 &&
-         "division by empty denominator in rational function!");
+  assert(den.size() != 0 && "division by empty denominator in rational function!");
 
   unsigned numParam = num[0].getNumInputs();
   for (const QuasiPolynomial &qp : num)

>From a6dfd7e92ccaad346f1b05f04bf20006f559287c Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 13 Jan 2024 18:24:27 +0530
Subject: [PATCH 15/18] Add assert for vector sizes

---
 mlir/include/mlir/Analysis/Presburger/Barvinok.h | 2 +-
 mlir/lib/Analysis/Presburger/Barvinok.cpp        | 7 +++++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 72cbca71ba5a94..edee19f0e1a535 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -88,7 +88,7 @@ GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign,
 /// i.e., has nonzero dot product with those of the given vectors
 /// that are not null.
 /// If any of the vectors is null, it is ignored.
-Point getNonOrthogonalVector(std::vector<Point> vectors);
+Point getNonOrthogonalVector(ArrayRef<Point> vectors);
 
 /// Find the coefficient of a given power of s in a rational function
 /// given by P(s)/Q(s), where
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index d7a77cc3ff19fa..fc433f8ced5570 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -170,8 +170,10 @@ GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction(
 /// v is outside the set as desired, and we append it to vs
 /// to obtain the result of the d'th step.
 Point mlir::presburger::detail::getNonOrthogonalVector(
-    std::vector<Point> vectors) {
+    ArrayRef<Point> vectors) {
   unsigned dim = vectors[0].size();
+  for (const Point &vector : vectors)
+    assert(vector.size() == dim && "all vectors need to be the same size!");
 
   SmallVector<Fraction> newPoint = {Fraction(1, 1)};
   std::vector<Fraction> lowerDimDotProducts;
@@ -223,7 +225,8 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
 /// barvinokalgorithm-latte1.pdf, p. 1285
 QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
     unsigned power, ArrayRef<QuasiPolynomial> num, ArrayRef<Fraction> den) {
-  assert(den.size() != 0 && "division by empty denominator in rational function!");
+  assert(den.size() != 0 &&
+         "division by empty denominator in rational function!");
 
   unsigned numParam = num[0].getNumInputs();
   for (const QuasiPolynomial &qp : num)

>From 6b86a403d1bc263daf690a51295dda9f2c151137 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 13 Jan 2024 18:29:11 +0530
Subject: [PATCH 16/18] Reorg

---
 mlir/lib/Analysis/Presburger/Barvinok.cpp | 25 +++++++++--------------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index fc433f8ced5570..a5ea4bb6dd4e20 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -178,33 +178,28 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
   SmallVector<Fraction> newPoint = {Fraction(1, 1)};
   std::vector<Fraction> lowerDimDotProducts;
   Fraction dotProduct;
-  Fraction maxDisallowedValue = Fraction(-1, 0),
+  Fraction maxDisallowedValue = -Fraction(1, 0),
            disallowedValue = Fraction(0, 1);
   Fraction newValue;
 
   for (unsigned d = 1; d < dim; ++d) {
-    lowerDimDotProducts.clear();
 
-    // Compute the set of dot products <x_i[:d-1], vs> for each i.
+    // Compute the disallowed values  - <x_i[:d-1], vs> / x_i[d] for each i.
+    maxDisallowedValue = -Fraction(1, 0);
     for (const Point &vector : vectors) {
+      if (vector[d] == 0)
+        continue;
       dotProduct = Fraction(0, 1);
-      for (unsigned i = 0; i < d; i++)
+      for (unsigned i = 0; i < d; ++i)
         dotProduct = dotProduct + vector[i] * newPoint[i];
-      lowerDimDotProducts.push_back(dotProduct);
-    }
+      disallowedValue = -dotProduct / vector[d];
 
-    // Compute - <x_i[:d-1], vs> / x_i[d] for each i,
-    // and find the biggest such value.
-    for (unsigned i = 0, e = vectors.size(); i < e; ++i) {
-      if (vectors[i][d] == 0)
-        continue;
-      disallowedValue = -lowerDimDotProducts[i] / vectors[i][d];
-      if (maxDisallowedValue < disallowedValue)
-        maxDisallowedValue = disallowedValue;
+      // Find the biggest such value
+      maxDisallowedValue = std::max(maxDisallowedValue, disallowedValue);
     }
 
     newValue = Fraction(ceil(maxDisallowedValue + Fraction(1, 1)), 1);
-    newPoint.append(1, newValue);
+    newPoint.push_back(newValue);
   }
   return newPoint;
 }

>From 575feff1d1333e368caaa101cbcac99d31768c8e Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 13 Jan 2024 18:38:36 +0530
Subject: [PATCH 17/18] refactor with dotp

---
 mlir/lib/Analysis/Presburger/Barvinok.cpp        | 9 ++++-----
 mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp | 3 +--
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index a5ea4bb6dd4e20..75251ab2891919 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -177,7 +177,7 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
 
   SmallVector<Fraction> newPoint = {Fraction(1, 1)};
   std::vector<Fraction> lowerDimDotProducts;
-  Fraction dotProduct;
+  Fraction dotP;
   Fraction maxDisallowedValue = -Fraction(1, 0),
            disallowedValue = Fraction(0, 1);
   Fraction newValue;
@@ -189,10 +189,9 @@ Point mlir::presburger::detail::getNonOrthogonalVector(
     for (const Point &vector : vectors) {
       if (vector[d] == 0)
         continue;
-      dotProduct = Fraction(0, 1);
-      for (unsigned i = 0; i < d; ++i)
-        dotProduct = dotProduct + vector[i] * newPoint[i];
-      disallowedValue = -dotProduct / vector[d];
+      dotP = dotProduct(ArrayRef(vector).slice(0, d), newPoint);
+      disallowedValue =
+          -dotProduct(ArrayRef(vector).slice(0, d), newPoint) / vector[d];
 
       // Find the biggest such value
       maxDisallowedValue = std::max(maxDisallowedValue, disallowedValue);
diff --git a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
index f6ee7c8638c197..21854b4ce8d526 100644
--- a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
+++ b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
@@ -122,9 +122,8 @@ QuasiPolynomial QuasiPolynomial::simplify() {
 
 Fraction QuasiPolynomial::getConstantTerm() {
   Fraction t = 0;
-  for (unsigned i = 0, e = coefficients.size(); i < e; ++i) {
+  for (unsigned i = 0, e = coefficients.size(); i < e; ++i)
     if (affine[i].size() == 0)
       t += coefficients[i];
-  }
   return t;
 }

>From 1fb3e67104a70c953f97c8b0bbe70d524634267d Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 13 Jan 2024 18:45:25 +0530
Subject: [PATCH 18/18] Fix doc

---
 mlir/lib/Analysis/Presburger/Barvinok.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 75251ab2891919..8b7edef72bf395 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -233,6 +233,8 @@ QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction(
   coefficients[0] = num[0] / den[0];
 
   for (unsigned i = 1; i <= power; ++i) {
+    // If the i'th power is not in the numerator, coefficients[i]
+    // remains zero.
     if (i < num.size())
       coefficients[i] = num[i];
 



More information about the Mlir-commits mailing list