From d0ce5b952aa30a72d33ed2685a02c4c88fc2d0d5 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Mon, 15 Jul 2024 19:42:27 +0100 Subject: [PATCH] mlir/Presburger: optimize to avoid creating copies (#97897) Summary: Optimize the Presburger library to avoid unnecessarily creating copies. While at it, fix some other minor issues in the codebase. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251672 --- .../Analysis/Presburger/QuasiPolynomial.h | 10 +-- mlir/lib/Analysis/Presburger/Barvinok.cpp | 41 +++++----- .../Analysis/Presburger/IntegerRelation.cpp | 30 ++++---- .../Analysis/Presburger/LinearTransform.cpp | 4 +- mlir/lib/Analysis/Presburger/PWMAFunction.cpp | 6 +- .../Presburger/PresburgerRelation.cpp | 34 +++++---- .../Analysis/Presburger/QuasiPolynomial.cpp | 26 +++---- mlir/lib/Analysis/Presburger/Simplex.cpp | 74 ++++++++++--------- mlir/lib/Analysis/Presburger/Utils.cpp | 9 +-- 9 files changed, 123 insertions(+), 111 deletions(-) diff --git a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h index aeac19e827b44f..5a0962df89d37a 100644 --- a/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h +++ b/mlir/include/mlir/Analysis/Presburger/QuasiPolynomial.h @@ -36,10 +36,10 @@ namespace presburger { // g_{ij} : Q^n -> Q are affine functionals. class QuasiPolynomial : public PresburgerSpace { public: - QuasiPolynomial(unsigned numVars, SmallVector coeffs = {}, - std::vector>> aff = {}); + QuasiPolynomial(unsigned numVars, ArrayRef coeffs = {}, + ArrayRef>> aff = {}); - QuasiPolynomial(unsigned numVars, Fraction constant); + QuasiPolynomial(unsigned numVars, const Fraction &constant); // Find the number of inputs (numDomain) to the polynomial. // numSymbols is set to zero. @@ -57,7 +57,7 @@ class QuasiPolynomial : public PresburgerSpace { QuasiPolynomial operator+(const QuasiPolynomial &x) const; QuasiPolynomial operator-(const QuasiPolynomial &x) const; QuasiPolynomial operator*(const QuasiPolynomial &x) const; - QuasiPolynomial operator/(const Fraction x) const; + QuasiPolynomial operator/(const Fraction &x) const; // Removes terms which evaluate to zero from the expression // and folds affine functions which are constant into the @@ -77,4 +77,4 @@ class QuasiPolynomial : public PresburgerSpace { } // namespace presburger } // namespace mlir -#endif // MLIR_ANALYSIS_PRESBURGER_QUASIPOLYNOMIAL_H \ No newline at end of file +#endif // MLIR_ANALYSIS_PRESBURGER_QUASIPOLYNOMIAL_H diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp index dae840e00ff2e2..fad4364391d569 100644 --- a/mlir/lib/Analysis/Presburger/Barvinok.cpp +++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp @@ -361,7 +361,7 @@ mlir::presburger::detail::computePolytopeGeneratingFunction( continue; // If this subset corresponds to a vertex that has not been considered, // store it. - vertices.push_back(*vertex); + vertices.emplace_back(*vertex); // If a vertex is formed by the intersection of more than d facets, we // assume that any d-subset of these facets can be solved to obtain its @@ -472,10 +472,10 @@ mlir::presburger::detail::computePolytopeGeneratingFunction( Point mlir::presburger::detail::getNonOrthogonalVector( ArrayRef vectors) { unsigned dim = vectors[0].size(); - assert( - llvm::all_of(vectors, - [&](const Point &vector) { return vector.size() == dim; }) && - "all vectors need to be the same size!"); + assert(llvm::all_of( + vectors, + [&dim](const Point &vector) { return vector.size() == dim; }) && + "all vectors need to be the same size!"); SmallVector newPoint = {Fraction(1, 1)}; Fraction maxDisallowedValue = -Fraction(1, 0), @@ -493,7 +493,7 @@ Point mlir::presburger::detail::getNonOrthogonalVector( // Find the biggest such value maxDisallowedValue = std::max(maxDisallowedValue, disallowedValue); } - newPoint.push_back(maxDisallowedValue + 1); + newPoint.emplace_back(maxDisallowedValue + 1); } return newPoint; } @@ -519,19 +519,20 @@ QuasiPolynomial mlir::presburger::detail::getCoefficientInRationalFunction( unsigned numParam = num[0].getNumInputs(); // We use the `isEqual` method of PresburgerSpace, which QuasiPolynomial // inherits from. - assert( - llvm::all_of( - num, [&](const QuasiPolynomial &qp) { return num[0].isEqual(qp); }) && - "the quasipolynomials should all belong to the same space!"); + assert(llvm::all_of(num, + [&num](const QuasiPolynomial &qp) { + return num[0].isEqual(qp); + }) && + "the quasipolynomials should all belong to the same space!"); std::vector coefficients; coefficients.reserve(power + 1); - coefficients.push_back(num[0] / den[0]); + coefficients.emplace_back(num[0] / den[0]); for (unsigned i = 1; i <= power; ++i) { // If the power is not there in the numerator, the coefficient is zero. - coefficients.push_back(i < num.size() ? num[i] - : QuasiPolynomial(numParam, 0)); + coefficients.emplace_back(i < num.size() ? num[i] + : QuasiPolynomial(numParam, 0)); // After den.size(), the coefficients are zero, so we stop // subtracting at that point (if it is less than i). @@ -573,7 +574,7 @@ substituteMuInTerm(unsigned numParams, const ParamPoint &v, SmallVector coefficients; coefficients.reserve(numDims); for (const Point &d : ds) - coefficients.push_back(-dotProduct(mu, d)); + coefficients.emplace_back(-dotProduct(mu, d)); // Then, the affine function is a single floor expression, given by the // corresponding column of v. @@ -581,7 +582,7 @@ substituteMuInTerm(unsigned numParams, const ParamPoint &v, std::vector>> affine; affine.reserve(numDims); for (unsigned j = 0; j < numDims; ++j) - affine.push_back({SmallVector(vTranspose.getRow(j))}); + affine.push_back({SmallVector{vTranspose.getRow(j)}}); QuasiPolynomial num(numParams, coefficients, affine); num = num.simplify(); @@ -593,7 +594,7 @@ substituteMuInTerm(unsigned numParams, const ParamPoint &v, for (const Point &d : ds) { // This term in the denominator is // (1 - t^dens.back()) - dens.push_back(dotProduct(d, mu)); + dens.emplace_back(dotProduct(d, mu)); } return {num, dens}; @@ -641,7 +642,7 @@ std::vector getBinomialCoefficients(const QuasiPolynomial &n, coefficients.emplace_back(numParams, 1); for (unsigned j = 1; j <= r; ++j) // We use the recursive formula for binomial coefficients here and below. - coefficients.push_back( + coefficients.emplace_back( (coefficients[j - 1] * (n - QuasiPolynomial(numParams, j - 1)) / Fraction(j, 1)) .simplify()); @@ -656,7 +657,7 @@ std::vector getBinomialCoefficients(const Fraction &n, coefficients.reserve((int64_t)floor(r)); coefficients.emplace_back(1); for (unsigned j = 1; j <= r; ++j) - coefficients.push_back(coefficients[j - 1] * (n - (j - 1)) / (j)); + coefficients.emplace_back(coefficients[j - 1] * (n - (j - 1)) / (j)); return coefficients; } @@ -764,8 +765,8 @@ mlir::presburger::detail::computeNumTerms(const GeneratingFunction &gf) { eachTermDenCoefficients.reserve(r); for (const Fraction &den : dens) { singleTermDenCoefficients = getBinomialCoefficients(den + 1, den + 1); - eachTermDenCoefficients.push_back( - ArrayRef(singleTermDenCoefficients).slice(1)); + eachTermDenCoefficients.emplace_back( + ArrayRef(singleTermDenCoefficients).drop_front()); } // Now we find the coefficients in Q(s) itself diff --git a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp index 095a7dcb287f3c..bdcb55251b1041 100644 --- a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp +++ b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp @@ -511,10 +511,10 @@ void IntegerRelation::getLowerAndUpperBoundIndices( continue; if (atIneq(r, pos) >= 1) { // Lower bound. - lbIndices->push_back(r); + lbIndices->emplace_back(r); } else if (atIneq(r, pos) <= -1) { // Upper bound. - ubIndices->push_back(r); + ubIndices->emplace_back(r); } } @@ -528,7 +528,7 @@ void IntegerRelation::getLowerAndUpperBoundIndices( continue; if (containsConstraintDependentOnRange(r, /*isEq=*/true)) continue; - eqIndices->push_back(r); + eqIndices->emplace_back(r); } } @@ -791,7 +791,7 @@ IntMatrix IntegerRelation::getBoundedDirections() const { // processes all the inequalities. for (unsigned i = 0, e = getNumInequalities(); i < e; ++i) { if (simplex.isBoundedAlongConstraint(i)) - boundedIneqs.push_back(i); + boundedIneqs.emplace_back(i); } // The direction vector is given by the coefficients and does not include the @@ -1981,13 +1981,13 @@ void IntegerRelation::fourierMotzkinEliminate(unsigned pos, bool darkShadow, for (unsigned r = 0, e = getNumInequalities(); r < e; r++) { if (atIneq(r, pos) == 0) { // Var does not appear in bound. - nbIndices.push_back(r); + nbIndices.emplace_back(r); } else if (atIneq(r, pos) >= 1) { // Lower bound. - lbIndices.push_back(r); + lbIndices.emplace_back(r); } else { // Upper bound. - ubIndices.push_back(r); + ubIndices.emplace_back(r); } } @@ -2028,8 +2028,8 @@ void IntegerRelation::fourierMotzkinEliminate(unsigned pos, bool darkShadow, continue; assert(lbCoeff >= 1 && ubCoeff >= 1 && "bounds wrongly identified"); DynamicAPInt lcm = llvm::lcm(lbCoeff, ubCoeff); - ineq.push_back(atIneq(ubPos, l) * (lcm / ubCoeff) + - atIneq(lbPos, l) * (lcm / lbCoeff)); + ineq.emplace_back(atIneq(ubPos, l) * (lcm / ubCoeff) + + atIneq(lbPos, l) * (lcm / lbCoeff)); assert(lcm > 0 && "lcm should be positive!"); if (lcm != 1) allLCMsAreOne = false; @@ -2057,7 +2057,7 @@ void IntegerRelation::fourierMotzkinEliminate(unsigned pos, bool darkShadow, for (unsigned l = 0, e = getNumCols(); l < e; l++) { if (l == pos) continue; - ineq.push_back(atIneq(nbPos, l)); + ineq.emplace_back(atIneq(nbPos, l)); } newRel.addInequality(ineq); } @@ -2072,7 +2072,7 @@ void IntegerRelation::fourierMotzkinEliminate(unsigned pos, bool darkShadow, for (unsigned l = 0, e = getNumCols(); l < e; l++) { if (l == pos) continue; - eq.push_back(atEq(r, l)); + eq.emplace_back(atEq(r, l)); } newRel.addEquality(eq); } @@ -2264,8 +2264,8 @@ IntegerRelation::unionBoundingBox(const IntegerRelation &otherCst) { std::negate()); std::copy(maxUb.begin(), maxUb.end(), newUb.begin() + getNumDimVars()); - boundingLbs.push_back(newLb); - boundingUbs.push_back(newUb); + boundingLbs.emplace_back(newLb); + boundingUbs.emplace_back(newUb); } // Clear all constraints and add the lower/upper bounds for the bounding box. @@ -2309,7 +2309,7 @@ static void getIndependentConstraints(const IntegerRelation &cst, unsigned pos, break; } if (c == pos + num) - nbIneqIndices.push_back(r); + nbIneqIndices.emplace_back(r); } for (unsigned r = 0, e = cst.getNumEqualities(); r < e; r++) { @@ -2320,7 +2320,7 @@ static void getIndependentConstraints(const IntegerRelation &cst, unsigned pos, break; } if (c == pos + num) - nbEqIndices.push_back(r); + nbEqIndices.emplace_back(r); } } diff --git a/mlir/lib/Analysis/Presburger/LinearTransform.cpp b/mlir/lib/Analysis/Presburger/LinearTransform.cpp index cccbf4c9991d3c..1e389ca69e4e8e 100644 --- a/mlir/lib/Analysis/Presburger/LinearTransform.cpp +++ b/mlir/lib/Analysis/Presburger/LinearTransform.cpp @@ -51,7 +51,7 @@ IntegerRelation LinearTransform::applyTo(const IntegerRelation &rel) const { const DynamicAPInt &c = eq.back(); SmallVector newEq = preMultiplyWithRow(eq.drop_back()); - newEq.push_back(c); + newEq.emplace_back(c); result.addEquality(newEq); } @@ -61,7 +61,7 @@ IntegerRelation LinearTransform::applyTo(const IntegerRelation &rel) const { const DynamicAPInt &c = ineq.back(); SmallVector newIneq = preMultiplyWithRow(ineq.drop_back()); - newIneq.push_back(c); + newIneq.emplace_back(c); result.addInequality(newIneq); } diff --git a/mlir/lib/Analysis/Presburger/PWMAFunction.cpp b/mlir/lib/Analysis/Presburger/PWMAFunction.cpp index f78eb7d2d98ceb..beb9f3e82e22d3 100644 --- a/mlir/lib/Analysis/Presburger/PWMAFunction.cpp +++ b/mlir/lib/Analysis/Presburger/PWMAFunction.cpp @@ -46,7 +46,7 @@ static SmallVector subtractExprs(ArrayRef vecA, SmallVector result; result.reserve(vecA.size()); for (unsigned i = 0, e = vecA.size(); i < e; ++i) - result.push_back(vecA[i] - vecB[i]); + result.emplace_back(vecA[i] - vecB[i]); return result; } @@ -78,7 +78,7 @@ MultiAffineFunction::valueAt(ArrayRef point) const { // function of; we have computed one possible set of values and use them here. pointHomogenous.reserve(pointHomogenous.size() + divValues.size()); for (const std::optional &divVal : divValues) - pointHomogenous.push_back(*divVal); + pointHomogenous.emplace_back(*divVal); // The matrix `output` has an affine expression in the ith row, corresponding // to the expression for the ith value in the output vector. The last column // of the matrix contains the constant term. Let v be the input point with @@ -295,7 +295,7 @@ void PWMAFunction::addPiece(const Piece &piece) { assert(piece.isConsistent() && "Piece should be consistent"); assert(piece.domain.intersect(getDomain()).isIntegerEmpty() && "Piece should be disjoint from the function"); - pieces.push_back(piece); + pieces.emplace_back(piece); } void PWMAFunction::print(raw_ostream &os) const { diff --git a/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp b/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp index e284ca82420bac..239ffe6aaaa764 100644 --- a/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp +++ b/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp @@ -79,7 +79,7 @@ const IntegerRelation &PresburgerRelation::getDisjunct(unsigned index) const { /// IntegerRelation. void PresburgerRelation::unionInPlace(const IntegerRelation &disjunct) { assert(space.isCompatible(disjunct.getSpace()) && "Spaces should match"); - disjuncts.push_back(disjunct); + disjuncts.emplace_back(disjunct); } /// Mutate this set, turning it into the union of this set and the given set. @@ -121,8 +121,8 @@ PresburgerRelation::unionSet(const PresburgerRelation &set) const { /// A point is contained in the union iff any of the parts contain the point. bool PresburgerRelation::containsPoint(ArrayRef point) const { - return llvm::any_of(disjuncts, [&](const IntegerRelation &disjunct) { - return (disjunct.containsPointNoLocal(point)); + return llvm::any_of(disjuncts, [&point](const IntegerRelation &disjunct) { + return disjunct.containsPointNoLocal(point); }); } @@ -376,6 +376,15 @@ static PresburgerRelation getSetDifference(IntegerRelation b, // The index of the last inequality that was processed at this level. // This is empty when we are coming to this level for the first time. std::optional lastIneqProcessed; + + // Convenience constructor. + Frame(unsigned simplexSnapshot, + const IntegerRelation::CountsSnapshot &bCounts, + const IntegerRelation &sI, ArrayRef ineqsToProcess = {}, + std::optional lastIneqProcessed = std::nullopt) + : simplexSnapshot(simplexSnapshot), bCounts(bCounts), sI(sI), + ineqsToProcess(ineqsToProcess), lastIneqProcessed(lastIneqProcessed) { + } }; SmallVector frames; @@ -489,9 +498,7 @@ static PresburgerRelation getSetDifference(IntegerRelation b, // // TODO: consider supporting tail recursion directly if this becomes // relevant for performance. - frames.push_back(Frame{initialSnapshot, initBCounts, sI, - /*ineqsToProcess=*/{}, - /*lastIneqProcessed=*/{}}); + frames.emplace_back(Frame{initialSnapshot, initBCounts, sI}); ++level; continue; } @@ -521,7 +528,7 @@ static PresburgerRelation getSetDifference(IntegerRelation b, ineqsToProcess.reserve(totalNewSimplexInequalities); for (unsigned i = 0; i < totalNewSimplexInequalities; ++i) if (!canIgnoreIneq[i]) - ineqsToProcess.push_back(i); + ineqsToProcess.emplace_back(i); if (ineqsToProcess.empty()) { // Nothing to process; return. (we have no frame to pop.) @@ -531,8 +538,7 @@ static PresburgerRelation getSetDifference(IntegerRelation b, unsigned simplexSnapshot = simplex.getSnapshot(); IntegerRelation::CountsSnapshot bCounts = b.getCounts(); - frames.push_back(Frame{simplexSnapshot, bCounts, sI, ineqsToProcess, - /*lastIneqProcessed=*/std::nullopt}); + frames.emplace_back(Frame{simplexSnapshot, bCounts, sI, ineqsToProcess}); // We have completed the initial setup for this level. // Fallthrough to the main recursive part below. } @@ -796,7 +802,7 @@ SetCoalescer::SetCoalescer(const PresburgerRelation &s) : space(s.getSpace()) { continue; } ++i; - simplices.push_back(simp); + simplices.emplace_back(simp); } } @@ -928,9 +934,9 @@ LogicalResult SetCoalescer::typeInequality(ArrayRef ineq, Simplex &simp) { Simplex::IneqType type = simp.findIneqType(ineq); if (type == Simplex::IneqType::Redundant) - redundantIneqsB.push_back(ineq); + redundantIneqsB.emplace_back(ineq); else if (type == Simplex::IneqType::Cut) - cuttingIneqsB.push_back(ineq); + cuttingIneqsB.emplace_back(ineq); else return failure(); return success(); @@ -940,7 +946,7 @@ LogicalResult SetCoalescer::typeEquality(ArrayRef eq, Simplex &simp) { if (typeInequality(eq, simp).failed()) return failure(); - negEqs.push_back(getNegatedCoeffs(eq)); + negEqs.emplace_back(getNegatedCoeffs(eq)); ArrayRef inv(negEqs.back()); return typeInequality(inv, simp); } @@ -1038,7 +1044,7 @@ PresburgerRelation PresburgerRelation::simplify() const { } bool PresburgerRelation::isFullDim() const { - return llvm::any_of(getAllDisjuncts(), [&](IntegerRelation disjunct) { + return llvm::any_of(getAllDisjuncts(), [](IntegerRelation disjunct) { return disjunct.isFullDim(); }); } diff --git a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp index 85cb56e8a11366..940a28f0ca0068 100644 --- a/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp +++ b/mlir/lib/Analysis/Presburger/QuasiPolynomial.cpp @@ -14,8 +14,8 @@ using namespace mlir; using namespace presburger; QuasiPolynomial::QuasiPolynomial( - unsigned numVars, SmallVector coeffs, - std::vector>> aff) + unsigned numVars, ArrayRef coeffs, + ArrayRef>> aff) : PresburgerSpace(/*numDomain=*/numVars, /*numRange=*/1, /*numSymbols=*/0, /*numLocals=*/0), coefficients(coeffs), affine(aff) { @@ -36,7 +36,7 @@ QuasiPolynomial::QuasiPolynomial( } /// Define a quasipolynomial which is a single constant. -QuasiPolynomial::QuasiPolynomial(unsigned numVars, Fraction constant) +QuasiPolynomial::QuasiPolynomial(unsigned numVars, const Fraction &constant) : PresburgerSpace(/*numDomain=*/numVars, /*numRange=*/1, /*numSymbols=*/0, /*numLocals=*/0), coefficients({constant}), affine({{}}) {} @@ -71,7 +71,7 @@ QuasiPolynomial QuasiPolynomial::operator*(const QuasiPolynomial &x) const { coeffs.reserve(coefficients.size() * x.coefficients.size()); for (const Fraction &coeff : coefficients) for (const Fraction &xcoeff : x.coefficients) - coeffs.push_back(coeff * xcoeff); + coeffs.emplace_back(coeff * xcoeff); std::vector> product; std::vector>> aff; @@ -81,14 +81,14 @@ QuasiPolynomial QuasiPolynomial::operator*(const QuasiPolynomial &x) const { product.clear(); product.insert(product.end(), term.begin(), term.end()); product.insert(product.end(), xterm.begin(), xterm.end()); - aff.push_back(product); + aff.emplace_back(product); } } return QuasiPolynomial(getNumInputs(), coeffs, aff); } -QuasiPolynomial QuasiPolynomial::operator/(const Fraction x) const { +QuasiPolynomial QuasiPolynomial::operator/(const Fraction &x) const { assert(x != 0 && "division by zero!"); QuasiPolynomial qp(*this); for (Fraction &coeff : qp.coefficients) @@ -130,15 +130,15 @@ QuasiPolynomial QuasiPolynomial::simplify() { newCoeff = coefficients[i]; for (ArrayRef term : affine[i]) { bool allCoeffsZero = llvm::all_of( - term.slice(0, numParam), [](const Fraction c) { return c == 0; }); + term.slice(0, numParam), [](const Fraction &c) { return c == 0; }); if (allCoeffsZero) newCoeff *= term[numParam]; else - newAffineTerm.push_back(SmallVector(term)); + newAffineTerm.emplace_back(term); } - newCoeffs.push_back(newCoeff); - newAffine.push_back(newAffineTerm); + newCoeffs.emplace_back(newCoeff); + newAffine.emplace_back(newAffineTerm); } return QuasiPolynomial(getNumInputs(), newCoeffs, newAffine); } @@ -157,8 +157,8 @@ QuasiPolynomial QuasiPolynomial::collectTerms() { } if (alreadyPresent) continue; - newCoeffs.push_back(coefficients[i]); - newAffine.push_back(affine[i]); + newCoeffs.emplace_back(coefficients[i]); + newAffine.emplace_back(affine[i]); } return QuasiPolynomial(getNumInputs(), newCoeffs, newAffine); @@ -167,7 +167,7 @@ QuasiPolynomial QuasiPolynomial::collectTerms() { Fraction QuasiPolynomial::getConstantTerm() { Fraction constTerm = 0; for (unsigned i = 0, e = coefficients.size(); i < e; ++i) - if (affine[i].size() == 0) + if (affine[i].empty()) constTerm += coefficients[i]; return constTerm; } diff --git a/mlir/lib/Analysis/Presburger/Simplex.cpp b/mlir/lib/Analysis/Presburger/Simplex.cpp index bebbf0325f430c..7c8a019557132a 100644 --- a/mlir/lib/Analysis/Presburger/Simplex.cpp +++ b/mlir/lib/Analysis/Presburger/Simplex.cpp @@ -12,6 +12,7 @@ #include "mlir/Analysis/Presburger/Matrix.h" #include "mlir/Analysis/Presburger/PresburgerSpace.h" #include "mlir/Analysis/Presburger/Utils.h" +#include "llvm/ADT/DynamicAPInt.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallVector.h" @@ -42,18 +43,20 @@ scaleAndAddForAssert(ArrayRef a, const DynamicAPInt &scale, SmallVector res; res.reserve(a.size()); for (unsigned i = 0, e = a.size(); i < e; ++i) - res.push_back(a[i] + scale * b[i]); + res.emplace_back(a[i] + scale * b[i]); return res; } SimplexBase::SimplexBase(unsigned nVar, bool mustUseBigM) : usingBigM(mustUseBigM), nRedundant(0), nSymbol(0), tableau(0, getNumFixedCols() + nVar), empty(false) { + var.reserve(nVar); + colUnknown.reserve(nVar + 1); colUnknown.insert(colUnknown.begin(), getNumFixedCols(), nullIndex); for (unsigned i = 0; i < nVar; ++i) { var.emplace_back(Orientation::Column, /*restricted=*/false, /*pos=*/getNumFixedCols() + i); - colUnknown.push_back(i); + colUnknown.emplace_back(i); } } @@ -105,9 +108,9 @@ unsigned SimplexBase::addZeroRow(bool makeRestricted) { // Resize the tableau to accommodate the extra row. unsigned newRow = tableau.appendExtraRow(); assert(getNumRows() == getNumRows() && "Inconsistent tableau size"); - rowUnknown.push_back(~con.size()); + rowUnknown.emplace_back(~con.size()); con.emplace_back(Orientation::Row, makeRestricted, newRow); - undoLog.push_back(UndoLogEntry::RemoveLastConstraint); + undoLog.emplace_back(UndoLogEntry::RemoveLastConstraint); tableau(newRow, 0) = 1; return newRow; } @@ -346,8 +349,8 @@ SymbolicLexSimplex::getSymbolicSampleNumerator(unsigned row) const { SmallVector sample; sample.reserve(nSymbol + 1); for (unsigned col = 3; col < 3 + nSymbol; ++col) - sample.push_back(tableau(row, col)); - sample.push_back(tableau(row, 1)); + sample.emplace_back(tableau(row, col)); + sample.emplace_back(tableau(row, 1)); return sample; } @@ -426,8 +429,8 @@ LogicalResult SymbolicLexSimplex::addSymbolicCut(unsigned row) { divCoeffs.reserve(nSymbol + 1); DynamicAPInt divDenom = d; for (unsigned col = 3; col < 3 + nSymbol; ++col) - divCoeffs.push_back(mod(-tableau(row, col), divDenom)); // (-a_i%d)s_i - divCoeffs.push_back(mod(-tableau(row, 1), divDenom)); // -c%d. + divCoeffs.emplace_back(mod(-tableau(row, col), divDenom)); // (-a_i%d)s_i + divCoeffs.emplace_back(mod(-tableau(row, 1), divDenom)); // -c%d. normalizeDiv(divCoeffs, divDenom); domainSimplex.addDivisionVariable(divCoeffs, divDenom); @@ -619,8 +622,8 @@ SymbolicLexOpt SymbolicLexSimplex::computeSymbolicIntegerLexMin() { // reallocated. int splitIndex = rowUnknown[splitRow]; unsigned snapshot = getSnapshot(); - stack.push_back( - {splitIndex, snapshot, domainSnapshot, domainPolyCounts}); + stack.emplace_back( + StackFrame{splitIndex, snapshot, domainSnapshot, domainPolyCounts}); ++level; continue; } @@ -1093,7 +1096,7 @@ void SimplexBase::markEmpty() { // non-empty when rolling back past this point. if (empty) return; - undoLog.push_back(UndoLogEntry::UnmarkEmpty); + undoLog.emplace_back(UndoLogEntry::UnmarkEmpty); empty = true; } @@ -1120,6 +1123,7 @@ void Simplex::addInequality(ArrayRef coeffs) { void SimplexBase::addEquality(ArrayRef coeffs) { addInequality(coeffs); SmallVector negatedCoeffs; + negatedCoeffs.reserve(coeffs.size()); for (const DynamicAPInt &coeff : coeffs) negatedCoeffs.emplace_back(-coeff); addInequality(negatedCoeffs); @@ -1134,11 +1138,12 @@ unsigned SimplexBase::getSnapshot() const { return undoLog.size(); } unsigned SimplexBase::getSnapshotBasis() { SmallVector basis; + basis.reserve(colUnknown.size()); for (int index : colUnknown) { if (index != nullIndex) - basis.push_back(index); + basis.emplace_back(index); } - savedBases.push_back(std::move(basis)); + savedBases.emplace_back(std::move(basis)); undoLog.emplace_back(UndoLogEntry::RestoreBasis); return undoLog.size() - 1; @@ -1304,7 +1309,7 @@ void SimplexBase::addDivisionVariable(ArrayRef coeffs, SmallVector ineq(coeffs.begin(), coeffs.end()); DynamicAPInt constTerm = ineq.back(); ineq.back() = -denom; - ineq.push_back(constTerm); + ineq.emplace_back(constTerm); addInequality(ineq); for (DynamicAPInt &coeff : ineq) @@ -1321,7 +1326,7 @@ void SimplexBase::appendVariable(unsigned count) { for (unsigned i = 0; i < count; ++i) { var.emplace_back(Orientation::Column, /*restricted=*/false, /*pos=*/getNumColumns() + i); - colUnknown.push_back(var.size() - 1); + colUnknown.emplace_back(var.size() - 1); } tableau.resizeHorizontally(getNumColumns() + count); undoLog.insert(undoLog.end(), count, UndoLogEntry::RemoveLastVariable); @@ -1516,12 +1521,12 @@ Simplex Simplex::makeProduct(const Simplex &a, const Simplex &b) { result.colUnknown.assign(2, nullIndex); for (unsigned i = 2, e = a.getNumColumns(); i < e; ++i) { - result.colUnknown.push_back(a.colUnknown[i]); + result.colUnknown.emplace_back(a.colUnknown[i]); result.unknownFromIndex(result.colUnknown.back()).pos = result.colUnknown.size() - 1; } for (unsigned i = 2, e = b.getNumColumns(); i < e; ++i) { - result.colUnknown.push_back(indexFromBIndex(b.colUnknown[i])); + result.colUnknown.emplace_back(indexFromBIndex(b.colUnknown[i])); result.unknownFromIndex(result.colUnknown.back()).pos = result.colUnknown.size() - 1; } @@ -1530,7 +1535,7 @@ Simplex Simplex::makeProduct(const Simplex &a, const Simplex &b) { unsigned resultRow = result.tableau.appendExtraRow(); for (unsigned col = 0, e = a.getNumColumns(); col < e; ++col) result.tableau(resultRow, col) = a.tableau(row, col); - result.rowUnknown.push_back(a.rowUnknown[row]); + result.rowUnknown.emplace_back(a.rowUnknown[row]); result.unknownFromIndex(result.rowUnknown.back()).pos = result.rowUnknown.size() - 1; }; @@ -1545,7 +1550,7 @@ Simplex Simplex::makeProduct(const Simplex &a, const Simplex &b) { unsigned offset = a.getNumColumns() - 2; for (unsigned col = 2, e = b.getNumColumns(); col < e; ++col) result.tableau(resultRow, offset + col) = b.tableau(row, col); - result.rowUnknown.push_back(indexFromBIndex(b.rowUnknown[row])); + result.rowUnknown.emplace_back(indexFromBIndex(b.rowUnknown[row])); result.unknownFromIndex(result.rowUnknown.back()).pos = result.rowUnknown.size() - 1; }; @@ -1632,7 +1637,7 @@ Simplex::getSamplePointIfIntegral() const { // If the sample is non-integral, return std::nullopt. if (coord.num % coord.den != 0) return {}; - integerSample.push_back(coord.num / coord.den); + integerSample.emplace_back(coord.num / coord.den); } return integerSample; } @@ -1661,7 +1666,7 @@ class presburger::GBRSimplex { void addEqualityForDirection(ArrayRef dir) { assert(llvm::any_of(dir, [](const DynamicAPInt &x) { return x != 0; }) && "Direction passed is the zero vector!"); - snapshotStack.push_back(simplex.getSnapshot()); + snapshotStack.emplace_back(simplex.getSnapshot()); simplex.addEquality(getCoeffsForDirection(dir)); } /// Compute max(dotProduct(dir, x - y)). @@ -1691,6 +1696,7 @@ class presburger::GBRSimplex { assert(maybeWidth.isBounded() && "Width should be bounded!"); dualDenom = simplex.tableau(row, 0); dual.clear(); + dual.reserve((conIndex - simplexConstraintOffset) / 2); // The increment is i += 2 because equalities are added as two inequalities, // one positive and one negative. Each iteration processes one equality. @@ -1715,14 +1721,14 @@ class presburger::GBRSimplex { // Note that it is NOT valid to perform pivots during the computation of // the duals. This entire dual computation must be performed on the same // tableau configuration. - assert(!(simplex.con[i].orientation == Orientation::Column && - simplex.con[i + 1].orientation == Orientation::Column) && + assert((simplex.con[i].orientation != Orientation::Column || + simplex.con[i + 1].orientation != Orientation::Column) && "Both inequalities for the equality cannot be in column " "orientation!"); if (simplex.con[i].orientation == Orientation::Column) - dual.push_back(-simplex.tableau(row, simplex.con[i].pos)); + dual.emplace_back(-simplex.tableau(row, simplex.con[i].pos)); else if (simplex.con[i + 1].orientation == Orientation::Column) - dual.push_back(simplex.tableau(row, simplex.con[i + 1].pos)); + dual.emplace_back(simplex.tableau(row, simplex.con[i + 1].pos)); else dual.emplace_back(0); } @@ -1749,9 +1755,9 @@ class presburger::GBRSimplex { assert(2 * dir.size() == simplex.getNumVariables() && "Direction vector has wrong dimensionality"); SmallVector coeffs(dir.begin(), dir.end()); - coeffs.reserve(2 * dir.size()); + coeffs.reserve(dir.size() + 1); for (const DynamicAPInt &coeff : dir) - coeffs.push_back(-coeff); + coeffs.emplace_back(-coeff); coeffs.emplace_back(0); // constant term return coeffs; } @@ -1921,7 +1927,7 @@ void Simplex::reduceBasis(IntMatrix &basis, unsigned level) { // because this case should only occur when i is level, and there are no // duals in that case anyway. assert(i == level && "This case should only occur when i == level"); - width.push_back( + width.emplace_back( gbrSimplex.computeWidthAndDuals(basis.getRow(i), dual, dualDenom)); } @@ -1930,8 +1936,8 @@ void Simplex::reduceBasis(IntMatrix &basis, unsigned level) { "We don't know dual_i but we know width_{i+1}"); // We don't know dual for our level, so let's find it. gbrSimplex.addEqualityForDirection(basis.getRow(i)); - width.push_back(gbrSimplex.computeWidthAndDuals(basis.getRow(i + 1), dual, - dualDenom)); + width.emplace_back(gbrSimplex.computeWidthAndDuals(basis.getRow(i + 1), + dual, dualDenom)); gbrSimplex.removeLastEquality(); } @@ -2056,12 +2062,12 @@ std::optional> Simplex::findIntegerSample() { computeIntegerBounds(basisCoeffs); } - snapshotStack.push_back(getSnapshot()); + snapshotStack.emplace_back(getSnapshot()); // The smallest value in the range is the next value to try. // The values in the optionals are guaranteed to exist since we know the // polytope is bounded. - nextValueStack.push_back(*minRoundedUp); - upperBoundStack.push_back(*maxRoundedDown); + nextValueStack.emplace_back(*minRoundedUp); + upperBoundStack.emplace_back(*maxRoundedDown); } assert((snapshotStack.size() - 1 == level && @@ -2088,7 +2094,7 @@ std::optional> Simplex::findIntegerSample() { // Try the next value in the range and "recurse" into the next level. SmallVector basisCoeffs(basis.getRow(level).begin(), basis.getRow(level).end()); - basisCoeffs.push_back(-nextValue); + basisCoeffs.emplace_back(-nextValue); addEquality(basisCoeffs); level++; } diff --git a/mlir/lib/Analysis/Presburger/Utils.cpp b/mlir/lib/Analysis/Presburger/Utils.cpp index 383888c3b5660e..e74aae70796802 100644 --- a/mlir/lib/Analysis/Presburger/Utils.cpp +++ b/mlir/lib/Analysis/Presburger/Utils.cpp @@ -33,7 +33,7 @@ using llvm::dynamicAPIntFromInt64; static void normalizeDivisionByGCD(MutableArrayRef dividend, DynamicAPInt &divisor) { assert(divisor > 0 && "divisor must be non-negative!"); - if (divisor == 0 || dividend.empty()) + if (dividend.empty()) return; // We take the absolute value of dividend's coefficients to make sure that // `gcd` is positive. @@ -556,8 +556,7 @@ std::vector presburger::multiplyPolynomials(ArrayRef a, auto getCoeff = [](ArrayRef arr, unsigned i) -> Fraction { if (i < arr.size()) return arr[i]; - else - return 0; + return 0; }; std::vector convolution; @@ -566,11 +565,11 @@ std::vector presburger::multiplyPolynomials(ArrayRef a, Fraction sum(0, 1); for (unsigned l = 0; l <= k; ++l) sum += getCoeff(a, l) * getCoeff(b, k - l); - convolution.push_back(sum); + convolution.emplace_back(sum); } return convolution; } bool presburger::isRangeZero(ArrayRef arr) { - return llvm::all_of(arr, [&](Fraction f) { return f == 0; }); + return llvm::all_of(arr, [](const Fraction &f) { return f == 0; }); }