[Mlir-commits] [mlir] [MLIR][Presburger] Generating functions and quasi-polynomials for Barvinok's algorithm (PR #75702)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Dec 18 05:53:39 PST 2023


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

>From b65a078edbbd8d711b1bb9ec12b938f47c550e9a Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 16 Dec 2023 19:37:00 +0530
Subject: [PATCH 01/15] Definitions for gf and qp classes

---
 .../mlir/Analysis/Presburger/Barvinok.h       | 229 ++++++++++++++++++
 1 file changed, 229 insertions(+)
 create mode 100644 mlir/include/mlir/Analysis/Presburger/Barvinok.h

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
new file mode 100644
index 00000000000000..3ee9d5dc452d0e
--- /dev/null
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -0,0 +1,229 @@
+//===- Barvinok.h - Barvinok's Algorithm -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Functions and classes for Barvinok's algorithm in MLIR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_ANALYSIS_PRESBURGER_BARVINOK_H
+#define MLIR_ANALYSIS_PRESBURGER_BARVINOK_H
+
+#include "mlir/Analysis/Presburger/Fraction.h"
+#include "mlir/Analysis/Presburger/IntegerRelation.h"
+#include "mlir/Analysis/Presburger/Matrix.h"
+#include "mlir/Analysis/Presburger/PresburgerSpace.h"
+#include "mlir/Analysis/Presburger/Utils.h"
+#include "mlir/Support/LogicalResult.h"
+#include <optional>
+
+namespace mlir {
+namespace presburger {
+
+// The H (inequality) representation of both general
+// polyhedra and cones specifically is an integer relation.
+using PolyhedronH = IntegerRelation;
+using ConeH = PolyhedronH;
+
+// The V (generator) representation of both general
+// polyhedra and cones specifically is simply a matrix
+// whose rows are the generators.
+using PolyhedronV = Matrix<MPInt>;
+using ConeV = PolyhedronV;
+
+// A parametric point is a vector, each of whose elements
+// is an affine function of n parameters. Each row
+// in the matrix represents the affine function and
+// has n+1 elements.
+using ParamPoint = Matrix<Fraction>;
+
+// A point is simply a vector.
+using Point = SmallVector<Fraction>;
+
+// A class to describe the type of generating function
+// used to enumerate the integer points in a polytope.
+// Consists of a set of terms, where the ith term has
+// * a sign, ±1, stored in `signs[i]`
+// * a numerator, of the form x^{n},
+//      where n, stored in `numerators[i]`,
+//      is a parametric point (a vertex).
+// * a denominator, of the form (1 - x^{d1})...(1 - x^{dn}),
+//      where each dj, stored in `denominators[i][j]`,
+//      is a vector (a generator).
+class GeneratingFunction {
+public:
+  GeneratingFunction(SmallVector<int, 16> s, std::vector<ParamPoint> nums,
+                     std::vector<std::vector<Point>> dens)
+      : signs(s), numerators(nums), denominators(dens){};
+
+  unsigned getNumParams() {
+    for (auto term : numerators)
+      return (term.getNumColumns() - 1);
+    return -1;
+  }
+
+  bool operator==(const GeneratingFunction &gf) const {
+    if (signs != gf.signs || numerators != gf.numerators ||
+        denominators != gf.denominators)
+      return false;
+    return true;
+  }
+
+  GeneratingFunction operator+(const GeneratingFunction &gf) {
+    bool sameNumParams = (getNumParams() == -1) || (gf.getNumParams() == -1) ||
+                         (getNumParams() == gf.getNumParams());
+    assert(
+        sameNumParams &&
+        "two generators with different numbers of parameters cannot be added!");
+    signs.insert(signs.end(), gf.signs.begin(), gf.signs.end());
+    numerators.insert(numerators.end(), gf.numerators.begin(),
+                      gf.numerators.end());
+    denominators.insert(denominators.end(), gf.denominators.begin(),
+                        gf.denominators.end());
+    return *this;
+  }
+
+  llvm::raw_ostream &print(llvm::raw_ostream &os) const {
+    for (unsigned i = 0; i < signs.size(); i++) {
+      if (signs[i] == 1)
+        os << "+";
+      else
+        os << "-";
+
+      os << "*(x^[";
+      for (unsigned j = 0; j < numerators[i].size() - 1; j++)
+        os << numerators[i][j] << ",";
+      os << numerators[i][numerators[i].size() - 1] << "])/";
+
+      for (Point den : denominators[i]) {
+        os << "(x^[";
+        for (unsigned j = 0; j < den.size(); j++)
+          os << den[j] << ",";
+        os << den[den.size() - 1] << "])";
+      }
+    }
+    return os;
+  }
+
+  SmallVector<int, 16> signs;
+  std::vector<ParamPoint> numerators;
+  std::vector<std::vector<Point>> denominators;
+};
+
+// A class to describe the quasi-polynomials obtained by
+// substituting the unit vector in the type of generating
+// function described above.
+// Consists of a set of terms.
+// The ith term is a constant `coefficients[i]`, multiplied
+// by the product of a set of affine functions on n parameters.
+class QuasiPolynomial {
+public:
+  QuasiPolynomial(SmallVector<Fraction> coeffs = {},
+                  std::vector<std::vector<SmallVector<Fraction>>> aff = {})
+      : coefficients(coeffs), affine(aff){};
+
+  QuasiPolynomial(Fraction cons) : coefficients({cons}), affine({{}}){};
+
+  QuasiPolynomial(QuasiPolynomial const &) = default;
+
+  SmallVector<Fraction> coefficients;
+  std::vector<std::vector<SmallVector<Fraction>>> affine;
+
+  // Find the number of parameters involved in the polynomial
+  // from the dimensionality of the affine functions.
+  unsigned getNumParams() {
+    // Find the first term which involves some affine function.
+    for (auto term : affine) {
+      if (term.size() == 0)
+        continue;
+      // The number of elements in the affine function is
+      // one more than the number of parameters.
+      return (term[0].size() - 1);
+    }
+    // The polynomial can be treated as having any number
+    // of parameters.
+    return -1;
+  }
+
+  QuasiPolynomial operator+(const QuasiPolynomial &x) {
+    bool sameNumParams = (getNumParams() == -1) || (x.getNumParams() == -1) ||
+                         (getNumParams() == x.getNumParams());
+    assert(sameNumParams && "two quasi-polynomials with different numbers of "
+                            "parameters cannot be added!");
+    coefficients.append(x.coefficients);
+    affine.insert(affine.end(), x.affine.begin(), x.affine.end());
+    return *this;
+  }
+
+  QuasiPolynomial operator-(const QuasiPolynomial &x) {
+    bool sameNumParams = (getNumParams() == -1) || (x.getNumParams() == -1) ||
+                         (getNumParams() == x.getNumParams());
+    assert(sameNumParams && "two quasi-polynomials with different numbers of "
+                            "parameters cannot be subtracted!");
+    QuasiPolynomial qp(x.coefficients, x.affine);
+    for (unsigned i = 0; i < x.coefficients.size(); i++)
+      qp.coefficients[i] = -qp.coefficients[i];
+    return (*this + qp);
+  }
+
+  QuasiPolynomial operator*(const QuasiPolynomial &x) {
+    bool sameNumParams = (getNumParams() == -1) || (x.getNumParams() == -1) ||
+                         (getNumParams() == x.getNumParams());
+    assert(sameNumParams && "two quasi-polynomials with different numbers of "
+                            "parameters cannot be multiplied!");
+    QuasiPolynomial qp();
+    std::vector<SmallVector<Fraction>> product;
+    for (unsigned i = 0; i < coefficients.size(); i++) {
+      for (unsigned j = 0; j < x.coefficients.size(); j++) {
+        qp.coefficients.append({coefficients[i] * x.coefficients[j]});
+
+        product.clear();
+        product.insert(product.end(), affine[i].begin(), affine[i].end());
+        product.insert(product.end(), x.affine[j].begin(), x.affine[j].end());
+
+        qp.affine.push_back(product);
+      }
+    }
+
+    return qp;
+  }
+
+  QuasiPolynomial operator/(Fraction x) {
+    assert(x != 0 && "division by zero!");
+    for (unsigned i = 0; i < coefficients.size(); i++)
+      coefficients[i] = coefficients[i] / x;
+    return *this;
+  };
+
+  // Removes terms which evaluate to zero from the expression.
+  QuasiPolynomial reduce() {
+    SmallVector<Fraction> newCoeffs({});
+    std::vector<std::vector<SmallVector<Fraction>>> newAffine({});
+    bool prodIsNonz, sumIsNonz;
+    for (unsigned i = 0; i < coefficients.size(); i++) {
+      prodIsNonz = true;
+      for (unsigned j = 0; j < affine[i].size(); j++) {
+        sumIsNonz = false;
+        for (unsigned k = 0; k < affine[i][j].size(); k++)
+          if (affine[i][j][k] != Fraction(0, 1))
+            sumIsNonz = true;
+        if (sumIsNonz == false)
+          prodIsNonz = false;
+      }
+      if (prodIsNonz == true && coefficients[i] != Fraction(0, 1)) {
+        newCoeffs.append({coefficients[i]});
+        newAffine.push_back({affine[i]});
+      }
+    }
+    return QuasiPolynomial(newCoeffs, newAffine);
+  }
+};
+
+} // namespace presburger
+} // namespace mlir
+
+#endif // MLIR_ANALYSIS_PRESBURGER_BARVINOK_H
\ No newline at end of file

>From 6101acb97250f3455bf3aaf4cf3b88165b2c740b Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sat, 16 Dec 2023 21:02:51 +0530
Subject: [PATCH 02/15] Comments

---
 mlir/include/mlir/Analysis/Presburger/Barvinok.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 3ee9d5dc452d0e..d753f97d3bcf74 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -60,9 +60,15 @@ class GeneratingFunction {
                      std::vector<std::vector<Point>> dens)
       : signs(s), numerators(nums), denominators(dens){};
 
+  // Find the number of parameters involved in the function
+  // from the dimensionality of the affine functions.
   unsigned getNumParams() {
     for (auto term : numerators)
+      // The number of elements in the affine function is
+      // one more than the number of parameters.
       return (term.getNumColumns() - 1);
+    // The polynomial can be treated as having any number
+    // of parameters.
     return -1;
   }
 

>From 5d425bd2c83576f3ba389aed3aa3291375dab185 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sun, 17 Dec 2023 01:27:14 +0530
Subject: [PATCH 03/15] Miscellaneous reformatting

---
 .../mlir/Analysis/Presburger/Barvinok.h       | 20 +++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index d753f97d3bcf74..bbd4baf3dd8cd8 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -56,9 +56,9 @@ using Point = SmallVector<Fraction>;
 //      is a vector (a generator).
 class GeneratingFunction {
 public:
-  GeneratingFunction(SmallVector<int, 16> s, std::vector<ParamPoint> nums,
+  GeneratingFunction(SmallVector<int, 16> signs, std::vector<ParamPoint> nums,
                      std::vector<std::vector<Point>> dens)
-      : signs(s), numerators(nums), denominators(dens){};
+      : signs(signs), numerators(nums), denominators(dens) {}
 
   // Find the number of parameters involved in the function
   // from the dimensionality of the affine functions.
@@ -96,18 +96,18 @@ class GeneratingFunction {
   llvm::raw_ostream &print(llvm::raw_ostream &os) const {
     for (unsigned i = 0; i < signs.size(); i++) {
       if (signs[i] == 1)
-        os << "+";
+        os << " + ";
       else
-        os << "-";
+        os << " - ";
 
-      os << "*(x^[";
+      os << "(x^[";
       for (unsigned j = 0; j < numerators[i].size() - 1; j++)
         os << numerators[i][j] << ",";
-      os << numerators[i][numerators[i].size() - 1] << "])/";
+      os << numerators[i].back() << "])/";
 
       for (Point den : denominators[i]) {
         os << "(x^[";
-        for (unsigned j = 0; j < den.size(); j++)
+        for (unsigned j = 0; j < den.size() - 1; j++)
           os << den[j] << ",";
         os << den[den.size() - 1] << "])";
       }
@@ -115,7 +115,7 @@ class GeneratingFunction {
     return os;
   }
 
-  SmallVector<int, 16> signs;
+  SmallVector<int, 8> signs;
   std::vector<ParamPoint> numerators;
   std::vector<std::vector<Point>> denominators;
 };
@@ -130,9 +130,9 @@ class QuasiPolynomial {
 public:
   QuasiPolynomial(SmallVector<Fraction> coeffs = {},
                   std::vector<std::vector<SmallVector<Fraction>>> aff = {})
-      : coefficients(coeffs), affine(aff){};
+      : coefficients(coeffs), affine(aff) {}
 
-  QuasiPolynomial(Fraction cons) : coefficients({cons}), affine({{}}){};
+  QuasiPolynomial(Fraction cons) : coefficients({cons}), affine({{}}) {}
 
   QuasiPolynomial(QuasiPolynomial const &) = default;
 

>From 883e99356b4875c83eb79bba4bf591d5f5a95444 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sun, 17 Dec 2023 01:31:44 +0530
Subject: [PATCH 04/15] Remove superfluous == operator

---
 mlir/include/mlir/Analysis/Presburger/Barvinok.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index bbd4baf3dd8cd8..d99ec62bd93a41 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -72,13 +72,6 @@ class GeneratingFunction {
     return -1;
   }
 
-  bool operator==(const GeneratingFunction &gf) const {
-    if (signs != gf.signs || numerators != gf.numerators ||
-        denominators != gf.denominators)
-      return false;
-    return true;
-  }
-
   GeneratingFunction operator+(const GeneratingFunction &gf) {
     bool sameNumParams = (getNumParams() == -1) || (gf.getNumParams() == -1) ||
                          (getNumParams() == gf.getNumParams());

>From 2812e75ff47666d56053c1396b9157d52031ed88 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sun, 17 Dec 2023 01:40:04 +0530
Subject: [PATCH 05/15] Use SmallVector::append() instead of insert()

---
 mlir/include/mlir/Analysis/Presburger/Barvinok.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index d99ec62bd93a41..b7dd528f92ffd3 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -78,7 +78,7 @@ class GeneratingFunction {
     assert(
         sameNumParams &&
         "two generators with different numbers of parameters cannot be added!");
-    signs.insert(signs.end(), gf.signs.begin(), gf.signs.end());
+    signs.append(gf.signs);
     numerators.insert(numerators.end(), gf.numerators.begin(),
                       gf.numerators.end());
     denominators.insert(denominators.end(), gf.denominators.begin(),

>From 625b1b1bbe0c95addf9af0a00d2bbb7aa470d8a7 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sun, 17 Dec 2023 01:51:01 +0530
Subject: [PATCH 06/15] Refactor numParam as private attribute

---
 .../mlir/Analysis/Presburger/Barvinok.h       | 87 +++++++++----------
 1 file changed, 43 insertions(+), 44 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index b7dd528f92ffd3..64e5d98b20adbc 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -56,28 +56,24 @@ using Point = SmallVector<Fraction>;
 //      is a vector (a generator).
 class GeneratingFunction {
 public:
-  GeneratingFunction(SmallVector<int, 16> signs, std::vector<ParamPoint> nums,
+  GeneratingFunction(unsigned numParam, SmallVector<int, 8> signs,
+                     std::vector<ParamPoint> nums,
                      std::vector<std::vector<Point>> dens)
-      : signs(signs), numerators(nums), denominators(dens) {}
+      : numParam(numParam), signs(signs), numerators(nums), denominators(dens) {
+    for (auto term : numerators)
+      assert(term.getNumColumns() - 1 == numParam &&
+             "dimensionality of numerator exponents does not match number of "
+             "parameters!");
+  }
 
   // Find the number of parameters involved in the function
   // from the dimensionality of the affine functions.
-  unsigned getNumParams() {
-    for (auto term : numerators)
-      // The number of elements in the affine function is
-      // one more than the number of parameters.
-      return (term.getNumColumns() - 1);
-    // The polynomial can be treated as having any number
-    // of parameters.
-    return -1;
-  }
+  unsigned getNumParams() { return numParam; }
 
   GeneratingFunction operator+(const GeneratingFunction &gf) {
-    bool sameNumParams = (getNumParams() == -1) || (gf.getNumParams() == -1) ||
-                         (getNumParams() == gf.getNumParams());
-    assert(
-        sameNumParams &&
-        "two generators with different numbers of parameters cannot be added!");
+    assert(numParam == gf.getNumParams() &&
+           "two generating functions with different numbers of parameters "
+           "cannot be added!");
     signs.append(gf.signs);
     numerators.insert(numerators.end(), gf.numerators.begin(),
                       gf.numerators.end());
@@ -111,6 +107,9 @@ class GeneratingFunction {
   SmallVector<int, 8> signs;
   std::vector<ParamPoint> numerators;
   std::vector<std::vector<Point>> denominators;
+
+private:
+  unsigned numParam;
 };
 
 // A class to describe the quasi-polynomials obtained by
@@ -121,38 +120,32 @@ class GeneratingFunction {
 // by the product of a set of affine functions on n parameters.
 class QuasiPolynomial {
 public:
-  QuasiPolynomial(SmallVector<Fraction> coeffs = {},
+  QuasiPolynomial(unsigned numParam, SmallVector<Fraction> coeffs = {},
                   std::vector<std::vector<SmallVector<Fraction>>> aff = {})
-      : coefficients(coeffs), affine(aff) {}
+      : numParam(numParam), coefficients(coeffs), affine(aff) {
+    // Find the first term which involves some affine function.
+    for (auto term : affine)
+      if (term.size() == 0)
+        continue;
+    // The number of elements in the affine function is
+    // one more than the number of parameters.
+    assert(term[0].size() - 1 == numParam &&
+           "dimensionality of affine functions does not match number of "
+           "parameters!")
+  }
 
   QuasiPolynomial(Fraction cons) : coefficients({cons}), affine({{}}) {}
 
   QuasiPolynomial(QuasiPolynomial const &) = default;
 
-  SmallVector<Fraction> coefficients;
-  std::vector<std::vector<SmallVector<Fraction>>> affine;
-
   // Find the number of parameters involved in the polynomial
   // from the dimensionality of the affine functions.
-  unsigned getNumParams() {
-    // Find the first term which involves some affine function.
-    for (auto term : affine) {
-      if (term.size() == 0)
-        continue;
-      // The number of elements in the affine function is
-      // one more than the number of parameters.
-      return (term[0].size() - 1);
-    }
-    // The polynomial can be treated as having any number
-    // of parameters.
-    return -1;
-  }
+  unsigned getNumParams() { return numParam; }
 
   QuasiPolynomial operator+(const QuasiPolynomial &x) {
-    bool sameNumParams = (getNumParams() == -1) || (x.getNumParams() == -1) ||
-                         (getNumParams() == x.getNumParams());
-    assert(sameNumParams && "two quasi-polynomials with different numbers of "
-                            "parameters cannot be added!");
+    assert(numParam == x.getNumParams() &&
+           "two quasi-polynomials with different numbers of parameters cannot "
+           "be added!");
     coefficients.append(x.coefficients);
     affine.insert(affine.end(), x.affine.begin(), x.affine.end());
     return *this;
@@ -161,8 +154,9 @@ class QuasiPolynomial {
   QuasiPolynomial operator-(const QuasiPolynomial &x) {
     bool sameNumParams = (getNumParams() == -1) || (x.getNumParams() == -1) ||
                          (getNumParams() == x.getNumParams());
-    assert(sameNumParams && "two quasi-polynomials with different numbers of "
-                            "parameters cannot be subtracted!");
+    assert(numParam == x.getNumParams() &&
+           "two quasi-polynomials with different numbers of parameters cannot "
+           "be subtracted!");
     QuasiPolynomial qp(x.coefficients, x.affine);
     for (unsigned i = 0; i < x.coefficients.size(); i++)
       qp.coefficients[i] = -qp.coefficients[i];
@@ -170,10 +164,9 @@ class QuasiPolynomial {
   }
 
   QuasiPolynomial operator*(const QuasiPolynomial &x) {
-    bool sameNumParams = (getNumParams() == -1) || (x.getNumParams() == -1) ||
-                         (getNumParams() == x.getNumParams());
-    assert(sameNumParams && "two quasi-polynomials with different numbers of "
-                            "parameters cannot be multiplied!");
+    assert(numParam = x.getNumParams() &&
+                      "two quasi-polynomials with different numbers of "
+                      "parameters cannot be multiplied!");
     QuasiPolynomial qp();
     std::vector<SmallVector<Fraction>> product;
     for (unsigned i = 0; i < coefficients.size(); i++) {
@@ -220,6 +213,12 @@ class QuasiPolynomial {
     }
     return QuasiPolynomial(newCoeffs, newAffine);
   }
+
+  SmallVector<Fraction> coefficients;
+  std::vector<std::vector<SmallVector<Fraction>>> affine;
+
+private:
+  unsigned numParam;
 };
 
 } // namespace presburger

>From 94b5996de245280e1e9cd60673d46f793b995416 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sun, 17 Dec 2023 12:49:32 +0530
Subject: [PATCH 07/15] Formatting fixes

---
 .../mlir/Analysis/Presburger/Barvinok.h       | 68 +++++++++++--------
 1 file changed, 39 insertions(+), 29 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 64e5d98b20adbc..80ab8fb4df1ef7 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -1,4 +1,4 @@
-//===- Barvinok.h - Barvinok's Algorithm -----------*- C++ -*-===//
+//===- Barvinok.h - Barvinok's Algorithm ------------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -54,13 +54,21 @@ using Point = SmallVector<Fraction>;
 // * a denominator, of the form (1 - x^{d1})...(1 - x^{dn}),
 //      where each dj, stored in `denominators[i][j]`,
 //      is a vector (a generator).
+//
+// Represents functions f : Q^n -> Q of the form
+//
+// f(x) = \sum_i s_i * (x^n_i(p)) / (\prod_j (1 - x^d_{ij})
+//
+// where s_i is ±1,
+// n_i \in (Q^d -> Q)^n is an n-vector of affine functions on d parameters, and
+// g_{ij} \in Q^n are vectors.
 class GeneratingFunction {
 public:
   GeneratingFunction(unsigned numParam, SmallVector<int, 8> signs,
                      std::vector<ParamPoint> nums,
                      std::vector<std::vector<Point>> dens)
       : numParam(numParam), signs(signs), numerators(nums), denominators(dens) {
-    for (auto term : numerators)
+    for (const auto &term : numerators)
       assert(term.getNumColumns() - 1 == numParam &&
              "dimensionality of numerator exponents does not match number of "
              "parameters!");
@@ -83,20 +91,20 @@ class GeneratingFunction {
   }
 
   llvm::raw_ostream &print(llvm::raw_ostream &os) const {
-    for (unsigned i = 0; i < signs.size(); i++) {
+    for (unsigned i = 0, e = signs.size(); i < e; i++) {
       if (signs[i] == 1)
         os << " + ";
       else
         os << " - ";
 
-      os << "(x^[";
-      for (unsigned j = 0; j < numerators[i].size() - 1; j++)
+      os << "x^[";
+      for (unsigned j = 0, e = numerators[i].size(); j < e - 1; j++)
         os << numerators[i][j] << ",";
-      os << numerators[i].back() << "])/";
+      os << numerators[i].back() << "]/";
 
       for (Point den : denominators[i]) {
         os << "(x^[";
-        for (unsigned j = 0; j < den.size() - 1; j++)
+        for (unsigned j = 0, e = den.size(); j < e - 1; j++)
           os << den[j] << ",";
         os << den[den.size() - 1] << "])";
       }
@@ -118,28 +126,30 @@ class GeneratingFunction {
 // Consists of a set of terms.
 // The ith term is a constant `coefficients[i]`, multiplied
 // by the product of a set of affine functions on n parameters.
+// Represents functions f : Q^n -> Q of the form
+//
+// f(x) = \sum_i c_i * \prod_j ⌊g_{ij}(x)⌋
+//
+// where c_i \in Q and
+// g_{ij} : Q^n -> Q are affine functionals.
 class QuasiPolynomial {
 public:
   QuasiPolynomial(unsigned numParam, SmallVector<Fraction> coeffs = {},
                   std::vector<std::vector<SmallVector<Fraction>>> aff = {})
       : numParam(numParam), coefficients(coeffs), affine(aff) {
     // Find the first term which involves some affine function.
-    for (auto term : affine)
+    for (auto term : affine) {
       if (term.size() == 0)
         continue;
-    // The number of elements in the affine function is
-    // one more than the number of parameters.
-    assert(term[0].size() - 1 == numParam &&
-           "dimensionality of affine functions does not match number of "
-           "parameters!")
+      // The number of elements in the affine function is
+      // one more than the number of parameters.
+      assert(term[0].size() - 1 == numParam &&
+             "dimensionality of affine functions does not match number of "
+             "parameters!")
+    }
   }
 
-  QuasiPolynomial(Fraction cons) : coefficients({cons}), affine({{}}) {}
-
-  QuasiPolynomial(QuasiPolynomial const &) = default;
-
-  // Find the number of parameters involved in the polynomial
-  // from the dimensionality of the affine functions.
+  // Find the number of parameters involved in the polynomial.
   unsigned getNumParams() { return numParam; }
 
   QuasiPolynomial operator+(const QuasiPolynomial &x) {
@@ -158,7 +168,7 @@ class QuasiPolynomial {
            "two quasi-polynomials with different numbers of parameters cannot "
            "be subtracted!");
     QuasiPolynomial qp(x.coefficients, x.affine);
-    for (unsigned i = 0; i < x.coefficients.size(); i++)
+    for (unsigned i = 0, e = x.coefficients.size(); i < e; i++)
       qp.coefficients[i] = -qp.coefficients[i];
     return (*this + qp);
   }
@@ -169,8 +179,8 @@ class QuasiPolynomial {
                       "parameters cannot be multiplied!");
     QuasiPolynomial qp();
     std::vector<SmallVector<Fraction>> product;
-    for (unsigned i = 0; i < coefficients.size(); i++) {
-      for (unsigned j = 0; j < x.coefficients.size(); j++) {
+    for (unsigned i = 0, e = coefficients.size(); i < e; i++) {
+      for (unsigned j = 0, e = x.coefficients.size(); j < e; j++) {
         qp.coefficients.append({coefficients[i] * x.coefficients[j]});
 
         product.clear();
@@ -186,27 +196,27 @@ class QuasiPolynomial {
 
   QuasiPolynomial operator/(Fraction x) {
     assert(x != 0 && "division by zero!");
-    for (unsigned i = 0; i < coefficients.size(); i++)
-      coefficients[i] = coefficients[i] / x;
+    for (Fraction &coeff : coefficients)
+      coeff /= x;
     return *this;
   };
 
   // Removes terms which evaluate to zero from the expression.
-  QuasiPolynomial reduce() {
+  QuasiPolynomial simplify() {
     SmallVector<Fraction> newCoeffs({});
     std::vector<std::vector<SmallVector<Fraction>>> newAffine({});
     bool prodIsNonz, sumIsNonz;
-    for (unsigned i = 0; i < coefficients.size(); i++) {
+    for (unsigned i = 0, e = coefficients.size(); i < e; i++) {
       prodIsNonz = true;
-      for (unsigned j = 0; j < affine[i].size(); j++) {
+      for (unsigned j = 0, e = affine[i].size(); j < e; j++) {
         sumIsNonz = false;
-        for (unsigned k = 0; k < affine[i][j].size(); k++)
+        for (unsigned k = 0, e = affine[i][j].size(); k < e; k++)
           if (affine[i][j][k] != Fraction(0, 1))
             sumIsNonz = true;
         if (sumIsNonz == false)
           prodIsNonz = false;
       }
-      if (prodIsNonz == true && coefficients[i] != Fraction(0, 1)) {
+      if (prodIsNonz && coefficients[i] != Fraction(0, 1)) {
         newCoeffs.append({coefficients[i]});
         newAffine.push_back({affine[i]});
       }

>From f005fdc6cdac0b7b859066e5d8d3cd6c47b9a312 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sun, 17 Dec 2023 12:51:58 +0530
Subject: [PATCH 08/15] Add type instead of auto

---
 mlir/include/mlir/Analysis/Presburger/Barvinok.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 80ab8fb4df1ef7..682099ed84b029 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -68,7 +68,7 @@ class GeneratingFunction {
                      std::vector<ParamPoint> nums,
                      std::vector<std::vector<Point>> dens)
       : numParam(numParam), signs(signs), numerators(nums), denominators(dens) {
-    for (const auto &term : numerators)
+    for (const ParamPoint &term : numerators)
       assert(term.getNumColumns() - 1 == numParam &&
              "dimensionality of numerator exponents does not match number of "
              "parameters!");
@@ -138,7 +138,7 @@ class QuasiPolynomial {
                   std::vector<std::vector<SmallVector<Fraction>>> aff = {})
       : numParam(numParam), coefficients(coeffs), affine(aff) {
     // Find the first term which involves some affine function.
-    for (auto term : affine) {
+    for (const std::vector<SmallVector<Fraction>> &term : affine) {
       if (term.size() == 0)
         continue;
       // The number of elements in the affine function is

>From 34da1b2e557c503cb6207d2d3d039adea1e85674 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sun, 17 Dec 2023 21:21:13 +0530
Subject: [PATCH 09/15] Pass numParam

---
 mlir/include/mlir/Analysis/Presburger/Barvinok.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 682099ed84b029..f9c06ef56157cc 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -177,7 +177,7 @@ class QuasiPolynomial {
     assert(numParam = x.getNumParams() &&
                       "two quasi-polynomials with different numbers of "
                       "parameters cannot be multiplied!");
-    QuasiPolynomial qp();
+    QuasiPolynomial qp(numParam);
     std::vector<SmallVector<Fraction>> product;
     for (unsigned i = 0, e = coefficients.size(); i < e; i++) {
       for (unsigned j = 0, e = x.coefficients.size(); j < e; j++) {

>From 07e5be7b0c5d943ba67895340ecc07a737055fa6 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sun, 17 Dec 2023 21:28:29 +0530
Subject: [PATCH 10/15] Use range-based loop

---
 mlir/include/mlir/Analysis/Presburger/Barvinok.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index f9c06ef56157cc..e8f2c20662f2c3 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -168,8 +168,8 @@ class QuasiPolynomial {
            "two quasi-polynomials with different numbers of parameters cannot "
            "be subtracted!");
     QuasiPolynomial qp(x.coefficients, x.affine);
-    for (unsigned i = 0, e = x.coefficients.size(); i < e; i++)
-      qp.coefficients[i] = -qp.coefficients[i];
+    for (Fraction &coeff : qp.coefficients)
+      coeff = -coeff;
     return (*this + qp);
   }
 

>From f255ad13abd7ee2fb15c4aebe5bf5abd2b33c2b8 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sun, 17 Dec 2023 21:29:48 +0530
Subject: [PATCH 11/15] Formatting

---
 .../mlir/Analysis/Presburger/Barvinok.h        | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index e8f2c20662f2c3..a5ddf5e28b2360 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -162,15 +162,13 @@ class QuasiPolynomial {
   }
 
   QuasiPolynomial operator-(const QuasiPolynomial &x) {
-    bool sameNumParams = (getNumParams() == -1) || (x.getNumParams() == -1) ||
-                         (getNumParams() == x.getNumParams());
     assert(numParam == x.getNumParams() &&
            "two quasi-polynomials with different numbers of parameters cannot "
            "be subtracted!");
     QuasiPolynomial qp(x.coefficients, x.affine);
     for (Fraction &coeff : qp.coefficients)
       coeff = -coeff;
-    return (*this + qp);
+    return *this + qp;
   }
 
   QuasiPolynomial operator*(const QuasiPolynomial &x) {
@@ -205,18 +203,18 @@ class QuasiPolynomial {
   QuasiPolynomial simplify() {
     SmallVector<Fraction> newCoeffs({});
     std::vector<std::vector<SmallVector<Fraction>>> newAffine({});
-    bool prodIsNonz, sumIsNonz;
+    bool prodIsNonzero, sumIsNonzero;
     for (unsigned i = 0, e = coefficients.size(); i < e; i++) {
-      prodIsNonz = true;
+      prodIsNonzero = true;
       for (unsigned j = 0, e = affine[i].size(); j < e; j++) {
-        sumIsNonz = false;
+        sumIsNonzero = false;
         for (unsigned k = 0, e = affine[i][j].size(); k < e; k++)
           if (affine[i][j][k] != Fraction(0, 1))
-            sumIsNonz = true;
-        if (sumIsNonz == false)
-          prodIsNonz = false;
+            sumIsNonzero = true;
+        if (sumIsNonzero == false)
+          prodIsNonzero = false;
       }
-      if (prodIsNonz && coefficients[i] != Fraction(0, 1)) {
+      if (prodIsNonzero && coefficients[i] != Fraction(0, 1)) {
         newCoeffs.append({coefficients[i]});
         newAffine.push_back({affine[i]});
       }

>From ef899d9ab25ffb489c5c36a8ce970eaee187b9b3 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Sun, 17 Dec 2023 23:36:27 +0530
Subject: [PATCH 12/15] Use llvm::any_of and llvm::all_of

---
 .../mlir/Analysis/Presburger/Barvinok.h       | 25 ++++++++-----------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index a5ddf5e28b2360..7f24882457512d 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -203,21 +203,18 @@ class QuasiPolynomial {
   QuasiPolynomial simplify() {
     SmallVector<Fraction> newCoeffs({});
     std::vector<std::vector<SmallVector<Fraction>>> newAffine({});
-    bool prodIsNonzero, sumIsNonzero;
     for (unsigned i = 0, e = coefficients.size(); i < e; i++) {
-      prodIsNonzero = true;
-      for (unsigned j = 0, e = affine[i].size(); j < e; j++) {
-        sumIsNonzero = false;
-        for (unsigned k = 0, e = affine[i][j].size(); k < e; k++)
-          if (affine[i][j][k] != Fraction(0, 1))
-            sumIsNonzero = true;
-        if (sumIsNonzero == false)
-          prodIsNonzero = false;
-      }
-      if (prodIsNonzero && coefficients[i] != Fraction(0, 1)) {
-        newCoeffs.append({coefficients[i]});
-        newAffine.push_back({affine[i]});
-      }
+      // A term is zero if its coefficient is zero, or
+      if (coefficients[i] == Fraction(0, 1) ||
+              // if any of the affine functions in the product
+              llvm::any_of(affine[i], [](SmallVector<Fraction> affine_ij) {
+                // has all its coefficients as zero.
+                return llvm::all_of(affine_ij,
+                                    [](Fraction f) { return f == 0; });
+              });)
+        continue;
+      newCoeffs.append({coefficients[i]});
+      newAffine.push_back({affine[i]});
     }
     return QuasiPolynomial(newCoeffs, newAffine);
   }

>From 9bc0cb5d2598f9feba119feab7e2e1be7b449532 Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Mon, 18 Dec 2023 15:41:12 +0530
Subject: [PATCH 13/15] Make data private

---
 mlir/include/mlir/Analysis/Presburger/Barvinok.h | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 7f24882457512d..1980b5d634b6b2 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -78,6 +78,12 @@ class GeneratingFunction {
   // from the dimensionality of the affine functions.
   unsigned getNumParams() { return numParam; }
 
+  SmallVector<int, 8> getSigns() { return signs; }
+
+  std::vector<ParamPoint> getNumerators() { return numerators; }
+
+  std::vector<std::vector<Point>> getDenominators() { return denominators; }
+
   GeneratingFunction operator+(const GeneratingFunction &gf) {
     assert(numParam == gf.getNumParams() &&
            "two generating functions with different numbers of parameters "
@@ -112,12 +118,11 @@ class GeneratingFunction {
     return os;
   }
 
+private:
+  unsigned numParam;
   SmallVector<int, 8> signs;
   std::vector<ParamPoint> numerators;
   std::vector<std::vector<Point>> denominators;
-
-private:
-  unsigned numParam;
 };
 
 // A class to describe the quasi-polynomials obtained by
@@ -219,11 +224,10 @@ class QuasiPolynomial {
     return QuasiPolynomial(newCoeffs, newAffine);
   }
 
-  SmallVector<Fraction> coefficients;
-  std::vector<std::vector<SmallVector<Fraction>>> affine;
-
 private:
   unsigned numParam;
+  SmallVector<Fraction> coefficients;
+  std::vector<std::vector<SmallVector<Fraction>>> affine;
 };
 
 } // namespace presburger

>From d1e6b249951e836131acf5963dd12c260617faed Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Mon, 18 Dec 2023 16:05:42 +0530
Subject: [PATCH 14/15] Define getters

---
 .../include/mlir/Analysis/Presburger/Barvinok.h | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index 1980b5d634b6b2..37ba5cc040e871 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -24,17 +24,6 @@
 namespace mlir {
 namespace presburger {
 
-// The H (inequality) representation of both general
-// polyhedra and cones specifically is an integer relation.
-using PolyhedronH = IntegerRelation;
-using ConeH = PolyhedronH;
-
-// The V (generator) representation of both general
-// polyhedra and cones specifically is simply a matrix
-// whose rows are the generators.
-using PolyhedronV = Matrix<MPInt>;
-using ConeV = PolyhedronV;
-
 // A parametric point is a vector, each of whose elements
 // is an affine function of n parameters. Each row
 // in the matrix represents the affine function and
@@ -78,7 +67,7 @@ class GeneratingFunction {
   // from the dimensionality of the affine functions.
   unsigned getNumParams() { return numParam; }
 
-  SmallVector<int, 8> getSigns() { return signs; }
+  SmallVector<int> getSigns() { return signs; }
 
   std::vector<ParamPoint> getNumerators() { return numerators; }
 
@@ -157,6 +146,10 @@ class QuasiPolynomial {
   // Find the number of parameters involved in the polynomial.
   unsigned getNumParams() { return numParam; }
 
+  SmallVector<Fraction> getCoefficients() { return coefficients; }
+
+  std::vector<std::vector<SmallVector<Fraction>>> getAffine() { return affine; }
+
   QuasiPolynomial operator+(const QuasiPolynomial &x) {
     assert(numParam == x.getNumParams() &&
            "two quasi-polynomials with different numbers of parameters cannot "

>From c04f6d9f5a7aed53740a4ab776d236d4bc1b26df Mon Sep 17 00:00:00 2001
From: Abhinav271828 <abhinav.m at research.iiit.ac.in>
Date: Mon, 18 Dec 2023 19:22:56 +0530
Subject: [PATCH 15/15] Refactor headers

---
 .../mlir/Analysis/Presburger/Barvinok.h       | 229 ------------------
 .../Analysis/Presburger/QuasiPolynomial.h     | 103 ++++++++
 mlir/lib/Analysis/Presburger/CMakeLists.txt   |   1 +
 .../Analysis/Presburger/GeneratingFunction.h  | 116 +++++++++
 .../Analysis/Presburger/QuasiPolynomial.cpp   |  65 +++++
 5 files changed, 285 insertions(+), 229 deletions(-)
 delete mode 100644 mlir/include/mlir/Analysis/Presburger/Barvinok.h
 create mode 100644 mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
 create mode 100644 mlir/lib/Analysis/Presburger/GeneratingFunction.h
 create mode 100644 mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp

diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
deleted file mode 100644
index 37ba5cc040e871..00000000000000
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ /dev/null
@@ -1,229 +0,0 @@
-//===- Barvinok.h - Barvinok's Algorithm ------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Functions and classes for Barvinok's algorithm in MLIR.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MLIR_ANALYSIS_PRESBURGER_BARVINOK_H
-#define MLIR_ANALYSIS_PRESBURGER_BARVINOK_H
-
-#include "mlir/Analysis/Presburger/Fraction.h"
-#include "mlir/Analysis/Presburger/IntegerRelation.h"
-#include "mlir/Analysis/Presburger/Matrix.h"
-#include "mlir/Analysis/Presburger/PresburgerSpace.h"
-#include "mlir/Analysis/Presburger/Utils.h"
-#include "mlir/Support/LogicalResult.h"
-#include <optional>
-
-namespace mlir {
-namespace presburger {
-
-// A parametric point is a vector, each of whose elements
-// is an affine function of n parameters. Each row
-// in the matrix represents the affine function and
-// has n+1 elements.
-using ParamPoint = Matrix<Fraction>;
-
-// A point is simply a vector.
-using Point = SmallVector<Fraction>;
-
-// A class to describe the type of generating function
-// used to enumerate the integer points in a polytope.
-// Consists of a set of terms, where the ith term has
-// * a sign, ±1, stored in `signs[i]`
-// * a numerator, of the form x^{n},
-//      where n, stored in `numerators[i]`,
-//      is a parametric point (a vertex).
-// * a denominator, of the form (1 - x^{d1})...(1 - x^{dn}),
-//      where each dj, stored in `denominators[i][j]`,
-//      is a vector (a generator).
-//
-// Represents functions f : Q^n -> Q of the form
-//
-// f(x) = \sum_i s_i * (x^n_i(p)) / (\prod_j (1 - x^d_{ij})
-//
-// where s_i is ±1,
-// n_i \in (Q^d -> Q)^n is an n-vector of affine functions on d parameters, and
-// g_{ij} \in Q^n are vectors.
-class GeneratingFunction {
-public:
-  GeneratingFunction(unsigned numParam, SmallVector<int, 8> signs,
-                     std::vector<ParamPoint> nums,
-                     std::vector<std::vector<Point>> dens)
-      : numParam(numParam), signs(signs), numerators(nums), denominators(dens) {
-    for (const ParamPoint &term : numerators)
-      assert(term.getNumColumns() - 1 == numParam &&
-             "dimensionality of numerator exponents does not match number of "
-             "parameters!");
-  }
-
-  // Find the number of parameters involved in the function
-  // from the dimensionality of the affine functions.
-  unsigned getNumParams() { return numParam; }
-
-  SmallVector<int> getSigns() { return signs; }
-
-  std::vector<ParamPoint> getNumerators() { return numerators; }
-
-  std::vector<std::vector<Point>> getDenominators() { return denominators; }
-
-  GeneratingFunction operator+(const GeneratingFunction &gf) {
-    assert(numParam == gf.getNumParams() &&
-           "two generating functions with different numbers of parameters "
-           "cannot be added!");
-    signs.append(gf.signs);
-    numerators.insert(numerators.end(), gf.numerators.begin(),
-                      gf.numerators.end());
-    denominators.insert(denominators.end(), gf.denominators.begin(),
-                        gf.denominators.end());
-    return *this;
-  }
-
-  llvm::raw_ostream &print(llvm::raw_ostream &os) const {
-    for (unsigned i = 0, e = signs.size(); i < e; i++) {
-      if (signs[i] == 1)
-        os << " + ";
-      else
-        os << " - ";
-
-      os << "x^[";
-      for (unsigned j = 0, e = numerators[i].size(); j < e - 1; j++)
-        os << numerators[i][j] << ",";
-      os << numerators[i].back() << "]/";
-
-      for (Point den : denominators[i]) {
-        os << "(x^[";
-        for (unsigned j = 0, e = den.size(); j < e - 1; j++)
-          os << den[j] << ",";
-        os << den[den.size() - 1] << "])";
-      }
-    }
-    return os;
-  }
-
-private:
-  unsigned numParam;
-  SmallVector<int, 8> signs;
-  std::vector<ParamPoint> numerators;
-  std::vector<std::vector<Point>> denominators;
-};
-
-// A class to describe the quasi-polynomials obtained by
-// substituting the unit vector in the type of generating
-// function described above.
-// Consists of a set of terms.
-// The ith term is a constant `coefficients[i]`, multiplied
-// by the product of a set of affine functions on n parameters.
-// Represents functions f : Q^n -> Q of the form
-//
-// f(x) = \sum_i c_i * \prod_j ⌊g_{ij}(x)⌋
-//
-// where c_i \in Q and
-// g_{ij} : Q^n -> Q are affine functionals.
-class QuasiPolynomial {
-public:
-  QuasiPolynomial(unsigned numParam, SmallVector<Fraction> coeffs = {},
-                  std::vector<std::vector<SmallVector<Fraction>>> aff = {})
-      : numParam(numParam), coefficients(coeffs), affine(aff) {
-    // Find the first term which involves some affine function.
-    for (const std::vector<SmallVector<Fraction>> &term : affine) {
-      if (term.size() == 0)
-        continue;
-      // The number of elements in the affine function is
-      // one more than the number of parameters.
-      assert(term[0].size() - 1 == numParam &&
-             "dimensionality of affine functions does not match number of "
-             "parameters!")
-    }
-  }
-
-  // Find the number of parameters involved in the polynomial.
-  unsigned getNumParams() { return numParam; }
-
-  SmallVector<Fraction> getCoefficients() { return coefficients; }
-
-  std::vector<std::vector<SmallVector<Fraction>>> getAffine() { return affine; }
-
-  QuasiPolynomial operator+(const QuasiPolynomial &x) {
-    assert(numParam == x.getNumParams() &&
-           "two quasi-polynomials with different numbers of parameters cannot "
-           "be added!");
-    coefficients.append(x.coefficients);
-    affine.insert(affine.end(), x.affine.begin(), x.affine.end());
-    return *this;
-  }
-
-  QuasiPolynomial operator-(const QuasiPolynomial &x) {
-    assert(numParam == x.getNumParams() &&
-           "two quasi-polynomials with different numbers of parameters cannot "
-           "be subtracted!");
-    QuasiPolynomial qp(x.coefficients, x.affine);
-    for (Fraction &coeff : qp.coefficients)
-      coeff = -coeff;
-    return *this + qp;
-  }
-
-  QuasiPolynomial operator*(const QuasiPolynomial &x) {
-    assert(numParam = x.getNumParams() &&
-                      "two quasi-polynomials with different numbers of "
-                      "parameters cannot be multiplied!");
-    QuasiPolynomial qp(numParam);
-    std::vector<SmallVector<Fraction>> product;
-    for (unsigned i = 0, e = coefficients.size(); i < e; i++) {
-      for (unsigned j = 0, e = x.coefficients.size(); j < e; j++) {
-        qp.coefficients.append({coefficients[i] * x.coefficients[j]});
-
-        product.clear();
-        product.insert(product.end(), affine[i].begin(), affine[i].end());
-        product.insert(product.end(), x.affine[j].begin(), x.affine[j].end());
-
-        qp.affine.push_back(product);
-      }
-    }
-
-    return qp;
-  }
-
-  QuasiPolynomial operator/(Fraction x) {
-    assert(x != 0 && "division by zero!");
-    for (Fraction &coeff : coefficients)
-      coeff /= x;
-    return *this;
-  };
-
-  // Removes terms which evaluate to zero from the expression.
-  QuasiPolynomial simplify() {
-    SmallVector<Fraction> newCoeffs({});
-    std::vector<std::vector<SmallVector<Fraction>>> newAffine({});
-    for (unsigned i = 0, e = coefficients.size(); i < e; i++) {
-      // A term is zero if its coefficient is zero, or
-      if (coefficients[i] == Fraction(0, 1) ||
-              // if any of the affine functions in the product
-              llvm::any_of(affine[i], [](SmallVector<Fraction> affine_ij) {
-                // has all its coefficients as zero.
-                return llvm::all_of(affine_ij,
-                                    [](Fraction f) { return f == 0; });
-              });)
-        continue;
-      newCoeffs.append({coefficients[i]});
-      newAffine.push_back({affine[i]});
-    }
-    return QuasiPolynomial(newCoeffs, newAffine);
-  }
-
-private:
-  unsigned numParam;
-  SmallVector<Fraction> coefficients;
-  std::vector<std::vector<SmallVector<Fraction>>> affine;
-};
-
-} // namespace presburger
-} // namespace mlir
-
-#endif // MLIR_ANALYSIS_PRESBURGER_BARVINOK_H
\ No newline at end of file
diff --git a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
new file mode 100644
index 00000000000000..6c457a8d94bead
--- /dev/null
+++ b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h
@@ -0,0 +1,103 @@
+//===- QuasiPolynomial.h - Quasipolynomial Class ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Definition of the QuasiPolynomial class for Barvinok's algorithm,
+// which represents a single-valued function on a set of parameters.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_ANALYSIS_PRESBURGER_QUASIPOLYNOMIAL_H
+#define MLIR_ANALYSIS_PRESBURGER_QUASIPOLYNOMIAL_H
+
+#include "mlir/Analysis/Presburger/Fraction.h"
+#include "mlir/Analysis/Presburger/Matrix.h"
+
+namespace mlir {
+namespace presburger {
+
+// A class to describe the quasi-polynomials obtained by
+// substituting the unit vector in the type of generating
+// function described above.
+// Consists of a set of terms.
+// The ith term is a constant `coefficients[i]`, multiplied
+// by the product of a set of affine functions on n parameters.
+// Represents functions f : Q^n -> Q of the form
+//
+// f(x) = \sum_i c_i * \prod_j ⌊g_{ij}(x)⌋
+//
+// where c_i \in Q and
+// g_{ij} : Q^n -> Q are affine functionals.
+class QuasiPolynomial {
+public:
+  QuasiPolynomial(unsigned numParam, SmallVector<Fraction> coeffs = {},
+                  std::vector<std::vector<SmallVector<Fraction>>> aff = {});
+
+  unsigned getNumParams();
+  SmallVector<Fraction> getCoefficients();
+  std::vector<std::vector<SmallVector<Fraction>>> getAffine();
+
+  QuasiPolynomial operator+(QuasiPolynomial &x) {
+    assert(numParam == x.getNumParams() &&
+           "two quasi-polynomials with different numbers of parameters cannot "
+           "be added!");
+    coefficients.append(x.coefficients);
+    affine.insert(affine.end(), x.affine.begin(), x.affine.end());
+    return *this;
+  }
+
+  QuasiPolynomial operator-(QuasiPolynomial &x) {
+    assert(numParam == x.getNumParams() &&
+           "two quasi-polynomials with different numbers of parameters cannot "
+           "be subtracted!");
+    QuasiPolynomial qp(numParam, x.coefficients, x.affine);
+    for (Fraction &coeff : qp.coefficients)
+      coeff = -coeff;
+    return *this + qp;
+  }
+
+  QuasiPolynomial operator*(QuasiPolynomial &x) {
+    assert(numParam = x.getNumParams() &&
+                      "two quasi-polynomials with different numbers of "
+                      "parameters cannot be multiplied!");
+    QuasiPolynomial qp(numParam);
+    std::vector<SmallVector<Fraction>> product;
+    for (unsigned i = 0, e = coefficients.size(); i < e; i++) {
+      for (unsigned j = 0, e = x.coefficients.size(); j < e; j++) {
+        qp.coefficients.append({coefficients[i] * x.coefficients[j]});
+
+        product.clear();
+        product.insert(product.end(), affine[i].begin(), affine[i].end());
+        product.insert(product.end(), x.affine[j].begin(), x.affine[j].end());
+
+        qp.affine.push_back(product);
+      }
+    }
+
+    return qp;
+  }
+
+  QuasiPolynomial operator/(Fraction x) {
+    assert(x != 0 && "division by zero!");
+    for (Fraction &coeff : coefficients)
+      coeff /= x;
+    return *this;
+  };
+
+  // Removes terms which evaluate to zero from the expression.
+  QuasiPolynomial simplify();
+
+private:
+  unsigned numParam;
+  SmallVector<Fraction> coefficients;
+  std::vector<std::vector<SmallVector<Fraction>>> affine;
+};
+
+} // namespace presburger
+} // namespace mlir
+
+#endif // MLIR_ANALYSIS_PRESBURGER_QUASIPOLYNOMIAL_H
\ No newline at end of file
diff --git a/mlir/lib/Analysis/Presburger/CMakeLists.txt b/mlir/lib/Analysis/Presburger/CMakeLists.txt
index 22f1a4cac44055..e77e1623dae175 100644
--- a/mlir/lib/Analysis/Presburger/CMakeLists.txt
+++ b/mlir/lib/Analysis/Presburger/CMakeLists.txt
@@ -6,6 +6,7 @@ add_mlir_library(MLIRPresburger
   PresburgerRelation.cpp
   PresburgerSpace.cpp
   PWMAFunction.cpp
+  QuasiPolynomial.cpp
   Simplex.cpp
   SlowMPInt.cpp
   Utils.cpp
diff --git a/mlir/lib/Analysis/Presburger/GeneratingFunction.h b/mlir/lib/Analysis/Presburger/GeneratingFunction.h
new file mode 100644
index 00000000000000..11832e822dc021
--- /dev/null
+++ b/mlir/lib/Analysis/Presburger/GeneratingFunction.h
@@ -0,0 +1,116 @@
+//===- GeneratingFunction.h - Rational Polynomials over Q^d -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Definition of the GeneratingFunction class for Barvinok's algorithm,
+// which represents a function over Q^n, parameterized by d parameters.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H
+#define MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H
+
+#include "mlir/Analysis/Presburger/Fraction.h"
+#include "mlir/Analysis/Presburger/Matrix.h"
+
+namespace mlir {
+namespace presburger {
+
+// A parametric point is a vector, each of whose elements
+// is an affine function of n parameters. Each row
+// in the matrix represents the affine function and
+// has n+1 elements.
+using ParamPoint = Matrix<Fraction>;
+
+// A point is simply a vector.
+using Point = SmallVector<Fraction>;
+
+// A class to describe the type of generating function
+// used to enumerate the integer points in a polytope.
+// Consists of a set of terms, where the ith term has
+// * a sign, ±1, stored in `signs[i]`
+// * a numerator, of the form x^{n},
+//      where n, stored in `numerators[i]`,
+//      is a parametric point (a vertex).
+// * a denominator, of the form (1 - x^{d1})...(1 - x^{dn}),
+//      where each dj, stored in `denominators[i][j]`,
+//      is a vector (a generator).
+//
+// Represents functions f : Q^n -> Q of the form
+//
+// f(x) = \sum_i s_i * (x^n_i(p)) / (\prod_j (1 - x^d_{ij})
+//
+// where s_i is ±1,
+// n_i \in (Q^d -> Q)^n is an n-vector of affine functions on d parameters, and
+// g_{ij} \in Q^n are vectors.
+class GeneratingFunction {
+public:
+  GeneratingFunction(unsigned numParam, SmallVector<int, 8> signs,
+                     std::vector<ParamPoint> nums,
+                     std::vector<std::vector<Point>> dens)
+      : numParam(numParam), signs(signs), numerators(nums), denominators(dens) {
+    for (const ParamPoint &term : numerators)
+      assert(term.getNumColumns() - 1 == numParam &&
+             "dimensionality of numerator exponents does not match number of "
+             "parameters!");
+  }
+
+  // Find the number of parameters involved in the function
+  // from the dimensionality of the affine functions.
+  unsigned getNumParams() { return numParam; }
+
+  SmallVector<int> getSigns() { return signs; }
+
+  std::vector<ParamPoint> getNumerators() { return numerators; }
+
+  std::vector<std::vector<Point>> getDenominators() { return denominators; }
+
+  GeneratingFunction operator+(const GeneratingFunction &gf) {
+    assert(numParam == gf.getNumParams() &&
+           "two generating functions with different numbers of parameters "
+           "cannot be added!");
+    signs.append(gf.signs);
+    numerators.insert(numerators.end(), gf.numerators.begin(),
+                      gf.numerators.end());
+    denominators.insert(denominators.end(), gf.denominators.begin(),
+                        gf.denominators.end());
+    return *this;
+  }
+
+  llvm::raw_ostream &print(llvm::raw_ostream &os) const {
+    for (unsigned i = 0, e = signs.size(); i < e; i++) {
+      if (signs[i] == 1)
+        os << " + ";
+      else
+        os << " - ";
+
+      os << "x^[";
+      for (unsigned j = 0, e = numerators[i].size(); j < e - 1; j++)
+        os << numerators[i][j] << ",";
+      os << numerators[i].back() << "]/";
+
+      for (Point den : denominators[i]) {
+        os << "(x^[";
+        for (unsigned j = 0, e = den.size(); j < e - 1; j++)
+          os << den[j] << ",";
+        os << den[den.size() - 1] << "])";
+      }
+    }
+    return os;
+  }
+
+private:
+  unsigned numParam;
+  SmallVector<int, 8> signs;
+  std::vector<ParamPoint> numerators;
+  std::vector<std::vector<Point>> denominators;
+};
+
+} // namespace presburger
+} // namespace mlir
+
+#endif // MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H
\ No newline at end of file
diff --git a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
new file mode 100644
index 00000000000000..14cfdcad0fb255
--- /dev/null
+++ b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp
@@ -0,0 +1,65 @@
+//===- QuasiPolynomial.cpp - Quasipolynomial Class --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Analysis/Presburger/QuasiPolynomial.h"
+#include "mlir/Analysis/Presburger/Fraction.h"
+#include "mlir/Analysis/Presburger/IntegerRelation.h"
+#include "mlir/Analysis/Presburger/Matrix.h"
+#include "mlir/Analysis/Presburger/PresburgerSpace.h"
+#include "mlir/Analysis/Presburger/Utils.h"
+#include "mlir/Support/LogicalResult.h"
+#include <optional>
+
+using namespace mlir;
+using namespace presburger;
+
+QuasiPolynomial::QuasiPolynomial(
+    unsigned numParam, SmallVector<Fraction> coeffs,
+    std::vector<std::vector<SmallVector<Fraction>>> aff)
+    : numParam(numParam), coefficients(coeffs), affine(aff) {
+  // Find the first term which involves some affine function.
+  for (const std::vector<SmallVector<Fraction>> &term : affine) {
+    if (term.size() == 0)
+      continue;
+    // The number of elements in the affine function is
+    // one more than the number of parameters.
+    assert(term[0].size() - 1 == numParam &&
+           "dimensionality of affine functions does not match number of "
+           "parameters!");
+  }
+}
+
+// Find the number of parameters involved in the polynomial.
+unsigned QuasiPolynomial::getNumParams() { return numParam; }
+
+SmallVector<Fraction> QuasiPolynomial::getCoefficients() {
+  return coefficients;
+}
+
+std::vector<std::vector<SmallVector<Fraction>>> QuasiPolynomial::getAffine() {
+  return affine;
+}
+
+// Removes terms which evaluate to zero from the expression.
+QuasiPolynomial QuasiPolynomial::simplify() {
+  SmallVector<Fraction> newCoeffs({});
+  std::vector<std::vector<SmallVector<Fraction>>> newAffine({});
+  for (unsigned i = 0, e = coefficients.size(); i < e; i++) {
+    // A term is zero if its coefficient is zero, or
+    if (coefficients[i] == Fraction(0, 1) ||
+        // if any of the affine functions in the product
+        llvm::any_of(affine[i], [](SmallVector<Fraction> affine_ij) {
+          // has all its coefficients as zero.
+          return llvm::all_of(affine_ij, [](Fraction f) { return f == 0; });
+        }))
+      continue;
+    newCoeffs.append({coefficients[i]});
+    newAffine.push_back({affine[i]});
+  }
+  return QuasiPolynomial(numParam, newCoeffs, newAffine);
+}
\ No newline at end of file



More information about the Mlir-commits mailing list