Skip to content

Commit aafb428

Browse files
committed
[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
1 parent 1cff723 commit aafb428

File tree

7 files changed

+71
-51
lines changed

7 files changed

+71
-51
lines changed

mlir/include/mlir/Analysis/Presburger/Matrix.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,10 @@ class Matrix {
124124

125125
/// Divide the first `nCols` of the specified row by their GCD.
126126
/// Returns the GCD of the first `nCols` of the specified row.
127-
uint64_t normalizeRow(unsigned row, unsigned nCols);
127+
int64_t normalizeRow(unsigned row, unsigned nCols);
128128
/// Divide the columns of the specified row by their GCD.
129129
/// Returns the GCD of the columns of the specified row.
130-
uint64_t normalizeRow(unsigned row);
130+
int64_t normalizeRow(unsigned row);
131131

132132
/// The given vector is interpreted as a row vector v. Post-multiply v with
133133
/// this matrix, say M, and return vM.

mlir/include/mlir/Analysis/Presburger/Simplex.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,10 +290,6 @@ class SimplexBase {
290290
/// Returns the index of the new Unknown in con.
291291
unsigned addRow(ArrayRef<int64_t> coeffs, bool makeRestricted = false);
292292

293-
/// Normalize the given row by removing common factors between the numerator
294-
/// and the denominator.
295-
void normalizeRow(unsigned row);
296-
297293
/// Swap the two rows/columns in the tableau and associated data structures.
298294
void swapRows(unsigned i, unsigned j);
299295
void swapColumns(unsigned i, unsigned j);
@@ -629,6 +625,10 @@ class SymbolicLexSimplex : public LexSimplexBase {
629625
/// The last element is the constant term. This ignores the big M coefficient.
630626
SmallVector<int64_t, 8> getSymbolicSampleNumerator(unsigned row) const;
631627

628+
/// Get an affine inequality in the symbols with integer coefficients that
629+
/// holds iff the symbolic sample of the specified row is non-negative.
630+
SmallVector<int64_t, 8> getSymbolicSampleIneq(unsigned row) const;
631+
632632
/// Return whether all the coefficients of the symbolic sample are integers.
633633
///
634634
/// This does not consult the domain to check if the specified expression

mlir/include/mlir/Analysis/Presburger/Utils.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ void removeDuplicateDivs(
130130
SmallVectorImpl<unsigned> &denoms, unsigned localOffset,
131131
llvm::function_ref<bool(unsigned i, unsigned j)> merge);
132132

133+
/// Compute the gcd of the range.
134+
int64_t gcdRange(ArrayRef<int64_t> range);
135+
136+
/// Divide the range by its gcd and return the gcd.
137+
int64_t normalizeRange(MutableArrayRef<int64_t> range);
138+
139+
/// Normalize the given (numerator, denominator) pair by dividing out the
140+
/// common factors between them. The numerator here is an affine expression
141+
/// with integer coefficients.
142+
void normalizeDiv(MutableArrayRef<int64_t> num, int64_t &denom);
143+
133144
/// Return `coeffs` with all the elements negated.
134145
SmallVector<int64_t, 8> getNegatedCoeffs(ArrayRef<int64_t> coeffs);
135146

mlir/lib/Analysis/Presburger/IntegerRelation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ void IntegerRelation::gcdTightenInequalities() {
882882
unsigned numCols = getNumCols();
883883
for (unsigned i = 0, e = getNumInequalities(); i < e; ++i) {
884884
// Normalize the constraint and tighten the constant term by the GCD.
885-
uint64_t gcd = inequalities.normalizeRow(i, getNumCols() - 1);
885+
int64_t gcd = inequalities.normalizeRow(i, getNumCols() - 1);
886886
if (gcd > 1)
887887
atIneq(i, numCols - 1) = mlir::floorDiv(atIneq(i, numCols - 1), gcd);
888888
}

mlir/lib/Analysis/Presburger/Matrix.cpp

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "mlir/Analysis/Presburger/Matrix.h"
10+
#include "mlir/Analysis/Presburger/Utils.h"
1011
#include "llvm/Support/MathExtras.h"
1112

1213
using namespace mlir;
@@ -234,22 +235,11 @@ void Matrix::negateRow(unsigned row) {
234235
at(row, column) = -at(row, column);
235236
}
236237

237-
uint64_t Matrix::normalizeRow(unsigned row, unsigned cols) {
238-
if (cols == 0)
239-
return 0;
240-
241-
int64_t gcd = std::abs(at(row, 0));
242-
for (unsigned j = 1, e = cols; j < e; ++j)
243-
gcd = llvm::GreatestCommonDivisor64(gcd, std::abs(at(row, j)));
244-
245-
if (gcd > 1)
246-
for (unsigned j = 0, e = cols; j < e; ++j)
247-
at(row, j) /= gcd;
248-
249-
return gcd;
238+
int64_t Matrix::normalizeRow(unsigned row, unsigned cols) {
239+
return normalizeRange(getRow(row).slice(0, cols));
250240
}
251241

252-
uint64_t Matrix::normalizeRow(unsigned row) {
242+
int64_t Matrix::normalizeRow(unsigned row) {
253243
return normalizeRow(row, getNumColumns());
254244
}
255245

mlir/lib/Analysis/Presburger/Simplex.cpp

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -156,29 +156,11 @@ unsigned SimplexBase::addRow(ArrayRef<int64_t> coeffs, bool makeRestricted) {
156156
nRowCoeff * tableau(nRow - 1, col) + idxRowCoeff * tableau(pos, col);
157157
}
158158

159-
normalizeRow(nRow - 1);
159+
tableau.normalizeRow(nRow - 1);
160160
// Push to undo log along with the index of the new constraint.
161161
return con.size() - 1;
162162
}
163163

164-
/// Normalize the row by removing factors that are common between the
165-
/// denominator and all the numerator coefficients.
166-
void SimplexBase::normalizeRow(unsigned row) {
167-
int64_t gcd = 0;
168-
for (unsigned col = 0; col < nCol; ++col) {
169-
gcd = llvm::greatestCommonDivisor(gcd, std::abs(tableau(row, col)));
170-
// If the gcd becomes 1 then the row is already normalized.
171-
if (gcd == 1)
172-
return;
173-
}
174-
175-
// Note that the gcd can never become zero since the first element of the row,
176-
// the denominator, is non-zero.
177-
assert(gcd != 0);
178-
for (unsigned col = 0; col < nCol; ++col)
179-
tableau(row, col) /= gcd;
180-
}
181-
182164
namespace {
183165
bool signMatchesDirection(int64_t elem, Direction direction) {
184166
assert(elem != 0 && "elem should not be 0");
@@ -349,6 +331,14 @@ SymbolicLexSimplex::getSymbolicSampleNumerator(unsigned row) const {
349331
return sample;
350332
}
351333

334+
SmallVector<int64_t, 8>
335+
SymbolicLexSimplex::getSymbolicSampleIneq(unsigned row) const {
336+
SmallVector<int64_t, 8> sample = getSymbolicSampleNumerator(row);
337+
// The inequality is equivalent to the GCD-normalized one.
338+
normalizeRange(sample);
339+
return sample;
340+
}
341+
352342
void LexSimplexBase::appendSymbol() {
353343
appendVariable();
354344
swapColumns(3 + nSymbol, nCol - 1);
@@ -404,14 +394,16 @@ LogicalResult SymbolicLexSimplex::addSymbolicCut(unsigned row) {
404394

405395
// Add the division variable `q` described above to the symbol domain.
406396
// q = ((-c%d) + sum_i (-a_i%d)s_i)/d.
407-
SmallVector<int64_t, 8> domainDivCoeffs;
408-
domainDivCoeffs.reserve(nSymbol + 1);
397+
SmallVector<int64_t, 8> divCoeffs;
398+
divCoeffs.reserve(nSymbol + 1);
399+
int64_t divDenom = d;
409400
for (unsigned col = 3; col < 3 + nSymbol; ++col)
410-
domainDivCoeffs.push_back(mod(-tableau(row, col), d)); // (-a_i%d)s_i
411-
domainDivCoeffs.push_back(mod(-tableau(row, 1), d)); // -c%d.
401+
divCoeffs.push_back(mod(-tableau(row, col), divDenom)); // (-a_i%d)s_i
402+
divCoeffs.push_back(mod(-tableau(row, 1), divDenom)); // -c%d.
412403

413-
domainSimplex.addDivisionVariable(domainDivCoeffs, d);
414-
domainPoly.addLocalFloorDiv(domainDivCoeffs, d);
404+
normalizeDiv(divCoeffs, divDenom);
405+
domainSimplex.addDivisionVariable(divCoeffs, divDenom);
406+
domainPoly.addLocalFloorDiv(divCoeffs, divDenom);
415407

416408
// Update `this` to account for the additional symbol we just added.
417409
appendSymbol();
@@ -476,7 +468,7 @@ Optional<unsigned> SymbolicLexSimplex::maybeGetAlwaysViolatedRow() {
476468
for (unsigned row = 0; row < nRow; ++row) {
477469
if (tableau(row, 2) > 0)
478470
continue;
479-
if (domainSimplex.isSeparateInequality(getSymbolicSampleNumerator(row))) {
471+
if (domainSimplex.isSeparateInequality(getSymbolicSampleIneq(row))) {
480472
// Sample numerator always takes negative values in the symbol domain.
481473
return row;
482474
}
@@ -552,7 +544,7 @@ SymbolicLexMin SymbolicLexSimplex::computeSymbolicIntegerLexMin() {
552544
assert(tableau(splitRow, 2) == 0 &&
553545
"Non-branching pivots should have been handled already!");
554546

555-
symbolicSample = getSymbolicSampleNumerator(splitRow);
547+
symbolicSample = getSymbolicSampleIneq(splitRow);
556548
if (domainSimplex.isRedundantInequality(symbolicSample))
557549
continue;
558550

@@ -630,7 +622,8 @@ SymbolicLexMin SymbolicLexSimplex::computeSymbolicIntegerLexMin() {
630622
assert(u.orientation == Orientation::Row &&
631623
"The split row should have been returned to row orientation!");
632624
SmallVector<int64_t, 8> splitIneq =
633-
getComplementIneq(getSymbolicSampleNumerator(u.pos));
625+
getComplementIneq(getSymbolicSampleIneq(u.pos));
626+
normalizeRange(splitIneq);
634627
if (moveRowUnknownToColumn(u.pos).failed()) {
635628
// The unknown can't be made non-negative; return.
636629
--level;
@@ -935,7 +928,7 @@ void SimplexBase::pivot(unsigned pivotRow, unsigned pivotCol) {
935928
tableau(pivotRow, col) = -tableau(pivotRow, col);
936929
}
937930
}
938-
normalizeRow(pivotRow);
931+
tableau.normalizeRow(pivotRow);
939932

940933
for (unsigned row = 0; row < nRow; ++row) {
941934
if (row == pivotRow)
@@ -951,7 +944,7 @@ void SimplexBase::pivot(unsigned pivotRow, unsigned pivotCol) {
951944
tableau(row, pivotCol) * tableau(pivotRow, j);
952945
}
953946
tableau(row, pivotCol) *= tableau(pivotRow, pivotCol);
954-
normalizeRow(row);
947+
tableau.normalizeRow(row);
955948
}
956949
}
957950

mlir/lib/Analysis/Presburger/Utils.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,32 @@ void presburger::removeDuplicateDivs(
304304
}
305305
}
306306

307+
int64_t presburger::gcdRange(ArrayRef<int64_t> range) {
308+
int64_t gcd = 0;
309+
for (int64_t elem : range) {
310+
gcd = llvm::GreatestCommonDivisor64(gcd, std::abs(elem));
311+
if (gcd == 1)
312+
return gcd;
313+
}
314+
return gcd;
315+
}
316+
317+
int64_t presburger::normalizeRange(MutableArrayRef<int64_t> range) {
318+
int64_t gcd = gcdRange(range);
319+
if (gcd == 0 || gcd == 1)
320+
return gcd;
321+
for (int64_t &elem : range)
322+
elem /= gcd;
323+
return gcd;
324+
}
325+
326+
void presburger::normalizeDiv(MutableArrayRef<int64_t> num, int64_t &denom) {
327+
int64_t gcd = llvm::greatestCommonDivisor(gcdRange(num), denom);
328+
for (int64_t &coeff : num)
329+
coeff /= gcd;
330+
denom /= gcd;
331+
}
332+
307333
SmallVector<int64_t, 8> presburger::getNegatedCoeffs(ArrayRef<int64_t> coeffs) {
308334
SmallVector<int64_t, 8> negatedCoeffs;
309335
negatedCoeffs.reserve(coeffs.size());

0 commit comments

Comments
 (0)