diff options
author | Arjun P <arjunpitchanathan@gmail.com> | 2022-04-10 21:09:13 +0100 |
---|---|---|
committer | Arjun P <arjunpitchanathan@gmail.com> | 2022-04-11 20:46:30 +0100 |
commit | aafb428237b4ee41f7cb1de0211a0fbdb74e1f1c (patch) | |
tree | 17be0c73331d0d1185b73194d36a89a567c02351 | |
parent | 1cff723ff527030295d84d3bb52d4d0b7cddb43a (diff) | |
download | llvm-aafb428237b4ee41f7cb1de0211a0fbdb74e1f1c.zip llvm-aafb428237b4ee41f7cb1de0211a0fbdb74e1f1c.tar.gz llvm-aafb428237b4ee41f7cb1de0211a0fbdb74e1f1c.tar.bz2 |
[MLIR][Presburger][Simplex] symbolic lexmin: add some normalization heuristics
Normalize some of the division and inequality expressions used,
which can improve performance. Also deduplicate some of the
normalization functionality throughout the Presburger library.
Reviewed By: Groverkss
Differential Revision: https://reviews.llvm.org/D123314
-rw-r--r-- | mlir/include/mlir/Analysis/Presburger/Matrix.h | 4 | ||||
-rw-r--r-- | mlir/include/mlir/Analysis/Presburger/Simplex.h | 8 | ||||
-rw-r--r-- | mlir/include/mlir/Analysis/Presburger/Utils.h | 11 | ||||
-rw-r--r-- | mlir/lib/Analysis/Presburger/IntegerRelation.cpp | 2 | ||||
-rw-r--r-- | mlir/lib/Analysis/Presburger/Matrix.cpp | 18 | ||||
-rw-r--r-- | mlir/lib/Analysis/Presburger/Simplex.cpp | 53 | ||||
-rw-r--r-- | mlir/lib/Analysis/Presburger/Utils.cpp | 26 |
7 files changed, 71 insertions, 51 deletions
diff --git a/mlir/include/mlir/Analysis/Presburger/Matrix.h b/mlir/include/mlir/Analysis/Presburger/Matrix.h index e2ad543..4940195 100644 --- a/mlir/include/mlir/Analysis/Presburger/Matrix.h +++ b/mlir/include/mlir/Analysis/Presburger/Matrix.h @@ -124,10 +124,10 @@ public: /// Divide the first `nCols` of the specified row by their GCD. /// Returns the GCD of the first `nCols` of the specified row. - uint64_t normalizeRow(unsigned row, unsigned nCols); + int64_t normalizeRow(unsigned row, unsigned nCols); /// Divide the columns of the specified row by their GCD. /// Returns the GCD of the columns of the specified row. - uint64_t normalizeRow(unsigned row); + int64_t normalizeRow(unsigned row); /// The given vector is interpreted as a row vector v. Post-multiply v with /// this matrix, say M, and return vM. diff --git a/mlir/include/mlir/Analysis/Presburger/Simplex.h b/mlir/include/mlir/Analysis/Presburger/Simplex.h index 67a4b5f..876095c 100644 --- a/mlir/include/mlir/Analysis/Presburger/Simplex.h +++ b/mlir/include/mlir/Analysis/Presburger/Simplex.h @@ -290,10 +290,6 @@ protected: /// Returns the index of the new Unknown in con. unsigned addRow(ArrayRef<int64_t> coeffs, bool makeRestricted = false); - /// Normalize the given row by removing common factors between the numerator - /// and the denominator. - void normalizeRow(unsigned row); - /// Swap the two rows/columns in the tableau and associated data structures. void swapRows(unsigned i, unsigned j); void swapColumns(unsigned i, unsigned j); @@ -629,6 +625,10 @@ private: /// The last element is the constant term. This ignores the big M coefficient. SmallVector<int64_t, 8> getSymbolicSampleNumerator(unsigned row) const; + /// Get an affine inequality in the symbols with integer coefficients that + /// holds iff the symbolic sample of the specified row is non-negative. + SmallVector<int64_t, 8> getSymbolicSampleIneq(unsigned row) const; + /// Return whether all the coefficients of the symbolic sample are integers. /// /// This does not consult the domain to check if the specified expression diff --git a/mlir/include/mlir/Analysis/Presburger/Utils.h b/mlir/include/mlir/Analysis/Presburger/Utils.h index 06298f6..732f093 100644 --- a/mlir/include/mlir/Analysis/Presburger/Utils.h +++ b/mlir/include/mlir/Analysis/Presburger/Utils.h @@ -130,6 +130,17 @@ void removeDuplicateDivs( SmallVectorImpl<unsigned> &denoms, unsigned localOffset, llvm::function_ref<bool(unsigned i, unsigned j)> merge); +/// Compute the gcd of the range. +int64_t gcdRange(ArrayRef<int64_t> range); + +/// Divide the range by its gcd and return the gcd. +int64_t normalizeRange(MutableArrayRef<int64_t> range); + +/// Normalize the given (numerator, denominator) pair by dividing out the +/// common factors between them. The numerator here is an affine expression +/// with integer coefficients. +void normalizeDiv(MutableArrayRef<int64_t> num, int64_t &denom); + /// Return `coeffs` with all the elements negated. SmallVector<int64_t, 8> getNegatedCoeffs(ArrayRef<int64_t> coeffs); diff --git a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp index 9c8035a..c7a18be 100644 --- a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp +++ b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp @@ -882,7 +882,7 @@ void IntegerRelation::gcdTightenInequalities() { unsigned numCols = getNumCols(); for (unsigned i = 0, e = getNumInequalities(); i < e; ++i) { // Normalize the constraint and tighten the constant term by the GCD. - uint64_t gcd = inequalities.normalizeRow(i, getNumCols() - 1); + int64_t gcd = inequalities.normalizeRow(i, getNumCols() - 1); if (gcd > 1) atIneq(i, numCols - 1) = mlir::floorDiv(atIneq(i, numCols - 1), gcd); } diff --git a/mlir/lib/Analysis/Presburger/Matrix.cpp b/mlir/lib/Analysis/Presburger/Matrix.cpp index 680e450..7686cff 100644 --- a/mlir/lib/Analysis/Presburger/Matrix.cpp +++ b/mlir/lib/Analysis/Presburger/Matrix.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "mlir/Analysis/Presburger/Matrix.h" +#include "mlir/Analysis/Presburger/Utils.h" #include "llvm/Support/MathExtras.h" using namespace mlir; @@ -234,22 +235,11 @@ void Matrix::negateRow(unsigned row) { at(row, column) = -at(row, column); } -uint64_t Matrix::normalizeRow(unsigned row, unsigned cols) { - if (cols == 0) - return 0; - - int64_t gcd = std::abs(at(row, 0)); - for (unsigned j = 1, e = cols; j < e; ++j) - gcd = llvm::GreatestCommonDivisor64(gcd, std::abs(at(row, j))); - - if (gcd > 1) - for (unsigned j = 0, e = cols; j < e; ++j) - at(row, j) /= gcd; - - return gcd; +int64_t Matrix::normalizeRow(unsigned row, unsigned cols) { + return normalizeRange(getRow(row).slice(0, cols)); } -uint64_t Matrix::normalizeRow(unsigned row) { +int64_t Matrix::normalizeRow(unsigned row) { return normalizeRow(row, getNumColumns()); } diff --git a/mlir/lib/Analysis/Presburger/Simplex.cpp b/mlir/lib/Analysis/Presburger/Simplex.cpp index 7a65730..5e679e68 100644 --- a/mlir/lib/Analysis/Presburger/Simplex.cpp +++ b/mlir/lib/Analysis/Presburger/Simplex.cpp @@ -156,29 +156,11 @@ unsigned SimplexBase::addRow(ArrayRef<int64_t> coeffs, bool makeRestricted) { nRowCoeff * tableau(nRow - 1, col) + idxRowCoeff * tableau(pos, col); } - normalizeRow(nRow - 1); + tableau.normalizeRow(nRow - 1); // Push to undo log along with the index of the new constraint. return con.size() - 1; } -/// Normalize the row by removing factors that are common between the -/// denominator and all the numerator coefficients. -void SimplexBase::normalizeRow(unsigned row) { - int64_t gcd = 0; - for (unsigned col = 0; col < nCol; ++col) { - gcd = llvm::greatestCommonDivisor(gcd, std::abs(tableau(row, col))); - // If the gcd becomes 1 then the row is already normalized. - if (gcd == 1) - return; - } - - // Note that the gcd can never become zero since the first element of the row, - // the denominator, is non-zero. - assert(gcd != 0); - for (unsigned col = 0; col < nCol; ++col) - tableau(row, col) /= gcd; -} - namespace { bool signMatchesDirection(int64_t elem, Direction direction) { assert(elem != 0 && "elem should not be 0"); @@ -349,6 +331,14 @@ SymbolicLexSimplex::getSymbolicSampleNumerator(unsigned row) const { return sample; } +SmallVector<int64_t, 8> +SymbolicLexSimplex::getSymbolicSampleIneq(unsigned row) const { + SmallVector<int64_t, 8> sample = getSymbolicSampleNumerator(row); + // The inequality is equivalent to the GCD-normalized one. + normalizeRange(sample); + return sample; +} + void LexSimplexBase::appendSymbol() { appendVariable(); swapColumns(3 + nSymbol, nCol - 1); @@ -404,14 +394,16 @@ LogicalResult SymbolicLexSimplex::addSymbolicCut(unsigned row) { // Add the division variable `q` described above to the symbol domain. // q = ((-c%d) + sum_i (-a_i%d)s_i)/d. - SmallVector<int64_t, 8> domainDivCoeffs; - domainDivCoeffs.reserve(nSymbol + 1); + SmallVector<int64_t, 8> divCoeffs; + divCoeffs.reserve(nSymbol + 1); + int64_t divDenom = d; for (unsigned col = 3; col < 3 + nSymbol; ++col) - domainDivCoeffs.push_back(mod(-tableau(row, col), d)); // (-a_i%d)s_i - domainDivCoeffs.push_back(mod(-tableau(row, 1), d)); // -c%d. + divCoeffs.push_back(mod(-tableau(row, col), divDenom)); // (-a_i%d)s_i + divCoeffs.push_back(mod(-tableau(row, 1), divDenom)); // -c%d. - domainSimplex.addDivisionVariable(domainDivCoeffs, d); - domainPoly.addLocalFloorDiv(domainDivCoeffs, d); + normalizeDiv(divCoeffs, divDenom); + domainSimplex.addDivisionVariable(divCoeffs, divDenom); + domainPoly.addLocalFloorDiv(divCoeffs, divDenom); // Update `this` to account for the additional symbol we just added. appendSymbol(); @@ -476,7 +468,7 @@ Optional<unsigned> SymbolicLexSimplex::maybeGetAlwaysViolatedRow() { for (unsigned row = 0; row < nRow; ++row) { if (tableau(row, 2) > 0) continue; - if (domainSimplex.isSeparateInequality(getSymbolicSampleNumerator(row))) { + if (domainSimplex.isSeparateInequality(getSymbolicSampleIneq(row))) { // Sample numerator always takes negative values in the symbol domain. return row; } @@ -552,7 +544,7 @@ SymbolicLexMin SymbolicLexSimplex::computeSymbolicIntegerLexMin() { assert(tableau(splitRow, 2) == 0 && "Non-branching pivots should have been handled already!"); - symbolicSample = getSymbolicSampleNumerator(splitRow); + symbolicSample = getSymbolicSampleIneq(splitRow); if (domainSimplex.isRedundantInequality(symbolicSample)) continue; @@ -630,7 +622,8 @@ SymbolicLexMin SymbolicLexSimplex::computeSymbolicIntegerLexMin() { assert(u.orientation == Orientation::Row && "The split row should have been returned to row orientation!"); SmallVector<int64_t, 8> splitIneq = - getComplementIneq(getSymbolicSampleNumerator(u.pos)); + getComplementIneq(getSymbolicSampleIneq(u.pos)); + normalizeRange(splitIneq); if (moveRowUnknownToColumn(u.pos).failed()) { // The unknown can't be made non-negative; return. --level; @@ -935,7 +928,7 @@ void SimplexBase::pivot(unsigned pivotRow, unsigned pivotCol) { tableau(pivotRow, col) = -tableau(pivotRow, col); } } - normalizeRow(pivotRow); + tableau.normalizeRow(pivotRow); for (unsigned row = 0; row < nRow; ++row) { if (row == pivotRow) @@ -951,7 +944,7 @@ void SimplexBase::pivot(unsigned pivotRow, unsigned pivotCol) { tableau(row, pivotCol) * tableau(pivotRow, j); } tableau(row, pivotCol) *= tableau(pivotRow, pivotCol); - normalizeRow(row); + tableau.normalizeRow(row); } } diff --git a/mlir/lib/Analysis/Presburger/Utils.cpp b/mlir/lib/Analysis/Presburger/Utils.cpp index 4cd7670..77230fc 100644 --- a/mlir/lib/Analysis/Presburger/Utils.cpp +++ b/mlir/lib/Analysis/Presburger/Utils.cpp @@ -304,6 +304,32 @@ void presburger::removeDuplicateDivs( } } +int64_t presburger::gcdRange(ArrayRef<int64_t> range) { + int64_t gcd = 0; + for (int64_t elem : range) { + gcd = llvm::GreatestCommonDivisor64(gcd, std::abs(elem)); + if (gcd == 1) + return gcd; + } + return gcd; +} + +int64_t presburger::normalizeRange(MutableArrayRef<int64_t> range) { + int64_t gcd = gcdRange(range); + if (gcd == 0 || gcd == 1) + return gcd; + for (int64_t &elem : range) + elem /= gcd; + return gcd; +} + +void presburger::normalizeDiv(MutableArrayRef<int64_t> num, int64_t &denom) { + int64_t gcd = llvm::greatestCommonDivisor(gcdRange(num), denom); + for (int64_t &coeff : num) + coeff /= gcd; + denom /= gcd; +} + SmallVector<int64_t, 8> presburger::getNegatedCoeffs(ArrayRef<int64_t> coeffs) { SmallVector<int64_t, 8> negatedCoeffs; negatedCoeffs.reserve(coeffs.size()); |