https://github.com/Abhinav271828 created https://github.com/llvm/llvm-project/pull/77199
We implement a function to compute the generating function for a signed unimodular cone with a parametric vertex. These functions, summed over tangential cones, provide the generating function corresponding to a parametric polyhedron. >From e500c63cccbe4a332e2667350781bcbb229e6b55 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sat, 30 Dec 2023 22:45:31 +0530 Subject: [PATCH 01/32] initial commit --- .../mlir/Analysis/Presburger/Barvinok.h | 54 +++++++++++++++ .../Analysis/Presburger/GeneratingFunction.h | 4 +- mlir/lib/Analysis/Presburger/Barvinok.cpp | 65 +++++++++++++++++++ mlir/lib/Analysis/Presburger/CMakeLists.txt | 1 + 4 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 mlir/include/mlir/Analysis/Presburger/Barvinok.h rename mlir/{lib => include/mlir}/Analysis/Presburger/GeneratingFunction.h (97%) create mode 100644 mlir/lib/Analysis/Presburger/Barvinok.cpp diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h new file mode 100644 index 00000000000000..c63ee1e230c8bf --- /dev/null +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -0,0 +1,54 @@ +//===- 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 relating to Barvinok's algorithm. +// These include functions to manipulate cones (define a cone object, get its +// dual, and find its index). +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_ANALYSIS_PRESBURGER_BARVINOK_H +#define MLIR_ANALYSIS_PRESBURGER_BARVINOK_H + +#include "mlir/Analysis/Presburger/Matrix.h" +#include "mlir/Analysis/Presburger/IntegerRelation.h" +#include <optional> + +namespace mlir { +namespace presburger { + +using PolyhedronH = IntegerRelation; +using PolyhedronV = IntMatrix; +using ConeH = PolyhedronH; +using ConeV = PolyhedronV; + +inline ConeH defineHRep(int num_ineqs, int num_vars, int num_params = 0) +{ + // We don't distinguish between domain and range variables, so + // we set the number of domain variables as 0 and the number of + // range variables as the number of actual variables. + // There are no symbols (non-parametric for now) and no local + // (existentially quantified) variables. + ConeH cone(PresburgerSpace::getRelationSpace(0, num_vars, num_params, 0)); + return cone; +} + +// Get the index of a cone. +// If it has more rays than the dimension, return 0. +MPInt getIndex(ConeV); + +// Get the dual of a cone in H-representation, returning the V-representation of it. +ConeV getDual(ConeH); + +// Get the dual of a cone in V-representation, returning the H-representation of it. +ConeH getDual(ConeV); + +} // namespace presburger +} // namespace mlir + +#endif // MLIR_ANALYSIS_PRESBURGER_BARVINOK_H \ No newline at end of file diff --git a/mlir/lib/Analysis/Presburger/GeneratingFunction.h b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h similarity index 97% rename from mlir/lib/Analysis/Presburger/GeneratingFunction.h rename to mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h index f7deba921ea51e..770d17fe17c307 100644 --- a/mlir/lib/Analysis/Presburger/GeneratingFunction.h +++ b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h @@ -19,6 +19,7 @@ namespace mlir { namespace presburger { +namespace internal { // A parametric point is a vector, each of whose elements // is an affine function of n parameters. Each row @@ -128,7 +129,8 @@ class GeneratingFunction { std::vector<std::vector<Point>> denominators; }; +} // namespace internal } // namespace presburger } // namespace mlir -#endif // MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H +#endif // MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H \ No newline at end of file diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp new file mode 100644 index 00000000000000..ddb24d1a79993f --- /dev/null +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -0,0 +1,65 @@ +//===- QuasiPolynomial.cpp - 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 +// +//===----------------------------------------------------------------------===// + +#include "mlir/Analysis/Presburger/Barvinok.h" + +using namespace mlir; +using namespace presburger; + +// Assuming that the input cone is pointed at the origin, +// converts it to its dual in V-representation. +// Essentially we just remove the all-zeroes constant column. +ConeV mlir::presburger::getDual(ConeH cone) +{ + ConeV dual(cone.getNumInequalities(), cone.getNumCols()-1, 0, 0); + // Assuming that an inequality of the form + // a1*x1 + ... + an*xn + b ≥ 0 + // is represented as a row [a1, ..., an, b] + // and that b = 0. + + for (unsigned i = 0; i < cone.getNumInequalities(); i++) + { + assert(dual.at(i, cone.getNumCols()-1) == 0 && "H-representation of cone is not centred at the origin!"); + for (unsigned j = 0; j < cone.getNumCols()-1; j++) + { + dual.at(i, j) = cone.atIneq(i, j); + } + } + + // Now dual is of the form [ [a1, ..., an] , ... ] + // which is the V-representation of the dual. + return dual; +} + +// Converts a cone in V-representation to the H-representation +// of its dual, pointed at the origin (not at the original vertex). +// Essentially adds a column consisting only of zeroes to the end. +ConeH mlir::presburger::getDual(ConeV cone) +{ + ConeH dual = defineHRep(cone.getNumRows(), cone.getNumColumns()); + cone.insertColumn(cone.getNumColumns()); + + for (unsigned i = 0; i < cone.getNumRows(); i++) + dual.addInequality(cone.getRow(i)); + + // Now dual is of the form [ [a1, ..., an, 0] , ... ] + // which is the H-representation of the dual. + return dual; +} + +// Find the index of a cone in V-representation. +// If there are more rays than variables, return 0. +MPInt mlir::presburger::getIndex(ConeV cone) +{ + unsigned rows = cone.getNumRows(); + unsigned cols = cone.getNumColumns(); + if (rows > cols) + return MPInt(0); + + return cone.determinant(); +} \ No newline at end of file diff --git a/mlir/lib/Analysis/Presburger/CMakeLists.txt b/mlir/lib/Analysis/Presburger/CMakeLists.txt index e77e1623dae175..83d0514c9e7d17 100644 --- a/mlir/lib/Analysis/Presburger/CMakeLists.txt +++ b/mlir/lib/Analysis/Presburger/CMakeLists.txt @@ -1,4 +1,5 @@ add_mlir_library(MLIRPresburger + Barvinok.cpp IntegerRelation.cpp LinearTransform.cpp Matrix.cpp >From b2566609ac319a9effad78405e7c8f948b3490ce Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sat, 30 Dec 2023 22:53:15 +0530 Subject: [PATCH 02/32] Formatting --- .../mlir/Analysis/Presburger/Barvinok.h | 33 +++++---- mlir/lib/Analysis/Presburger/Barvinok.cpp | 70 +++++++++---------- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index c63ee1e230c8bf..6ffdf96502fd20 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -15,37 +15,46 @@ #ifndef MLIR_ANALYSIS_PRESBURGER_BARVINOK_H #define MLIR_ANALYSIS_PRESBURGER_BARVINOK_H -#include "mlir/Analysis/Presburger/Matrix.h" #include "mlir/Analysis/Presburger/IntegerRelation.h" +#include "mlir/Analysis/Presburger/Matrix.h" #include <optional> namespace mlir { namespace presburger { +// A polyhedron in H-representation is a set of relations +// in d variables with integer coefficients. using PolyhedronH = IntegerRelation; + +// A polyhedron in V-representation is a set of rays, i.e., +// vectors, stored as rows of a matrix. using PolyhedronV = IntMatrix; + +// A cone in either representation is a special case of +// a polyhedron in that representation. using ConeH = PolyhedronH; using ConeV = PolyhedronV; -inline ConeH defineHRep(int num_ineqs, int num_vars, int num_params = 0) -{ - // We don't distinguish between domain and range variables, so - // we set the number of domain variables as 0 and the number of - // range variables as the number of actual variables. - // There are no symbols (non-parametric for now) and no local - // (existentially quantified) variables. - ConeH cone(PresburgerSpace::getRelationSpace(0, num_vars, num_params, 0)); - return cone; +inline ConeH defineHRep(int num_ineqs, int num_vars, int num_params = 0) { + // We don't distinguish between domain and range variables, so + // we set the number of domain variables as 0 and the number of + // range variables as the number of actual variables. + // There are no symbols (non-parametric for now) and no local + // (existentially quantified) variables. + return ConeH(PresburgerSpace::getRelationSpace(/*numDomain=*/0, + /*numRange=*/num_vars, + /*numSymbols=*/num_params, + /*numLocals=*/0)); } // Get the index of a cone. // If it has more rays than the dimension, return 0. MPInt getIndex(ConeV); -// Get the dual of a cone in H-representation, returning the V-representation of it. +// Get the dual of a cone in H-representation, returning its V-representation. ConeV getDual(ConeH); -// Get the dual of a cone in V-representation, returning the H-representation of it. +// Get the dual of a cone in V-representation, returning its H-representation. ConeH getDual(ConeV); } // namespace presburger diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp index ddb24d1a79993f..698dde6f15d6f4 100644 --- a/mlir/lib/Analysis/Presburger/Barvinok.cpp +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -14,52 +14,50 @@ using namespace presburger; // Assuming that the input cone is pointed at the origin, // converts it to its dual in V-representation. // Essentially we just remove the all-zeroes constant column. -ConeV mlir::presburger::getDual(ConeH cone) -{ - ConeV dual(cone.getNumInequalities(), cone.getNumCols()-1, 0, 0); - // Assuming that an inequality of the form - // a1*x1 + ... + an*xn + b ≥ 0 - // is represented as a row [a1, ..., an, b] - // and that b = 0. - - for (unsigned i = 0; i < cone.getNumInequalities(); i++) - { - assert(dual.at(i, cone.getNumCols()-1) == 0 && "H-representation of cone is not centred at the origin!"); - for (unsigned j = 0; j < cone.getNumCols()-1; j++) - { - dual.at(i, j) = cone.atIneq(i, j); - } +ConeV mlir::presburger::getDual(ConeH cone) { + unsigned inequalities = cone.getNumInequalities(); + unsigned variables = cone.getNumCols() - 1; + ConeV dual(inequalities, variables, 0, 0); + // Assuming that an inequality of the form + // a1*x1 + ... + an*xn + b ≥ 0 + // is represented as a row [a1, ..., an, b] + // and that b = 0. + + for (unsigned i = 0; i < inequalities; i++) { + assert(dual.at(i, variables) == 0 && + "H-representation of cone is not centred at the origin!"); + for (unsigned j = 0; j < variables; j++) { + dual.at(i, j) = cone.atIneq(i, j); } + } - // Now dual is of the form [ [a1, ..., an] , ... ] - // which is the V-representation of the dual. - return dual; + // Now dual is of the form [ [a1, ..., an] , ... ] + // which is the V-representation of the dual. + return dual; } // Converts a cone in V-representation to the H-representation // of its dual, pointed at the origin (not at the original vertex). // Essentially adds a column consisting only of zeroes to the end. -ConeH mlir::presburger::getDual(ConeV cone) -{ - ConeH dual = defineHRep(cone.getNumRows(), cone.getNumColumns()); - cone.insertColumn(cone.getNumColumns()); - - for (unsigned i = 0; i < cone.getNumRows(); i++) - dual.addInequality(cone.getRow(i)); - - // Now dual is of the form [ [a1, ..., an, 0] , ... ] - // which is the H-representation of the dual. - return dual; +ConeH mlir::presburger::getDual(ConeV cone) { + unsigned rows = cone.getNumRows(); + unsigned columns = cone.getNumColumns(); + ConeH dual = defineHRep(rows, columns); + cone.insertColumn(columns); + + for (unsigned i = 0; i < rows; i++) + dual.addInequality(cone.getRow(i)); + + // Now dual is of the form [ [a1, ..., an, 0] , ... ] + // which is the H-representation of the dual. + return dual; } // Find the index of a cone in V-representation. // If there are more rays than variables, return 0. -MPInt mlir::presburger::getIndex(ConeV cone) -{ - unsigned rows = cone.getNumRows(); - unsigned cols = cone.getNumColumns(); - if (rows > cols) - return MPInt(0); +MPInt mlir::presburger::getIndex(ConeV cone) { + if (cone.getNumRows() > cone.getNumColumns()) + return MPInt(0); - return cone.determinant(); + return cone.determinant(); } \ No newline at end of file >From b76e6f6da58d2bbe1bc22be248ee88452ea71d17 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sat, 30 Dec 2023 23:32:49 +0530 Subject: [PATCH 03/32] Add tests for cone fns --- .../mlir/Analysis/Presburger/Barvinok.h | 7 +-- mlir/lib/Analysis/Presburger/Barvinok.cpp | 6 ++- .../Analysis/Presburger/BarvinokTest.cpp | 47 +++++++++++++++++++ .../Analysis/Presburger/CMakeLists.txt | 1 + 4 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 mlir/unittests/Analysis/Presburger/BarvinokTest.cpp diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index 6ffdf96502fd20..665227a20fc258 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -35,15 +35,16 @@ using PolyhedronV = IntMatrix; using ConeH = PolyhedronH; using ConeV = PolyhedronV; -inline ConeH defineHRep(int num_ineqs, int num_vars, int num_params = 0) { +inline ConeH defineHRep(int num_vars) { // We don't distinguish between domain and range variables, so // we set the number of domain variables as 0 and the number of // range variables as the number of actual variables. - // There are no symbols (non-parametric for now) and no local + // There are no symbols (we don't work with parametric cones) and no local // (existentially quantified) variables. + // Once the cone is defined, we use `addInequality()` to set inequalities. return ConeH(PresburgerSpace::getRelationSpace(/*numDomain=*/0, /*numRange=*/num_vars, - /*numSymbols=*/num_params, + /*numSymbols=*/0, /*numLocals=*/0)); } diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp index 698dde6f15d6f4..8c6fc9a6e3f53d 100644 --- a/mlir/lib/Analysis/Presburger/Barvinok.cpp +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -24,7 +24,7 @@ ConeV mlir::presburger::getDual(ConeH cone) { // and that b = 0. for (unsigned i = 0; i < inequalities; i++) { - assert(dual.at(i, variables) == 0 && + assert(cone.atIneq(i, variables) == 0 && "H-representation of cone is not centred at the origin!"); for (unsigned j = 0; j < variables; j++) { dual.at(i, j) = cone.atIneq(i, j); @@ -42,7 +42,9 @@ ConeV mlir::presburger::getDual(ConeH cone) { ConeH mlir::presburger::getDual(ConeV cone) { unsigned rows = cone.getNumRows(); unsigned columns = cone.getNumColumns(); - ConeH dual = defineHRep(rows, columns); + ConeH dual = defineHRep(columns); + // Add a new column (for constants) at the end. + // This will be initialized to zero. cone.insertColumn(columns); for (unsigned i = 0; i < rows; i++) diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp new file mode 100644 index 00000000000000..2b7f0491d588eb --- /dev/null +++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp @@ -0,0 +1,47 @@ +#include "mlir/Analysis/Presburger/Barvinok.h" +#include "./Utils.h" +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +using namespace mlir; +using namespace presburger; + +// We randomly generate 3 vectors with 4 entries each +// and define a cone's H-representation using these +// numbers. We check that the dual contains the same +// numbers. +// We do the same in the reverse case. +TEST(BarvinokTest, getDual) { + ConeH cone1 = defineHRep(4); + cone1.addInequality({1, 2, 3, 4, 0}); + cone1.addInequality({3, 4, 2, 5, 0}); + cone1.addInequality({6, 2, 6, 1, 0}); + + ConeV dual1 = getDual(cone1); + + EXPECT_EQ_INT_MATRIX( + dual1, makeIntMatrix(3, 4, {{1, 2, 3, 4}, {3, 4, 2, 5}, {6, 2, 6, 1}})); + + ConeV cone2 = makeIntMatrix(3, 4, {{3, 6, 1, 5}, {3, 1, 7, 2}, {9, 3, 2, 7}}); + + ConeH dual2 = getDual(cone2); + + ConeH expected = defineHRep(4); + expected.addInequality({3, 6, 1, 5, 0}); + expected.addInequality({3, 1, 7, 2, 0}); + expected.addInequality({9, 3, 2, 7, 0}); + + EXPECT_TRUE(dual2.isEqual(expected)); +} + +// We randomly generate a nxn matrix to use as a cone +// with n inequalities in n variables and check for +// the determinant being equal to the index. +TEST(BarvinokTest, getIndex) { + ConeV cone = makeIntMatrix(3, 3, {{4, 2, 1}, {5, 2, 7}, {4, 1, 6}}); + EXPECT_EQ(getIndex(cone), cone.determinant()); + + cone = makeIntMatrix( + 4, 4, {{4, 2, 5, 1}, {4, 1, 3, 6}, {8, 2, 5, 6}, {5, 2, 5, 7}}); + EXPECT_EQ(getIndex(cone), cone.determinant()); +} diff --git a/mlir/unittests/Analysis/Presburger/CMakeLists.txt b/mlir/unittests/Analysis/Presburger/CMakeLists.txt index e37133354e53ca..25f9e5939e4a25 100644 --- a/mlir/unittests/Analysis/Presburger/CMakeLists.txt +++ b/mlir/unittests/Analysis/Presburger/CMakeLists.txt @@ -1,4 +1,5 @@ add_mlir_unittest(MLIRPresburgerTests + BarvinokTest.cpp FractionTest.cpp IntegerPolyhedronTest.cpp IntegerRelationTest.cpp >From 855bcb46c775c970fd56768759a2681bdc52a9b2 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sun, 31 Dec 2023 00:18:43 +0530 Subject: [PATCH 04/32] Use public_namespace_name::detail --- mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h index 770d17fe17c307..e29478e97be02c 100644 --- a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h +++ b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h @@ -19,7 +19,7 @@ namespace mlir { namespace presburger { -namespace internal { +namespace public_namespace_name::detail { // A parametric point is a vector, each of whose elements // is an affine function of n parameters. Each row >From df7549fdc05937216611b3af1830e90ad22d9bb7 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sun, 31 Dec 2023 10:14:19 +0530 Subject: [PATCH 05/32] Resolve conflict --- mlir/lib/Analysis/Presburger/Matrix.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mlir/lib/Analysis/Presburger/Matrix.cpp b/mlir/lib/Analysis/Presburger/Matrix.cpp index 25300f84cfc047..a17565efbce95b 100644 --- a/mlir/lib/Analysis/Presburger/Matrix.cpp +++ b/mlir/lib/Analysis/Presburger/Matrix.cpp @@ -452,6 +452,8 @@ MPInt IntMatrix::determinant(IntMatrix *inverse) const { if (detM == 0) return MPInt(0); + if (!inverse) return detM; + *inverse = IntMatrix(nRows, nColumns); for (unsigned i = 0; i < nRows; i++) for (unsigned j = 0; j < nColumns; j++) >From 5a9c4bd13f384a17bc7399f696cf62c80dc3e82d Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sat, 30 Dec 2023 22:45:31 +0530 Subject: [PATCH 06/32] initial commit --- .../mlir/Analysis/Presburger/Barvinok.h | 54 +++++++++++++++ .../Analysis/Presburger/GeneratingFunction.h | 4 +- mlir/lib/Analysis/Presburger/Barvinok.cpp | 65 +++++++++++++++++++ mlir/lib/Analysis/Presburger/CMakeLists.txt | 1 + 4 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 mlir/include/mlir/Analysis/Presburger/Barvinok.h rename mlir/{lib => include/mlir}/Analysis/Presburger/GeneratingFunction.h (97%) create mode 100644 mlir/lib/Analysis/Presburger/Barvinok.cpp diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h new file mode 100644 index 00000000000000..c63ee1e230c8bf --- /dev/null +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -0,0 +1,54 @@ +//===- 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 relating to Barvinok's algorithm. +// These include functions to manipulate cones (define a cone object, get its +// dual, and find its index). +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_ANALYSIS_PRESBURGER_BARVINOK_H +#define MLIR_ANALYSIS_PRESBURGER_BARVINOK_H + +#include "mlir/Analysis/Presburger/Matrix.h" +#include "mlir/Analysis/Presburger/IntegerRelation.h" +#include <optional> + +namespace mlir { +namespace presburger { + +using PolyhedronH = IntegerRelation; +using PolyhedronV = IntMatrix; +using ConeH = PolyhedronH; +using ConeV = PolyhedronV; + +inline ConeH defineHRep(int num_ineqs, int num_vars, int num_params = 0) +{ + // We don't distinguish between domain and range variables, so + // we set the number of domain variables as 0 and the number of + // range variables as the number of actual variables. + // There are no symbols (non-parametric for now) and no local + // (existentially quantified) variables. + ConeH cone(PresburgerSpace::getRelationSpace(0, num_vars, num_params, 0)); + return cone; +} + +// Get the index of a cone. +// If it has more rays than the dimension, return 0. +MPInt getIndex(ConeV); + +// Get the dual of a cone in H-representation, returning the V-representation of it. +ConeV getDual(ConeH); + +// Get the dual of a cone in V-representation, returning the H-representation of it. +ConeH getDual(ConeV); + +} // namespace presburger +} // namespace mlir + +#endif // MLIR_ANALYSIS_PRESBURGER_BARVINOK_H \ No newline at end of file diff --git a/mlir/lib/Analysis/Presburger/GeneratingFunction.h b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h similarity index 97% rename from mlir/lib/Analysis/Presburger/GeneratingFunction.h rename to mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h index f7deba921ea51e..770d17fe17c307 100644 --- a/mlir/lib/Analysis/Presburger/GeneratingFunction.h +++ b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h @@ -19,6 +19,7 @@ namespace mlir { namespace presburger { +namespace internal { // A parametric point is a vector, each of whose elements // is an affine function of n parameters. Each row @@ -128,7 +129,8 @@ class GeneratingFunction { std::vector<std::vector<Point>> denominators; }; +} // namespace internal } // namespace presburger } // namespace mlir -#endif // MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H +#endif // MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H \ No newline at end of file diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp new file mode 100644 index 00000000000000..ddb24d1a79993f --- /dev/null +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -0,0 +1,65 @@ +//===- QuasiPolynomial.cpp - 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 +// +//===----------------------------------------------------------------------===// + +#include "mlir/Analysis/Presburger/Barvinok.h" + +using namespace mlir; +using namespace presburger; + +// Assuming that the input cone is pointed at the origin, +// converts it to its dual in V-representation. +// Essentially we just remove the all-zeroes constant column. +ConeV mlir::presburger::getDual(ConeH cone) +{ + ConeV dual(cone.getNumInequalities(), cone.getNumCols()-1, 0, 0); + // Assuming that an inequality of the form + // a1*x1 + ... + an*xn + b ≥ 0 + // is represented as a row [a1, ..., an, b] + // and that b = 0. + + for (unsigned i = 0; i < cone.getNumInequalities(); i++) + { + assert(dual.at(i, cone.getNumCols()-1) == 0 && "H-representation of cone is not centred at the origin!"); + for (unsigned j = 0; j < cone.getNumCols()-1; j++) + { + dual.at(i, j) = cone.atIneq(i, j); + } + } + + // Now dual is of the form [ [a1, ..., an] , ... ] + // which is the V-representation of the dual. + return dual; +} + +// Converts a cone in V-representation to the H-representation +// of its dual, pointed at the origin (not at the original vertex). +// Essentially adds a column consisting only of zeroes to the end. +ConeH mlir::presburger::getDual(ConeV cone) +{ + ConeH dual = defineHRep(cone.getNumRows(), cone.getNumColumns()); + cone.insertColumn(cone.getNumColumns()); + + for (unsigned i = 0; i < cone.getNumRows(); i++) + dual.addInequality(cone.getRow(i)); + + // Now dual is of the form [ [a1, ..., an, 0] , ... ] + // which is the H-representation of the dual. + return dual; +} + +// Find the index of a cone in V-representation. +// If there are more rays than variables, return 0. +MPInt mlir::presburger::getIndex(ConeV cone) +{ + unsigned rows = cone.getNumRows(); + unsigned cols = cone.getNumColumns(); + if (rows > cols) + return MPInt(0); + + return cone.determinant(); +} \ No newline at end of file diff --git a/mlir/lib/Analysis/Presburger/CMakeLists.txt b/mlir/lib/Analysis/Presburger/CMakeLists.txt index e77e1623dae175..83d0514c9e7d17 100644 --- a/mlir/lib/Analysis/Presburger/CMakeLists.txt +++ b/mlir/lib/Analysis/Presburger/CMakeLists.txt @@ -1,4 +1,5 @@ add_mlir_library(MLIRPresburger + Barvinok.cpp IntegerRelation.cpp LinearTransform.cpp Matrix.cpp >From d7e4ee018d8f8f8e19376dcf01406f5cef64e2c5 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sat, 30 Dec 2023 22:53:15 +0530 Subject: [PATCH 07/32] Formatting --- .../mlir/Analysis/Presburger/Barvinok.h | 33 +++++---- mlir/lib/Analysis/Presburger/Barvinok.cpp | 70 +++++++++---------- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index c63ee1e230c8bf..6ffdf96502fd20 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -15,37 +15,46 @@ #ifndef MLIR_ANALYSIS_PRESBURGER_BARVINOK_H #define MLIR_ANALYSIS_PRESBURGER_BARVINOK_H -#include "mlir/Analysis/Presburger/Matrix.h" #include "mlir/Analysis/Presburger/IntegerRelation.h" +#include "mlir/Analysis/Presburger/Matrix.h" #include <optional> namespace mlir { namespace presburger { +// A polyhedron in H-representation is a set of relations +// in d variables with integer coefficients. using PolyhedronH = IntegerRelation; + +// A polyhedron in V-representation is a set of rays, i.e., +// vectors, stored as rows of a matrix. using PolyhedronV = IntMatrix; + +// A cone in either representation is a special case of +// a polyhedron in that representation. using ConeH = PolyhedronH; using ConeV = PolyhedronV; -inline ConeH defineHRep(int num_ineqs, int num_vars, int num_params = 0) -{ - // We don't distinguish between domain and range variables, so - // we set the number of domain variables as 0 and the number of - // range variables as the number of actual variables. - // There are no symbols (non-parametric for now) and no local - // (existentially quantified) variables. - ConeH cone(PresburgerSpace::getRelationSpace(0, num_vars, num_params, 0)); - return cone; +inline ConeH defineHRep(int num_ineqs, int num_vars, int num_params = 0) { + // We don't distinguish between domain and range variables, so + // we set the number of domain variables as 0 and the number of + // range variables as the number of actual variables. + // There are no symbols (non-parametric for now) and no local + // (existentially quantified) variables. + return ConeH(PresburgerSpace::getRelationSpace(/*numDomain=*/0, + /*numRange=*/num_vars, + /*numSymbols=*/num_params, + /*numLocals=*/0)); } // Get the index of a cone. // If it has more rays than the dimension, return 0. MPInt getIndex(ConeV); -// Get the dual of a cone in H-representation, returning the V-representation of it. +// Get the dual of a cone in H-representation, returning its V-representation. ConeV getDual(ConeH); -// Get the dual of a cone in V-representation, returning the H-representation of it. +// Get the dual of a cone in V-representation, returning its H-representation. ConeH getDual(ConeV); } // namespace presburger diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp index ddb24d1a79993f..698dde6f15d6f4 100644 --- a/mlir/lib/Analysis/Presburger/Barvinok.cpp +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -14,52 +14,50 @@ using namespace presburger; // Assuming that the input cone is pointed at the origin, // converts it to its dual in V-representation. // Essentially we just remove the all-zeroes constant column. -ConeV mlir::presburger::getDual(ConeH cone) -{ - ConeV dual(cone.getNumInequalities(), cone.getNumCols()-1, 0, 0); - // Assuming that an inequality of the form - // a1*x1 + ... + an*xn + b ≥ 0 - // is represented as a row [a1, ..., an, b] - // and that b = 0. - - for (unsigned i = 0; i < cone.getNumInequalities(); i++) - { - assert(dual.at(i, cone.getNumCols()-1) == 0 && "H-representation of cone is not centred at the origin!"); - for (unsigned j = 0; j < cone.getNumCols()-1; j++) - { - dual.at(i, j) = cone.atIneq(i, j); - } +ConeV mlir::presburger::getDual(ConeH cone) { + unsigned inequalities = cone.getNumInequalities(); + unsigned variables = cone.getNumCols() - 1; + ConeV dual(inequalities, variables, 0, 0); + // Assuming that an inequality of the form + // a1*x1 + ... + an*xn + b ≥ 0 + // is represented as a row [a1, ..., an, b] + // and that b = 0. + + for (unsigned i = 0; i < inequalities; i++) { + assert(dual.at(i, variables) == 0 && + "H-representation of cone is not centred at the origin!"); + for (unsigned j = 0; j < variables; j++) { + dual.at(i, j) = cone.atIneq(i, j); } + } - // Now dual is of the form [ [a1, ..., an] , ... ] - // which is the V-representation of the dual. - return dual; + // Now dual is of the form [ [a1, ..., an] , ... ] + // which is the V-representation of the dual. + return dual; } // Converts a cone in V-representation to the H-representation // of its dual, pointed at the origin (not at the original vertex). // Essentially adds a column consisting only of zeroes to the end. -ConeH mlir::presburger::getDual(ConeV cone) -{ - ConeH dual = defineHRep(cone.getNumRows(), cone.getNumColumns()); - cone.insertColumn(cone.getNumColumns()); - - for (unsigned i = 0; i < cone.getNumRows(); i++) - dual.addInequality(cone.getRow(i)); - - // Now dual is of the form [ [a1, ..., an, 0] , ... ] - // which is the H-representation of the dual. - return dual; +ConeH mlir::presburger::getDual(ConeV cone) { + unsigned rows = cone.getNumRows(); + unsigned columns = cone.getNumColumns(); + ConeH dual = defineHRep(rows, columns); + cone.insertColumn(columns); + + for (unsigned i = 0; i < rows; i++) + dual.addInequality(cone.getRow(i)); + + // Now dual is of the form [ [a1, ..., an, 0] , ... ] + // which is the H-representation of the dual. + return dual; } // Find the index of a cone in V-representation. // If there are more rays than variables, return 0. -MPInt mlir::presburger::getIndex(ConeV cone) -{ - unsigned rows = cone.getNumRows(); - unsigned cols = cone.getNumColumns(); - if (rows > cols) - return MPInt(0); +MPInt mlir::presburger::getIndex(ConeV cone) { + if (cone.getNumRows() > cone.getNumColumns()) + return MPInt(0); - return cone.determinant(); + return cone.determinant(); } \ No newline at end of file >From 3c6f4554019ac0c964e62351772cfc43db93b63f Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sat, 30 Dec 2023 23:32:49 +0530 Subject: [PATCH 08/32] Add tests for cone fns --- .../mlir/Analysis/Presburger/Barvinok.h | 7 +-- mlir/lib/Analysis/Presburger/Barvinok.cpp | 6 ++- .../Analysis/Presburger/BarvinokTest.cpp | 47 +++++++++++++++++++ .../Analysis/Presburger/CMakeLists.txt | 1 + 4 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 mlir/unittests/Analysis/Presburger/BarvinokTest.cpp diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index 6ffdf96502fd20..665227a20fc258 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -35,15 +35,16 @@ using PolyhedronV = IntMatrix; using ConeH = PolyhedronH; using ConeV = PolyhedronV; -inline ConeH defineHRep(int num_ineqs, int num_vars, int num_params = 0) { +inline ConeH defineHRep(int num_vars) { // We don't distinguish between domain and range variables, so // we set the number of domain variables as 0 and the number of // range variables as the number of actual variables. - // There are no symbols (non-parametric for now) and no local + // There are no symbols (we don't work with parametric cones) and no local // (existentially quantified) variables. + // Once the cone is defined, we use `addInequality()` to set inequalities. return ConeH(PresburgerSpace::getRelationSpace(/*numDomain=*/0, /*numRange=*/num_vars, - /*numSymbols=*/num_params, + /*numSymbols=*/0, /*numLocals=*/0)); } diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp index 698dde6f15d6f4..8c6fc9a6e3f53d 100644 --- a/mlir/lib/Analysis/Presburger/Barvinok.cpp +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -24,7 +24,7 @@ ConeV mlir::presburger::getDual(ConeH cone) { // and that b = 0. for (unsigned i = 0; i < inequalities; i++) { - assert(dual.at(i, variables) == 0 && + assert(cone.atIneq(i, variables) == 0 && "H-representation of cone is not centred at the origin!"); for (unsigned j = 0; j < variables; j++) { dual.at(i, j) = cone.atIneq(i, j); @@ -42,7 +42,9 @@ ConeV mlir::presburger::getDual(ConeH cone) { ConeH mlir::presburger::getDual(ConeV cone) { unsigned rows = cone.getNumRows(); unsigned columns = cone.getNumColumns(); - ConeH dual = defineHRep(rows, columns); + ConeH dual = defineHRep(columns); + // Add a new column (for constants) at the end. + // This will be initialized to zero. cone.insertColumn(columns); for (unsigned i = 0; i < rows; i++) diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp new file mode 100644 index 00000000000000..2b7f0491d588eb --- /dev/null +++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp @@ -0,0 +1,47 @@ +#include "mlir/Analysis/Presburger/Barvinok.h" +#include "./Utils.h" +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +using namespace mlir; +using namespace presburger; + +// We randomly generate 3 vectors with 4 entries each +// and define a cone's H-representation using these +// numbers. We check that the dual contains the same +// numbers. +// We do the same in the reverse case. +TEST(BarvinokTest, getDual) { + ConeH cone1 = defineHRep(4); + cone1.addInequality({1, 2, 3, 4, 0}); + cone1.addInequality({3, 4, 2, 5, 0}); + cone1.addInequality({6, 2, 6, 1, 0}); + + ConeV dual1 = getDual(cone1); + + EXPECT_EQ_INT_MATRIX( + dual1, makeIntMatrix(3, 4, {{1, 2, 3, 4}, {3, 4, 2, 5}, {6, 2, 6, 1}})); + + ConeV cone2 = makeIntMatrix(3, 4, {{3, 6, 1, 5}, {3, 1, 7, 2}, {9, 3, 2, 7}}); + + ConeH dual2 = getDual(cone2); + + ConeH expected = defineHRep(4); + expected.addInequality({3, 6, 1, 5, 0}); + expected.addInequality({3, 1, 7, 2, 0}); + expected.addInequality({9, 3, 2, 7, 0}); + + EXPECT_TRUE(dual2.isEqual(expected)); +} + +// We randomly generate a nxn matrix to use as a cone +// with n inequalities in n variables and check for +// the determinant being equal to the index. +TEST(BarvinokTest, getIndex) { + ConeV cone = makeIntMatrix(3, 3, {{4, 2, 1}, {5, 2, 7}, {4, 1, 6}}); + EXPECT_EQ(getIndex(cone), cone.determinant()); + + cone = makeIntMatrix( + 4, 4, {{4, 2, 5, 1}, {4, 1, 3, 6}, {8, 2, 5, 6}, {5, 2, 5, 7}}); + EXPECT_EQ(getIndex(cone), cone.determinant()); +} diff --git a/mlir/unittests/Analysis/Presburger/CMakeLists.txt b/mlir/unittests/Analysis/Presburger/CMakeLists.txt index e37133354e53ca..25f9e5939e4a25 100644 --- a/mlir/unittests/Analysis/Presburger/CMakeLists.txt +++ b/mlir/unittests/Analysis/Presburger/CMakeLists.txt @@ -1,4 +1,5 @@ add_mlir_unittest(MLIRPresburgerTests + BarvinokTest.cpp FractionTest.cpp IntegerPolyhedronTest.cpp IntegerRelationTest.cpp >From 08d6cd624edf9ddb92550fc6d65bc41f5d011fcf Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sun, 31 Dec 2023 00:18:43 +0530 Subject: [PATCH 09/32] Use public_namespace_name::detail --- mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h index 770d17fe17c307..e29478e97be02c 100644 --- a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h +++ b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h @@ -19,7 +19,7 @@ namespace mlir { namespace presburger { -namespace internal { +namespace public_namespace_name::detail { // A parametric point is a vector, each of whose elements // is an affine function of n parameters. Each row >From 6592268fdb1d8e31bb795b37b3d63707d312c08d Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sun, 31 Dec 2023 10:25:36 +0530 Subject: [PATCH 10/32] Formatting --- mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h index e29478e97be02c..abf9cce8c9d4d4 100644 --- a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h +++ b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h @@ -129,7 +129,7 @@ class GeneratingFunction { std::vector<std::vector<Point>> denominators; }; -} // namespace internal +} // namespace public_namespace_name::detail } // namespace presburger } // namespace mlir >From 7007cf83615ed479a0d7daab81a2b1eeb7514bbc Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sun, 31 Dec 2023 21:17:54 +0530 Subject: [PATCH 11/32] Documentation --- mlir/include/mlir/Analysis/Presburger/Barvinok.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index 665227a20fc258..d39d0e704bf4e4 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -22,11 +22,11 @@ namespace mlir { namespace presburger { -// A polyhedron in H-representation is a set of relations +// A polyhedron in H-representation is a set of inequalities // in d variables with integer coefficients. using PolyhedronH = IntegerRelation; -// A polyhedron in V-representation is a set of rays, i.e., +// A polyhedron in V-representation is a set of rays and points, i.e., // vectors, stored as rows of a matrix. using PolyhedronV = IntMatrix; @@ -48,14 +48,21 @@ inline ConeH defineHRep(int num_vars) { /*numLocals=*/0)); } -// Get the index of a cone. +// Get the index of a cone, i.e., the volume of the parallelepiped +// spanned by its generators, which is equal to the number of integer +// points in its fundamental parallelepiped. +// If the index is 1, the cone is unimodular. +// Barvinok, A., and J. E. Pommersheim. "An algorithmic theory of lattice points in polyhedra." +// p. 107 // If it has more rays than the dimension, return 0. MPInt getIndex(ConeV); // Get the dual of a cone in H-representation, returning its V-representation. +// This assumes that the input is pointed at the origin; it fails otherwise. ConeV getDual(ConeH); // Get the dual of a cone in V-representation, returning its H-representation. +// The returned cone is pointed at the origin. ConeH getDual(ConeV); } // namespace presburger >From 9419d5b426261476d6bfda938b9457a030fe6f39 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sun, 31 Dec 2023 21:20:33 +0530 Subject: [PATCH 12/32] Use getSetSpace --- mlir/include/mlir/Analysis/Presburger/Barvinok.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index d39d0e704bf4e4..2acf9f68cb3c9e 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -42,10 +42,9 @@ inline ConeH defineHRep(int num_vars) { // There are no symbols (we don't work with parametric cones) and no local // (existentially quantified) variables. // Once the cone is defined, we use `addInequality()` to set inequalities. - return ConeH(PresburgerSpace::getRelationSpace(/*numDomain=*/0, - /*numRange=*/num_vars, - /*numSymbols=*/0, - /*numLocals=*/0)); + return ConeH(PresburgerSpace::getSetSpace(/*numDims=*/num_vars, + /*numSymbols=*/0, + /*numLocals=*/0)); } // Get the index of a cone, i.e., the volume of the parallelepiped >From edf909e8945f629abf0c04865d669d130dd390da Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sun, 31 Dec 2023 21:21:28 +0530 Subject: [PATCH 13/32] Clang-format --- mlir/include/mlir/Analysis/Presburger/Barvinok.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index 2acf9f68cb3c9e..c8d61641a47b5a 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -51,9 +51,8 @@ inline ConeH defineHRep(int num_vars) { // spanned by its generators, which is equal to the number of integer // points in its fundamental parallelepiped. // If the index is 1, the cone is unimodular. -// Barvinok, A., and J. E. Pommersheim. "An algorithmic theory of lattice points in polyhedra." -// p. 107 -// If it has more rays than the dimension, return 0. +// Barvinok, A., and J. E. Pommersheim. "An algorithmic theory of lattice points +// in polyhedra." p. 107 If it has more rays than the dimension, return 0. MPInt getIndex(ConeV); // Get the dual of a cone in H-representation, returning its V-representation. >From e5bcf072b98e5bb13ceae52ce44a7e80e87a9141 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sun, 31 Dec 2023 21:47:21 +0530 Subject: [PATCH 14/32] Add newlines --- mlir/include/mlir/Analysis/Presburger/Barvinok.h | 2 +- mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h | 2 +- mlir/lib/Analysis/Presburger/Barvinok.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 c8d61641a47b5a..c168ddf12be1e8 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -66,4 +66,4 @@ ConeH getDual(ConeV); } // namespace presburger } // namespace mlir -#endif // MLIR_ANALYSIS_PRESBURGER_BARVINOK_H \ No newline at end of file +#endif // MLIR_ANALYSIS_PRESBURGER_BARVINOK_H diff --git a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h index abf9cce8c9d4d4..fcc5c8c1dea15c 100644 --- a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h +++ b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h @@ -133,4 +133,4 @@ class GeneratingFunction { } // namespace presburger } // namespace mlir -#endif // MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H \ No newline at end of file +#endif // MLIR_ANALYSIS_PRESBURGER_GENERATINGFUNCTION_H diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp index 8c6fc9a6e3f53d..348797a8a3f137 100644 --- a/mlir/lib/Analysis/Presburger/Barvinok.cpp +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -62,4 +62,4 @@ MPInt mlir::presburger::getIndex(ConeV cone) { return MPInt(0); return cone.determinant(); -} \ No newline at end of file +} >From 3cf91b99ce361eddfd2ed470f7f9d7e1ead3c959 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Thu, 4 Jan 2024 21:38:37 +0530 Subject: [PATCH 15/32] Documentation and var namesg --- mlir/include/mlir/Analysis/Presburger/Barvinok.h | 6 ++++-- .../mlir/Analysis/Presburger/GeneratingFunction.h | 2 -- mlir/lib/Analysis/Presburger/Barvinok.cpp | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index c168ddf12be1e8..cc98f1272bdd45 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -52,11 +52,13 @@ inline ConeH defineHRep(int num_vars) { // points in its fundamental parallelepiped. // If the index is 1, the cone is unimodular. // Barvinok, A., and J. E. Pommersheim. "An algorithmic theory of lattice points -// in polyhedra." p. 107 If it has more rays than the dimension, return 0. +// in polyhedra." p. 107 +// If it has more rays than the dimension, return 0. MPInt getIndex(ConeV); // Get the dual of a cone in H-representation, returning its V-representation. -// This assumes that the input is pointed at the origin; it fails otherwise. +// This assumes that the input is pointed at the origin; it assert-fails +// otherwise. ConeV getDual(ConeH); // Get the dual of a cone in V-representation, returning its H-representation. diff --git a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h index fcc5c8c1dea15c..f7deba921ea51e 100644 --- a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h +++ b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h @@ -19,7 +19,6 @@ namespace mlir { namespace presburger { -namespace public_namespace_name::detail { // A parametric point is a vector, each of whose elements // is an affine function of n parameters. Each row @@ -129,7 +128,6 @@ class GeneratingFunction { std::vector<std::vector<Point>> denominators; }; -} // namespace public_namespace_name::detail } // namespace presburger } // namespace mlir diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp index 348797a8a3f137..f3c70aa0b5a1f9 100644 --- a/mlir/lib/Analysis/Presburger/Barvinok.cpp +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -15,18 +15,18 @@ using namespace presburger; // converts it to its dual in V-representation. // Essentially we just remove the all-zeroes constant column. ConeV mlir::presburger::getDual(ConeH cone) { - unsigned inequalities = cone.getNumInequalities(); - unsigned variables = cone.getNumCols() - 1; - ConeV dual(inequalities, variables, 0, 0); + unsigned numIneq = cone.getNumInequalities(); + unsigned numVar = cone.getNumCols() - 1; + ConeV dual(numIneq, numVar, 0, 0); // Assuming that an inequality of the form // a1*x1 + ... + an*xn + b ≥ 0 // is represented as a row [a1, ..., an, b] // and that b = 0. - for (unsigned i = 0; i < inequalities; i++) { - assert(cone.atIneq(i, variables) == 0 && + for (unsigned i = 0; i < numIneq; i++) { + assert(cone.atIneq(i, numVar) == 0 && "H-representation of cone is not centred at the origin!"); - for (unsigned j = 0; j < variables; j++) { + for (unsigned j = 0; j < numVar; j++) { dual.at(i, j) = cone.atIneq(i, j); } } >From b634957c9829564de2c15a599bdaf1f885a2bea0 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Thu, 4 Jan 2024 21:41:09 +0530 Subject: [PATCH 16/32] Namespace detail for Barvinok.h --- mlir/include/mlir/Analysis/Presburger/Barvinok.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index cc98f1272bdd45..de7d75aedd5f18 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -21,6 +21,7 @@ namespace mlir { namespace presburger { +namespace detail { // A polyhedron in H-representation is a set of inequalities // in d variables with integer coefficients. @@ -65,6 +66,7 @@ ConeV getDual(ConeH); // The returned cone is pointed at the origin. ConeH getDual(ConeV); +} // namespace detail } // namespace presburger } // namespace mlir >From a23d7e71ac91ad115dda3e181af0a409e07038dc Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Fri, 5 Jan 2024 14:26:24 +0530 Subject: [PATCH 17/32] Update doc --- mlir/unittests/Analysis/Presburger/BarvinokTest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp index 2b7f0491d588eb..301b1b200b32e4 100644 --- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp +++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp @@ -6,10 +6,10 @@ using namespace mlir; using namespace presburger; -// We randomly generate 3 vectors with 4 entries each -// and define a cone's H-representation using these -// numbers. We check that the dual contains the same -// numbers. +// The following are 3 randomly generated vectors with 4 +// entries each and define a cone's H-representation +// using these numbers. We check that the dual contains +// the same numbers. // We do the same in the reverse case. TEST(BarvinokTest, getDual) { ConeH cone1 = defineHRep(4); >From 5a286e50eb3cf7a5d744ce36153020badf664819 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Fri, 5 Jan 2024 14:54:28 +0530 Subject: [PATCH 18/32] Remove buggy namespace detail and shift GF back --- mlir/include/mlir/Analysis/Presburger/Barvinok.h | 2 -- .../mlir => lib}/Analysis/Presburger/GeneratingFunction.h | 0 2 files changed, 2 deletions(-) rename mlir/{include/mlir => lib}/Analysis/Presburger/GeneratingFunction.h (100%) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index de7d75aedd5f18..cc98f1272bdd45 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -21,7 +21,6 @@ namespace mlir { namespace presburger { -namespace detail { // A polyhedron in H-representation is a set of inequalities // in d variables with integer coefficients. @@ -66,7 +65,6 @@ ConeV getDual(ConeH); // The returned cone is pointed at the origin. ConeH getDual(ConeV); -} // namespace detail } // namespace presburger } // namespace mlir diff --git a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h b/mlir/lib/Analysis/Presburger/GeneratingFunction.h similarity index 100% rename from mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h rename to mlir/lib/Analysis/Presburger/GeneratingFunction.h >From 6ec7090a66caa73b4122238e355772f96f9b6fca Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Fri, 5 Jan 2024 14:58:39 +0530 Subject: [PATCH 19/32] Add namespace detail --- mlir/include/mlir/Analysis/Presburger/Barvinok.h | 2 ++ mlir/lib/Analysis/Presburger/Barvinok.cpp | 7 ++++--- mlir/unittests/Analysis/Presburger/BarvinokTest.cpp | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index cc98f1272bdd45..7165eee82772ad 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -21,6 +21,7 @@ namespace mlir { namespace presburger { +namespace detail { // A polyhedron in H-representation is a set of inequalities // in d variables with integer coefficients. @@ -65,6 +66,7 @@ ConeV getDual(ConeH); // The returned cone is pointed at the origin. ConeH getDual(ConeV); +} // namespace mlir::presburger::detail } // namespace presburger } // namespace mlir diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp index f3c70aa0b5a1f9..c01a13db2d96ac 100644 --- a/mlir/lib/Analysis/Presburger/Barvinok.cpp +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -10,11 +10,12 @@ using namespace mlir; using namespace presburger; +using namespace mlir::presburger::detail; // Assuming that the input cone is pointed at the origin, // converts it to its dual in V-representation. // Essentially we just remove the all-zeroes constant column. -ConeV mlir::presburger::getDual(ConeH cone) { +ConeV mlir::presburger::detail::getDual(ConeH cone) { unsigned numIneq = cone.getNumInequalities(); unsigned numVar = cone.getNumCols() - 1; ConeV dual(numIneq, numVar, 0, 0); @@ -39,7 +40,7 @@ ConeV mlir::presburger::getDual(ConeH cone) { // Converts a cone in V-representation to the H-representation // of its dual, pointed at the origin (not at the original vertex). // Essentially adds a column consisting only of zeroes to the end. -ConeH mlir::presburger::getDual(ConeV cone) { +ConeH mlir::presburger::detail::getDual(ConeV cone) { unsigned rows = cone.getNumRows(); unsigned columns = cone.getNumColumns(); ConeH dual = defineHRep(columns); @@ -57,7 +58,7 @@ ConeH mlir::presburger::getDual(ConeV cone) { // Find the index of a cone in V-representation. // If there are more rays than variables, return 0. -MPInt mlir::presburger::getIndex(ConeV cone) { +MPInt mlir::presburger::detail::getIndex(ConeV cone) { if (cone.getNumRows() > cone.getNumColumns()) return MPInt(0); diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp index 301b1b200b32e4..ae5bb65571cfc4 100644 --- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp +++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp @@ -5,6 +5,7 @@ using namespace mlir; using namespace presburger; +using namespace mlir::presburger::detail; // The following are 3 randomly generated vectors with 4 // entries each and define a cone's H-representation >From b8c7e1084d8b43c9dc6904b2010f7366d080a21c Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Fri, 5 Jan 2024 15:01:22 +0530 Subject: [PATCH 20/32] Formatting --- 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 7165eee82772ad..de7d75aedd5f18 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -66,7 +66,7 @@ ConeV getDual(ConeH); // The returned cone is pointed at the origin. ConeH getDual(ConeV); -} // namespace mlir::presburger::detail +} // namespace detail } // namespace presburger } // namespace mlir >From 71060a8921bbb7855fae6db83ab61c6ab6359248 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Fri, 5 Jan 2024 18:47:09 +0530 Subject: [PATCH 21/32] Fix style --- .../mlir/Analysis/Presburger/Barvinok.h | 64 +++++++++++-------- mlir/lib/Analysis/Presburger/Barvinok.cpp | 43 ++++++------- .../Analysis/Presburger/BarvinokTest.cpp | 16 ++--- 3 files changed, 65 insertions(+), 58 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index de7d75aedd5f18..e937f0ea64b40a 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -6,10 +6,16 @@ // //===----------------------------------------------------------------------===// // -// Functions relating to Barvinok's algorithm. +// Functions relating to an implementation of Barvinok's algorithm. // These include functions to manipulate cones (define a cone object, get its // dual, and find its index). // +// Barvinok, Alexander, and James E. Pommersheim. "An algorithmic theory of +// lattice points in polyhedra." New perspectives in algebraic combinatorics +// 38 (1999): 91-147. +// Verdoolaege, Sven, et al. "Counting integer points in parametric polytopes +// using Barvinok's rational functions." Algorithmica 48 (2007): 37-66. +// //===----------------------------------------------------------------------===// #ifndef MLIR_ANALYSIS_PRESBURGER_BARVINOK_H @@ -23,48 +29,50 @@ namespace mlir { namespace presburger { namespace detail { -// A polyhedron in H-representation is a set of inequalities -// in d variables with integer coefficients. +/// A polyhedron in H-representation is a set of inequalities +/// in d variables with integer coefficients. using PolyhedronH = IntegerRelation; -// A polyhedron in V-representation is a set of rays and points, i.e., -// vectors, stored as rows of a matrix. +/// A polyhedron in V-representation is a set of rays and points, i.e., +/// vectors, stored as rows of a matrix. using PolyhedronV = IntMatrix; -// A cone in either representation is a special case of -// a polyhedron in that representation. +/// A cone in either representation is a special case of +/// a polyhedron in that representation. using ConeH = PolyhedronH; using ConeV = PolyhedronV; inline ConeH defineHRep(int num_vars) { - // We don't distinguish between domain and range variables, so - // we set the number of domain variables as 0 and the number of - // range variables as the number of actual variables. - // There are no symbols (we don't work with parametric cones) and no local - // (existentially quantified) variables. - // Once the cone is defined, we use `addInequality()` to set inequalities. + /// We don't distinguish between domain and range variables, so + /// we set the number of domain variables as 0 and the number of + /// range variables as the number of actual variables. + /// There are no symbols (we don't work with parametric cones) and no local + /// (existentially quantified) variables. + /// Once the cone is defined, we use `addInequality()` to set inequalities. return ConeH(PresburgerSpace::getSetSpace(/*numDims=*/num_vars, /*numSymbols=*/0, /*numLocals=*/0)); } -// Get the index of a cone, i.e., the volume of the parallelepiped -// spanned by its generators, which is equal to the number of integer -// points in its fundamental parallelepiped. -// If the index is 1, the cone is unimodular. -// Barvinok, A., and J. E. Pommersheim. "An algorithmic theory of lattice points -// in polyhedra." p. 107 -// If it has more rays than the dimension, return 0. -MPInt getIndex(ConeV); +/// Get the index of a cone, i.e., the volume of the parallelepiped +/// spanned by its generators, which is equal to the number of integer +/// points in its fundamental parallelepiped. +/// If the index is 1, the cone is unimodular. +/// Barvinok, A., and J. E. Pommersheim. "An algorithmic theory of lattice +/// points in polyhedra." p. 107 If it has more rays than the dimension, return +/// 0. +MPInt getIndex(ConeV cone); -// Get the dual of a cone in H-representation, returning its V-representation. -// This assumes that the input is pointed at the origin; it assert-fails -// otherwise. -ConeV getDual(ConeH); +/// Given a cone in H-representation, return its dual. The dual cone is in +/// V-representation. +/// This assumes that the input is pointed at the origin; it assert-fails +/// otherwise. +ConeV getDual(ConeH cone); -// Get the dual of a cone in V-representation, returning its H-representation. -// The returned cone is pointed at the origin. -ConeH getDual(ConeV); +/// Given a cone in V-representation, return its dual. The dual cone is in +/// H-representation. +/// The returned cone is pointed at the origin. +ConeH getDual(ConeV cone); } // namespace detail } // namespace presburger diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp index c01a13db2d96ac..a857d4a51514f5 100644 --- a/mlir/lib/Analysis/Presburger/Barvinok.cpp +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -1,4 +1,4 @@ -//===- QuasiPolynomial.cpp - Barvinok's Algorithm ---------------*- C++ -*-===// +//===- Barvinok.cpp - 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. @@ -12,52 +12,51 @@ using namespace mlir; using namespace presburger; using namespace mlir::presburger::detail; -// Assuming that the input cone is pointed at the origin, -// converts it to its dual in V-representation. -// Essentially we just remove the all-zeroes constant column. +/// Assuming that the input cone is pointed at the origin, +/// converts it to its dual in V-representation. +/// Essentially we just remove the all-zeroes constant column. ConeV mlir::presburger::detail::getDual(ConeH cone) { unsigned numIneq = cone.getNumInequalities(); unsigned numVar = cone.getNumCols() - 1; ConeV dual(numIneq, numVar, 0, 0); - // Assuming that an inequality of the form - // a1*x1 + ... + an*xn + b ≥ 0 - // is represented as a row [a1, ..., an, b] - // and that b = 0. + /// Assuming that an inequality of the form + /// a1*x1 + ... + an*xn + b ≥ 0 + /// is represented as a row [a1, ..., an, b] + /// and that b = 0. - for (unsigned i = 0; i < numIneq; i++) { + for (unsigned i = 0; i < numIneq; ++i) { assert(cone.atIneq(i, numVar) == 0 && "H-representation of cone is not centred at the origin!"); - for (unsigned j = 0; j < numVar; j++) { + for (unsigned j = 0; j < numVar; ++j) { dual.at(i, j) = cone.atIneq(i, j); } } - // Now dual is of the form [ [a1, ..., an] , ... ] - // which is the V-representation of the dual. + /// Now dual is of the form [ [a1, ..., an] , ... ] + /// which is the V-representation of the dual. return dual; } -// Converts a cone in V-representation to the H-representation -// of its dual, pointed at the origin (not at the original vertex). -// Essentially adds a column consisting only of zeroes to the end. +/// Converts a cone in V-representation to the H-representation +/// of its dual, pointed at the origin (not at the original vertex). +/// Essentially adds a column consisting only of zeroes to the end. ConeH mlir::presburger::detail::getDual(ConeV cone) { unsigned rows = cone.getNumRows(); unsigned columns = cone.getNumColumns(); ConeH dual = defineHRep(columns); - // Add a new column (for constants) at the end. - // This will be initialized to zero. + /// Add a new column (for constants) at the end. + /// This will be initialized to zero. cone.insertColumn(columns); - for (unsigned i = 0; i < rows; i++) + for (unsigned i = 0; i < rows; ++i) dual.addInequality(cone.getRow(i)); - // Now dual is of the form [ [a1, ..., an, 0] , ... ] - // which is the H-representation of the dual. + /// Now dual is of the form [ [a1, ..., an, 0] , ... ] + /// which is the H-representation of the dual. return dual; } -// Find the index of a cone in V-representation. -// If there are more rays than variables, return 0. +/// Find the index of a cone in V-representation. MPInt mlir::presburger::detail::getIndex(ConeV cone) { if (cone.getNumRows() > cone.getNumColumns()) return MPInt(0); diff --git a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp index ae5bb65571cfc4..b88baa6c6b48a4 100644 --- a/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp +++ b/mlir/unittests/Analysis/Presburger/BarvinokTest.cpp @@ -7,11 +7,11 @@ using namespace mlir; using namespace presburger; using namespace mlir::presburger::detail; -// The following are 3 randomly generated vectors with 4 -// entries each and define a cone's H-representation -// using these numbers. We check that the dual contains -// the same numbers. -// We do the same in the reverse case. +/// The following are 3 randomly generated vectors with 4 +/// entries each and define a cone's H-representation +/// using these numbers. We check that the dual contains +/// the same numbers. +/// We do the same in the reverse case. TEST(BarvinokTest, getDual) { ConeH cone1 = defineHRep(4); cone1.addInequality({1, 2, 3, 4, 0}); @@ -35,9 +35,9 @@ TEST(BarvinokTest, getDual) { EXPECT_TRUE(dual2.isEqual(expected)); } -// We randomly generate a nxn matrix to use as a cone -// with n inequalities in n variables and check for -// the determinant being equal to the index. +/// We randomly generate a nxn matrix to use as a cone +/// with n inequalities in n variables and check for +/// the determinant being equal to the index. TEST(BarvinokTest, getIndex) { ConeV cone = makeIntMatrix(3, 3, {{4, 2, 1}, {5, 2, 7}, {4, 1, 6}}); EXPECT_EQ(getIndex(cone), cone.determinant()); >From e30dbbcd513b58a73faf87872c5ef793c41bf39b Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Fri, 5 Jan 2024 19:00:22 +0530 Subject: [PATCH 22/32] Doc fix --- mlir/include/mlir/Analysis/Presburger/Barvinok.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index e937f0ea64b40a..a472ef7c1cfa3e 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -10,11 +10,12 @@ // These include functions to manipulate cones (define a cone object, get its // dual, and find its index). // -// Barvinok, Alexander, and James E. Pommersheim. "An algorithmic theory of -// lattice points in polyhedra." New perspectives in algebraic combinatorics -// 38 (1999): 91-147. -// Verdoolaege, Sven, et al. "Counting integer points in parametric polytopes -// using Barvinok's rational functions." Algorithmica 48 (2007): 37-66. +// The implementation is based on: +// 1. Barvinok, Alexander, and James E. Pommersheim. "An algorithmic theory of +// lattice points in polyhedra." New perspectives in algebraic combinatorics +// 38 (1999): 91-147. +// 2. Verdoolaege, Sven, et al. "Counting integer points in parametric polytopes +// using Barvinok's rational functions." Algorithmica 48 (2007): 37-66. // //===----------------------------------------------------------------------===// >From 097d97dd16ac91904361095f06ef66127412fd01 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Fri, 5 Jan 2024 19:00:46 +0530 Subject: [PATCH 23/32] Formatting --- mlir/include/mlir/Analysis/Presburger/Barvinok.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index a472ef7c1cfa3e..ad753e5bb05e15 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -14,8 +14,9 @@ // 1. Barvinok, Alexander, and James E. Pommersheim. "An algorithmic theory of // lattice points in polyhedra." New perspectives in algebraic combinatorics // 38 (1999): 91-147. -// 2. Verdoolaege, Sven, et al. "Counting integer points in parametric polytopes -// using Barvinok's rational functions." Algorithmica 48 (2007): 37-66. +// 2. Verdoolaege, Sven, et al. "Counting integer points in parametric +// polytopes using Barvinok's rational functions." Algorithmica 48 (2007): +// 37-66. // //===----------------------------------------------------------------------===// >From d781192c336b9883fb22e1a0a32b72d6584d5aec Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Fri, 5 Jan 2024 19:02:13 +0530 Subject: [PATCH 24/32] Make WIP explicit --- mlir/include/mlir/Analysis/Presburger/Barvinok.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index ad753e5bb05e15..362d3ea7cf3160 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -6,7 +6,8 @@ // //===----------------------------------------------------------------------===// // -// Functions relating to an implementation of Barvinok's algorithm. +// Implementation of Barvinok's algorithm and related utility functions. +// Currently a work in progress. // These include functions to manipulate cones (define a cone object, get its // dual, and find its index). // >From b96b9fb3ca140e98e75f5ebe58781186fcecefb6 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Fri, 5 Jan 2024 19:09:02 +0530 Subject: [PATCH 25/32] Fix comment style --- .../mlir/Analysis/Presburger/Barvinok.h | 12 +++++------ mlir/lib/Analysis/Presburger/Barvinok.cpp | 20 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index 362d3ea7cf3160..6110a476a633bb 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -46,12 +46,12 @@ using ConeH = PolyhedronH; using ConeV = PolyhedronV; inline ConeH defineHRep(int num_vars) { - /// We don't distinguish between domain and range variables, so - /// we set the number of domain variables as 0 and the number of - /// range variables as the number of actual variables. - /// There are no symbols (we don't work with parametric cones) and no local - /// (existentially quantified) variables. - /// Once the cone is defined, we use `addInequality()` to set inequalities. + // We don't distinguish between domain and range variables, so + // we set the number of domain variables as 0 and the number of + // range variables as the number of actual variables. + // There are no symbols (we don't work with parametric cones) and no local + // (existentially quantified) variables. + // Once the cone is defined, we use `addInequality()` to set inequalities. return ConeH(PresburgerSpace::getSetSpace(/*numDims=*/num_vars, /*numSymbols=*/0, /*numLocals=*/0)); diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp index a857d4a51514f5..9152b66968a1f5 100644 --- a/mlir/lib/Analysis/Presburger/Barvinok.cpp +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -19,10 +19,10 @@ ConeV mlir::presburger::detail::getDual(ConeH cone) { unsigned numIneq = cone.getNumInequalities(); unsigned numVar = cone.getNumCols() - 1; ConeV dual(numIneq, numVar, 0, 0); - /// Assuming that an inequality of the form - /// a1*x1 + ... + an*xn + b ≥ 0 - /// is represented as a row [a1, ..., an, b] - /// and that b = 0. + // Assuming that an inequality of the form + // a1*x1 + ... + an*xn + b ≥ 0 + // is represented as a row [a1, ..., an, b] + // and that b = 0. for (unsigned i = 0; i < numIneq; ++i) { assert(cone.atIneq(i, numVar) == 0 && @@ -32,8 +32,8 @@ ConeV mlir::presburger::detail::getDual(ConeH cone) { } } - /// Now dual is of the form [ [a1, ..., an] , ... ] - /// which is the V-representation of the dual. + // Now dual is of the form [ [a1, ..., an] , ... ] + // which is the V-representation of the dual. return dual; } @@ -44,15 +44,15 @@ ConeH mlir::presburger::detail::getDual(ConeV cone) { unsigned rows = cone.getNumRows(); unsigned columns = cone.getNumColumns(); ConeH dual = defineHRep(columns); - /// Add a new column (for constants) at the end. - /// This will be initialized to zero. + // Add a new column (for constants) at the end. + // This will be initialized to zero. cone.insertColumn(columns); for (unsigned i = 0; i < rows; ++i) dual.addInequality(cone.getRow(i)); - /// Now dual is of the form [ [a1, ..., an, 0] , ... ] - /// which is the H-representation of the dual. + // Now dual is of the form [ [a1, ..., an, 0] , ... ] + // which is the H-representation of the dual. return dual; } >From 3cc29c3ce2e9c5af6bc493eacb06d42f26b2a6a5 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Fri, 5 Jan 2024 21:45:46 +0530 Subject: [PATCH 26/32] Fix variable name --- 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 6110a476a633bb..15e805860db237 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -45,14 +45,14 @@ using PolyhedronV = IntMatrix; using ConeH = PolyhedronH; using ConeV = PolyhedronV; -inline ConeH defineHRep(int num_vars) { +inline ConeH defineHRep(int numVars) { // We don't distinguish between domain and range variables, so // we set the number of domain variables as 0 and the number of // range variables as the number of actual variables. // There are no symbols (we don't work with parametric cones) and no local // (existentially quantified) variables. // Once the cone is defined, we use `addInequality()` to set inequalities. - return ConeH(PresburgerSpace::getSetSpace(/*numDims=*/num_vars, + return ConeH(PresburgerSpace::getSetSpace(/*numDims=*/numVars, /*numSymbols=*/0, /*numLocals=*/0)); } >From 8fe3212272ed113eebeac99a35f8a3f9a97f2d3f Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Fri, 5 Jan 2024 21:55:19 +0530 Subject: [PATCH 27/32] Shift GF and make namespace --- .../mlir}/Analysis/Presburger/GeneratingFunction.h | 2 ++ 1 file changed, 2 insertions(+) rename mlir/{lib => include/mlir}/Analysis/Presburger/GeneratingFunction.h (99%) diff --git a/mlir/lib/Analysis/Presburger/GeneratingFunction.h b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h similarity index 99% rename from mlir/lib/Analysis/Presburger/GeneratingFunction.h rename to mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h index f7deba921ea51e..318f1a6429a6c0 100644 --- a/mlir/lib/Analysis/Presburger/GeneratingFunction.h +++ b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h @@ -19,6 +19,7 @@ namespace mlir { namespace presburger { +namespace detail { // A parametric point is a vector, each of whose elements // is an affine function of n parameters. Each row @@ -128,6 +129,7 @@ class GeneratingFunction { std::vector<std::vector<Point>> denominators; }; +} // namespace detail } // namespace presburger } // namespace mlir >From f28ec4a9ac4035e8a784f393ce92a84e3616b1a8 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sat, 6 Jan 2024 16:04:20 +0530 Subject: [PATCH 28/32] Add GF test --- .../Analysis/Presburger/GeneratingFunction.h | 2 +- .../Analysis/Presburger/CMakeLists.txt | 1 + .../Presburger/GeneratingFunctionTest.cpp | 30 +++++++++++++++++ mlir/unittests/Analysis/Presburger/Utils.h | 32 +++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp diff --git a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h index 318f1a6429a6c0..0ef095dc80e604 100644 --- a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h +++ b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h @@ -84,7 +84,7 @@ class GeneratingFunction { std::vector<std::vector<Point>> sumDenominators = denominators; sumDenominators.insert(sumDenominators.end(), gf.denominators.begin(), gf.denominators.end()); - return GeneratingFunction(0, sumSigns, sumNumerators, sumDenominators); + return GeneratingFunction(numParam, sumSigns, sumNumerators, sumDenominators); } llvm::raw_ostream &print(llvm::raw_ostream &os) const { diff --git a/mlir/unittests/Analysis/Presburger/CMakeLists.txt b/mlir/unittests/Analysis/Presburger/CMakeLists.txt index e37133354e53ca..54a841726cd11f 100644 --- a/mlir/unittests/Analysis/Presburger/CMakeLists.txt +++ b/mlir/unittests/Analysis/Presburger/CMakeLists.txt @@ -1,5 +1,6 @@ add_mlir_unittest(MLIRPresburgerTests FractionTest.cpp + GeneratingFunctionTest.cpp IntegerPolyhedronTest.cpp IntegerRelationTest.cpp LinearTransformTest.cpp diff --git a/mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp b/mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp new file mode 100644 index 00000000000000..bb3345db6240a0 --- /dev/null +++ b/mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp @@ -0,0 +1,30 @@ +//===- MatrixTest.cpp - Tests for QuasiPolynomial -------------------------===// +// +// 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/GeneratingFunction.h" +#include "./Utils.h" +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +using namespace mlir; +using namespace presburger; +using namespace mlir::presburger::detail; + +TEST(GeneratingFunctionTest, sum) { + GeneratingFunction gf1(2, {1, -1}, + {makeFracMatrix(2, 3, {{1, 2, 5}, {7, 2, 6}}), makeFracMatrix(2, 3, {{5, 2, 5}, {3, 7, 2}})}, + {{{3, 6}, {7, 2}}, {{2, 8}, {6, 3}}}); + GeneratingFunction gf2(2, {1, 1}, + {makeFracMatrix(2, 3, {{6, 2, 1}, {4, 2, 6}}), makeFracMatrix(2, 3, {{3, 2, 6}, {9, 2, 5}})}, + {{{3, 7}, {5, 1}}, {{5, 2}, {6, 2}}}); + + GeneratingFunction sum = gf1 + gf2; + EXPECT_EQ_REPR_GENERATINGFUNCTION(sum, GeneratingFunction(2, {1, -1, 1, 1}, + {makeFracMatrix(2, 3, {{1, 2, 5}, {7, 2, 6}}), makeFracMatrix(2, 3, {{5, 2, 5}, {3, 7, 2}}), makeFracMatrix(2, 3, {{6, 2, 1}, {4, 2, 6}}), makeFracMatrix(2, 3, {{3, 2, 6}, {9, 2, 5}})}, + {{{3, 6}, {7, 2}}, {{2, 8}, {6, 3}}, {{3, 7}, {5, 1}}, {{5, 2}, {6, 2}}})); +} \ No newline at end of file diff --git a/mlir/unittests/Analysis/Presburger/Utils.h b/mlir/unittests/Analysis/Presburger/Utils.h index 2a9966c7ce2ea5..38c44aec4047f0 100644 --- a/mlir/unittests/Analysis/Presburger/Utils.h +++ b/mlir/unittests/Analysis/Presburger/Utils.h @@ -13,6 +13,7 @@ #ifndef MLIR_UNITTESTS_ANALYSIS_PRESBURGER_UTILS_H #define MLIR_UNITTESTS_ANALYSIS_PRESBURGER_UTILS_H +#include "mlir/Analysis/Presburger/GeneratingFunction.h" #include "mlir/Analysis/Presburger/IntegerRelation.h" #include "mlir/Analysis/Presburger/Matrix.h" #include "mlir/Analysis/Presburger/PWMAFunction.h" @@ -72,6 +73,37 @@ inline void EXPECT_EQ_FRAC_MATRIX(FracMatrix a, FracMatrix b) { EXPECT_EQ(a(row, col), b(row, col)); } +// Check the coefficients (in order) of two generating functions. +// Note that this is not a true equality check. +inline void EXPECT_EQ_REPR_GENERATINGFUNCTION(detail::GeneratingFunction a, detail::GeneratingFunction b) { + EXPECT_EQ(a.getNumParams(), b.getNumParams()); + + SmallVector<int> aSigns = a.getSigns(); + SmallVector<int> bSigns = b.getSigns(); + EXPECT_EQ(aSigns.size(), bSigns.size()); + for (unsigned i = 0, e = aSigns.size(); i < e; i++) + EXPECT_EQ(aSigns[i], bSigns[i]); + + std::vector<detail::ParamPoint> aNums = a.getNumerators(); + std::vector<detail::ParamPoint> bNums = b.getNumerators(); + EXPECT_EQ(aNums.size(), bNums.size()); + for (unsigned i = 0, e = aNums.size(); i < e; i++) + EXPECT_EQ_FRAC_MATRIX(aNums[i], bNums[i]); + + std::vector<std::vector<detail::Point>> aDens = a.getDenominators(); + std::vector<std::vector<detail::Point>> bDens = b.getDenominators(); + EXPECT_EQ(aDens.size(), bDens.size()); + for (unsigned i = 0, e = aDens.size(); i < e; i++) { + EXPECT_EQ(aDens[i].size(), bDens[i].size()); + for (unsigned j = 0, f = aDens[i].size(); j < f; j++) { + EXPECT_EQ(aDens[i][j].size(), bDens[i][j].size()); + for (unsigned k = 0, g = aDens[i][j].size(); k < g; k++) { + EXPECT_EQ(aDens[i][j][k], bDens[i][j][k]); + } + } + } +} + // Check the coefficients (in order) of two quasipolynomials. // Note that this is not a true equality check. inline void EXPECT_EQ_REPR_QUASIPOLYNOMIAL(QuasiPolynomial a, QuasiPolynomial b) { >From 364ca80e2988abd3b521bb7886a17b0088dce8f7 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sat, 6 Jan 2024 16:05:25 +0530 Subject: [PATCH 29/32] Formatting --- .../Presburger/GeneratingFunctionTest.cpp | 21 +++++++++++++------ mlir/unittests/Analysis/Presburger/Utils.h | 6 ++++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp b/mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp index bb3345db6240a0..c2701a441efd04 100644 --- a/mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp +++ b/mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp @@ -17,14 +17,23 @@ using namespace mlir::presburger::detail; TEST(GeneratingFunctionTest, sum) { GeneratingFunction gf1(2, {1, -1}, - {makeFracMatrix(2, 3, {{1, 2, 5}, {7, 2, 6}}), makeFracMatrix(2, 3, {{5, 2, 5}, {3, 7, 2}})}, + {makeFracMatrix(2, 3, {{1, 2, 5}, {7, 2, 6}}), + makeFracMatrix(2, 3, {{5, 2, 5}, {3, 7, 2}})}, {{{3, 6}, {7, 2}}, {{2, 8}, {6, 3}}}); GeneratingFunction gf2(2, {1, 1}, - {makeFracMatrix(2, 3, {{6, 2, 1}, {4, 2, 6}}), makeFracMatrix(2, 3, {{3, 2, 6}, {9, 2, 5}})}, + {makeFracMatrix(2, 3, {{6, 2, 1}, {4, 2, 6}}), + makeFracMatrix(2, 3, {{3, 2, 6}, {9, 2, 5}})}, {{{3, 7}, {5, 1}}, {{5, 2}, {6, 2}}}); - + GeneratingFunction sum = gf1 + gf2; - EXPECT_EQ_REPR_GENERATINGFUNCTION(sum, GeneratingFunction(2, {1, -1, 1, 1}, - {makeFracMatrix(2, 3, {{1, 2, 5}, {7, 2, 6}}), makeFracMatrix(2, 3, {{5, 2, 5}, {3, 7, 2}}), makeFracMatrix(2, 3, {{6, 2, 1}, {4, 2, 6}}), makeFracMatrix(2, 3, {{3, 2, 6}, {9, 2, 5}})}, - {{{3, 6}, {7, 2}}, {{2, 8}, {6, 3}}, {{3, 7}, {5, 1}}, {{5, 2}, {6, 2}}})); + EXPECT_EQ_REPR_GENERATINGFUNCTION( + sum, GeneratingFunction(2, {1, -1, 1, 1}, + {makeFracMatrix(2, 3, {{1, 2, 5}, {7, 2, 6}}), + makeFracMatrix(2, 3, {{5, 2, 5}, {3, 7, 2}}), + makeFracMatrix(2, 3, {{6, 2, 1}, {4, 2, 6}}), + makeFracMatrix(2, 3, {{3, 2, 6}, {9, 2, 5}})}, + {{{3, 6}, {7, 2}}, + {{2, 8}, {6, 3}}, + {{3, 7}, {5, 1}}, + {{5, 2}, {6, 2}}})); } \ No newline at end of file diff --git a/mlir/unittests/Analysis/Presburger/Utils.h b/mlir/unittests/Analysis/Presburger/Utils.h index 38c44aec4047f0..6b00898a7e2749 100644 --- a/mlir/unittests/Analysis/Presburger/Utils.h +++ b/mlir/unittests/Analysis/Presburger/Utils.h @@ -75,7 +75,8 @@ inline void EXPECT_EQ_FRAC_MATRIX(FracMatrix a, FracMatrix b) { // Check the coefficients (in order) of two generating functions. // Note that this is not a true equality check. -inline void EXPECT_EQ_REPR_GENERATINGFUNCTION(detail::GeneratingFunction a, detail::GeneratingFunction b) { +inline void EXPECT_EQ_REPR_GENERATINGFUNCTION(detail::GeneratingFunction a, + detail::GeneratingFunction b) { EXPECT_EQ(a.getNumParams(), b.getNumParams()); SmallVector<int> aSigns = a.getSigns(); @@ -106,7 +107,8 @@ inline void EXPECT_EQ_REPR_GENERATINGFUNCTION(detail::GeneratingFunction a, deta // Check the coefficients (in order) of two quasipolynomials. // Note that this is not a true equality check. -inline void EXPECT_EQ_REPR_QUASIPOLYNOMIAL(QuasiPolynomial a, QuasiPolynomial b) { +inline void EXPECT_EQ_REPR_QUASIPOLYNOMIAL(QuasiPolynomial a, + QuasiPolynomial b) { EXPECT_EQ(a.getNumInputs(), b.getNumInputs()); SmallVector<Fraction> aCoeffs = a.getCoefficients(), >From bfda840eaca761f091b42027203d3cacdc6a4e90 Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sat, 6 Jan 2024 16:08:16 +0530 Subject: [PATCH 30/32] Formatting --- mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h index 0ef095dc80e604..4dd692c251563b 100644 --- a/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h +++ b/mlir/include/mlir/Analysis/Presburger/GeneratingFunction.h @@ -84,7 +84,8 @@ class GeneratingFunction { std::vector<std::vector<Point>> sumDenominators = denominators; sumDenominators.insert(sumDenominators.end(), gf.denominators.begin(), gf.denominators.end()); - return GeneratingFunction(numParam, sumSigns, sumNumerators, sumDenominators); + return GeneratingFunction(numParam, sumSigns, sumNumerators, + sumDenominators); } llvm::raw_ostream &print(llvm::raw_ostream &os) const { >From dad5d41652fbfccaf6da6d41981bf0fe7307d69b Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sat, 6 Jan 2024 16:15:08 +0530 Subject: [PATCH 31/32] Newline --- mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp b/mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp index c2701a441efd04..5df1a5a0f64c05 100644 --- a/mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp +++ b/mlir/unittests/Analysis/Presburger/GeneratingFunctionTest.cpp @@ -36,4 +36,4 @@ TEST(GeneratingFunctionTest, sum) { {{2, 8}, {6, 3}}, {{3, 7}, {5, 1}}, {{5, 2}, {6, 2}}})); -} \ No newline at end of file +} >From 5094545a399f8c5741a6788a8fcd4946b027006c Mon Sep 17 00:00:00 2001 From: Abhinav271828 <abhina...@research.iiit.ac.in> Date: Sat, 6 Jan 2024 17:56:30 +0530 Subject: [PATCH 32/32] Initial commit --- .../mlir/Analysis/Presburger/Barvinok.h | 6 ++ mlir/lib/Analysis/Presburger/Barvinok.cpp | 69 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/mlir/include/mlir/Analysis/Presburger/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h index 15e805860db237..93b29e2d718e59 100644 --- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h +++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h @@ -24,6 +24,7 @@ #ifndef MLIR_ANALYSIS_PRESBURGER_BARVINOK_H #define MLIR_ANALYSIS_PRESBURGER_BARVINOK_H +#include "mlir/Analysis/Presburger/GeneratingFunction.h" #include "mlir/Analysis/Presburger/IntegerRelation.h" #include "mlir/Analysis/Presburger/Matrix.h" #include <optional> @@ -77,6 +78,11 @@ ConeV getDual(ConeH cone); /// The returned cone is pointed at the origin. ConeH getDual(ConeV cone); +/// Compute the generating function for a unimodular cone. +/// It assert-fails if the input cone is not unimodular. +GeneratingFunction unimodularConeGeneratingFunction(ParamPoint vertex, int sign, + ConeH cone); + } // namespace detail } // namespace presburger } // namespace mlir diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp index 9152b66968a1f5..31fafbda1129bf 100644 --- a/mlir/lib/Analysis/Presburger/Barvinok.cpp +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "mlir/Analysis/Presburger/Barvinok.h" +#include "mlir/Analysis/Presburger/GeneratingFunction.h" using namespace mlir; using namespace presburger; @@ -63,3 +64,71 @@ MPInt mlir::presburger::detail::getIndex(ConeV cone) { return cone.determinant(); } + +/// Compute the generating function for a unimodular cone. +GeneratingFunction mlir::presburger::detail::unimodularConeGeneratingFunction( + ParamPoint vertex, int sign, ConeH cone) { + // `cone` is assumed to be unimodular. + assert(getIndex(getDual(cone)) == 1 && "input cone is not unimodular!"); + + unsigned numVar = cone.getNumVars(); + unsigned numIneq = cone.getNumInequalities(); + + // Thus its ray matrix, U, is the inverse of the + // transpose of its inequality matrix, `cone`. + FracMatrix transp(numVar, numIneq); + for (unsigned i = 0; i < numVar; i++) + for (unsigned j = 0; j < numIneq; j++) + transp(j, i) = Fraction(cone.atIneq(i, j), 1); + + FracMatrix generators(numVar, numIneq); + transp.determinant(&generators); // This is the U-matrix. + + // The denominators of the generating function + // are given by the generators of the cone, i.e., + // the rows of the matrix U. + std::vector<Point> denominator(numIneq); + ArrayRef<Fraction> row; + for (unsigned i = 0; i < numVar; i++) { + row = generators.getRow(i); + denominator[i] = Point(row); + } + + // The vertex is v : [d, n+1]. + // We need to find affine functions of parameters λi(p) + // such that v = Σ λi(p)*ui. + // The λi are given by the columns of Λ = v^T @ U^{-1} = v^T @ transp. + // Then the numerator will be Σ -floor(-λi(p))*u_i. + // Thus we store the numerator as the affine function -Λ, + // since the generators are already stored in the denominator. + // Note that the outer -1 will have to be accounted for, as it is not stored. + // See end for an example. + + unsigned numColumns = vertex.getNumColumns(); + unsigned numRows = vertex.getNumRows(); + ParamPoint numerator(numColumns, numRows); + SmallVector<Fraction> ithCol(numRows); + for (unsigned i = 0; i < numColumns; i++) { + for (unsigned j = 0; j < numRows; j++) + ithCol[j] = vertex(j, i); + numerator.setRow(i, transp.preMultiplyWithRow(ithCol)); + numerator.negateRow(i); + } + + return GeneratingFunction(numColumns, SmallVector<int>(1, sign), + std::vector({numerator}), + std::vector({denominator})); + + // Suppose the vertex is given by the matrix [ 2 2 0], with 2 params + // [-1 -1/2 1] + // and the cone has H-representation [0 -1] => U-matrix [ 2 -1] + // [-1 -2] [-1 0] + // Therefore Λ will be given by [ 1 0 ] and the negation of this will be + // stored as the numerator. + // [ 1/2 -1 ] + // [ -1 -2 ] + + // Algebraically, the numerator exponent is + // [ -2 ⌊ -N - M/2 +1 ⌋ + 1 ⌊ 0 +M +2 ⌋ ] -> first COLUMN of U is [2, -1] + // [ 1 ⌊ -N - M/2 +1 ⌋ + 0 ⌊ 0 +M +2 ⌋ ] -> second COLUMN of U is [-1, 0] +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits