19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/SmallPtrSet.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/raw_ostream.h"
26 #define DEBUG_TYPE "flat-value-constraints"
29 using namespace presburger;
49 AffineExprFlattener(
unsigned nDims,
unsigned nSymbols)
81 struct SemiAffineExprFlattener :
public AffineExprFlattener {
82 using AffineExprFlattener::AffineExprFlattener;
89 assert(succeeded(result) &&
90 "unexpected failure in SimpleAffineExprFlattener");
111 bSubR.insert(bSubR.begin() + rPos, -1);
140 bool addConservativeSemiAffineBounds =
false) {
147 auto flattenExprs = [&](AffineExprFlattener &flattener) -> LogicalResult {
150 for (
auto expr : exprs) {
151 auto flattenResult = flattener.walkPostOrder(expr);
152 if (failed(flattenResult))
156 assert(flattener.operandExprStack.size() == exprs.size());
157 flattenedExprs->clear();
158 flattenedExprs->assign(flattener.operandExprStack.begin(),
159 flattener.operandExprStack.end());
167 if (addConservativeSemiAffineBounds) {
168 SemiAffineExprFlattener flattener(numDims, numSymbols);
169 return flattenExprs(flattener);
172 AffineExprFlattener flattener(numDims, numSymbols);
173 return flattenExprs(flattener);
179 AffineExpr expr,
unsigned numDims,
unsigned numSymbols,
181 bool addConservativeSemiAffineBounds) {
182 std::vector<SmallVector<int64_t, 8>> flattenedExprs;
185 localVarCst, addConservativeSemiAffineBounds);
186 *flattenedExpr = flattenedExprs[0];
203 localVarCst, addConservativeSemiAffineBounds);
228 assert(other.
getNumDims() == getNumDimVars() &&
"dim mismatch");
229 assert(other.
getNumSymbols() == getNumSymbolVars() &&
"symbol mismatch");
231 std::vector<SmallVector<int64_t, 8>> flatExprs;
232 if (failed(flattenAlignedMapAndMergeLocals(other, &flatExprs)))
245 for (
unsigned r = 0, e = flatExprs.size(); r < e; r++) {
246 const auto &flatExpr = flatExprs[r];
254 for (
unsigned i = 0, f = other.
getNumInputs(); i < f; i++) {
256 eqToAdd[e + i] = -flatExpr[i];
259 unsigned j = getNumDimVars() + getNumSymbolVars();
260 unsigned end = flatExpr.size() - 1;
262 eqToAdd[
j] = -flatExpr[i];
266 eqToAdd[getNumCols() - 1] = -flatExpr[flatExpr.size() - 1];
269 addEquality(eqToAdd);
303 unsigned offset,
unsigned num, int64_t lbConst,
306 assert(pos < cst.
getNumVars() &&
"invalid position");
310 if (lbConst != 0 || ubConst < 1)
312 int64_t divisor = ubConst + 1;
316 curEquality < numEqualities; curEquality++) {
317 int64_t coefficientAtPos = cst.
atEq64(curEquality, pos);
320 if (coefficientAtPos == 0)
336 unsigned quotientCount = 0;
337 int quotientPosition = -1;
338 int quotientSign = 1;
346 int64_t coefficientOfCurVar = cst.
atEq64(curEquality, curVar);
348 if (coefficientOfCurVar == 0)
351 if (coefficientOfCurVar % (divisor * coefficientAtPos) == 0) {
353 quotientPosition = curVar;
354 quotientSign = (coefficientOfCurVar * coefficientAtPos) > 0 ? 1 : -1;
361 dividendExpr = dividendExpr + memo[curVar] * coefficientOfCurVar;
369 if (coefficientAtPos > 0)
370 dividendExpr = (-dividendExpr).floorDiv(coefficientAtPos);
372 dividendExpr = dividendExpr.floorDiv(-coefficientAtPos);
381 auto dimExpr = dyn_cast<AffineDimExpr>(dividendExpr);
386 if (quotientCount >= 1) {
391 unsigned dimExprPos = dimExpr.getPosition();
392 unsigned dimExprCol = dimExprPos < offset ? dimExprPos : dimExprPos + num;
396 if (ub && *ub < divisor)
399 memo[pos] = dimExpr % divisor;
402 if (quotientCount == 1 && !memo[quotientPosition])
403 memo[quotientPosition] = dimExpr.floorDiv(divisor) * quotientSign;
421 assert(pos < cst.
getNumVars() &&
"invalid position");
425 for (
unsigned i = 0, e = cst.
getNumVars(); i < e; ++i)
439 for (
unsigned c = 0, f = cst.
getNumVars(); c < f; c++)
440 if (dividend[c] != 0)
441 dividendExpr = dividendExpr + dividend[c] * exprs[c];
444 exprs[pos] = dividendExpr.floorDiv(divisor);
449 bool fixedColWidth)
const {
450 unsigned ncols = getNumCols();
451 bool firstNonZero =
true;
452 for (
unsigned j = 0;
j < ncols;
j++) {
453 if (
j == ncols - 1) {
455 if (row[
j] == 0 && !firstNonZero) {
457 llvm::errs().indent(7);
459 llvm::errs() << ((row[
j] >= 0) ?
"+ " :
"") << row[
j] <<
' ';
462 std::string var = std::string(
"c_") + std::to_string(
j);
464 llvm::errs() <<
"+ " << var <<
' ';
465 else if (row[
j] == -1)
466 llvm::errs() <<
"- " << var <<
' ';
467 else if (row[
j] >= 2)
468 llvm::errs() <<
"+ " << row[
j] <<
'*' << var <<
' ';
469 else if (row[
j] <= -2)
470 llvm::errs() <<
"- " << -row[
j] <<
'*' << var <<
' ';
471 else if (fixedColWidth)
473 llvm::errs().indent(7);
475 firstNonZero =
false;
481 assert(hasConsistentState());
482 llvm::errs() <<
"Constraints (" << getNumDimVars() <<
" dims, "
483 << getNumSymbolVars() <<
" symbols, " << getNumLocalVars()
484 <<
" locals), (" << getNumConstraints() <<
" constraints)\n";
485 auto dumpConstraint = [&](
unsigned rowPos,
bool isEq) {
488 isEq ? getEquality64(rowPos) : getInequality64(rowPos);
490 llvm::errs() << (isEq ?
"=" :
">=") <<
" 0\n";
493 for (
unsigned i = 0, e = getNumInequalities(); i < e; i++)
494 dumpConstraint(i,
false);
495 for (
unsigned i = 0, e = getNumEqualities(); i < e; i++)
496 dumpConstraint(i,
true);
497 llvm::errs() <<
'\n';
501 unsigned pos,
unsigned offset,
unsigned num,
unsigned symStartPos,
503 bool closedUB)
const {
504 assert(pos + offset < getNumDimVars() &&
"invalid dim start pos");
505 assert(symStartPos >= (pos + offset) &&
"invalid sym start pos");
506 assert(getNumLocalVars() == localExprs.size() &&
507 "incorrect local exprs count");
510 getLowerAndUpperBoundIndices(pos + offset, &lbIndices, &ubIndices, &eqIndices,
516 for (
unsigned i = 0, e = a.size(); i < e; ++i) {
517 if (i < offset || i >= offset + num)
524 unsigned dimCount = symStartPos - num;
525 unsigned symCount = getNumDimAndSymbolVars() - symStartPos;
526 lbExprs.reserve(lbIndices.size() + eqIndices.size());
528 for (
auto idx : lbIndices) {
529 auto ineq = getInequality64(idx);
534 std::transform(lb.begin(), lb.end(), lb.begin(), std::negate<int64_t>());
538 int64_t divisor =
std::abs(ineq[pos + offset]);
539 expr = (expr + divisor - 1).floorDiv(divisor);
540 lbExprs.push_back(expr);
544 ubExprs.reserve(ubIndices.size() + eqIndices.size());
546 for (
auto idx : ubIndices) {
547 auto ineq = getInequality64(idx);
552 expr = expr.floorDiv(
std::abs(ineq[pos + offset]));
553 int64_t ubAdjustment = closedUB ? 0 : 1;
554 ubExprs.push_back(expr + ubAdjustment);
559 for (
auto idx : eqIndices) {
560 auto eq = getEquality64(idx);
562 if (eq[pos + offset] > 0)
563 std::transform(b.begin(), b.end(), b.begin(), std::negate<int64_t>());
568 expr = expr.floorDiv(
std::abs(eq[pos + offset]));
570 ubExprs.push_back(expr + 1);
574 expr = expr.ceilDiv(
std::abs(eq[pos + offset]));
575 lbExprs.push_back(expr);
578 auto lbMap =
AffineMap::get(dimCount, symCount, lbExprs, context);
579 auto ubMap =
AffineMap::get(dimCount, symCount, ubExprs, context);
581 return {lbMap, ubMap};
600 int64_t c = cst.
atEq64(idx,
j);
606 expr = expr + exprs[
j] * c;
615 int64_t vPos = cst.
atEq64(idx, pos);
616 assert(vPos != 0 &&
"expected non-zero here");
618 expr = (-expr).floorDiv(vPos);
621 expr = expr.floorDiv(-vPos);
638 else if (i >= offset + num)
650 for (
unsigned pos = 0, f = cst.
getNumVars(); pos < f; pos++) {
656 if (lbConst.has_value() && ubConst.has_value()) {
658 if (*lbConst == *ubConst) {
666 if (
detectAsMod(cst, pos, offset, num, *lbConst, *ubConst, context,
681 std::optional<unsigned> idx;
706 assert(offset + num <= getNumDimVars() &&
"invalid range");
709 normalizeConstraintsByGCD();
711 LLVM_DEBUG(llvm::dbgs() <<
"getSliceBounds for variables at positions ["
712 << offset <<
", " << offset + num <<
")\n");
713 LLVM_DEBUG(dumpPretty());
719 int64_t ubAdjustment = closedUB ? 0 : 1;
724 std::optional<FlatLinearConstraints> tmpClone;
725 for (
unsigned pos = 0; pos < num; pos++) {
726 unsigned numMapDims = getNumDimVars() - num;
727 unsigned numMapSymbols = getNumSymbolVars();
737 ubMap =
AffineMap::get(numMapDims, numMapSymbols, expr + ubAdjustment);
742 if (getNumLocalVars() == 0) {
748 tmpClone->removeRedundantInequalities();
750 std::tie(lbMap, ubMap) = tmpClone->getLowerAndUpperBound(
751 pos, offset, num, getNumDimVars(), {}, context,
761 LLVM_DEBUG(llvm::dbgs()
762 <<
"WARNING: Potentially over-approximating slice lb\n");
763 auto lbConst = getConstantBound64(
BoundType::LB, pos + offset);
764 if (lbConst.has_value()) {
770 LLVM_DEBUG(llvm::dbgs()
771 <<
"WARNING: Potentially over-approximating slice ub\n");
772 auto ubConst = getConstantBound64(
BoundType::UB, pos + offset);
773 if (ubConst.has_value()) {
775 numMapDims, numMapSymbols,
781 LLVM_DEBUG(llvm::dbgs() <<
"Slice bounds:\n");
782 LLVM_DEBUG(llvm::dbgs() <<
"lb map for pos = " << Twine(pos + offset)
783 <<
", expr: " << lbMap <<
'\n');
784 LLVM_DEBUG(llvm::dbgs() <<
"ub map for pos = " << Twine(pos + offset)
785 <<
", expr: " << ubMap <<
'\n');
791 bool addConservativeSemiAffineBounds) {
794 addConservativeSemiAffineBounds))) {
795 LLVM_DEBUG(llvm::dbgs()
796 <<
"composition unimplemented for semi-affine maps\n");
802 unsigned numLocalVars = getNumLocalVars();
818 assert(boundMap.
getNumDims() == getNumDimVars() &&
"dim mismatch");
819 assert(boundMap.
getNumSymbols() == getNumSymbolVars() &&
"symbol mismatch");
820 assert(pos < getNumDimAndSymbolVars() &&
"invalid position");
822 "EQ bound must be closed.");
827 "single result expected");
830 std::vector<SmallVector<int64_t, 8>> flatExprs;
831 if (failed(flattenAlignedMapAndMergeLocals(
832 boundMap, &flatExprs,
833 addSemiAffineBounds == AddConservativeSemiAffineBounds::Yes)))
838 for (
const auto &flatExpr : flatExprs) {
842 ineq[
j] = lower ? -flatExpr[
j] : flatExpr[
j];
849 ineq[pos] = lower ? 1 : -1;
851 unsigned j = getNumDimVars() + getNumSymbolVars();
852 unsigned end = flatExpr.size() - 1;
853 for (
unsigned i = boundMap.
getNumInputs(); i < end; i++,
j++) {
854 ineq[
j] = lower ? -flatExpr[i] : flatExpr[i];
858 int64_t boundAdjustment = (isClosedBound || type ==
BoundType::EQ) ? 0 : -1;
860 ineq[getNumCols() - 1] = (lower ? -flatExpr[flatExpr.size() - 1]
861 : flatExpr[flatExpr.size() - 1]) +
863 type ==
BoundType::EQ ? addEquality(ineq) : addInequality(ineq);
872 return addBound(type, pos, boundMap,
882 unsigned numDims = getNumDimVars();
883 unsigned numSyms = getNumSymbolVars();
886 for (
unsigned i = 0; i < numDims; i++)
888 for (
unsigned i = numDims, e = numDims + numSyms; i < e; i++)
897 for (
unsigned i = 0, e = getNumLocalVars(); i < e; ++i)
898 if (!memo[numDims + numSyms + i] &&
906 llvm::all_of(localExprs, [](
AffineExpr expr) {
return expr; }));
917 unsigned idx,
bool isEquality) {
936 expr = expr + exprs[
j] * c;
950 unsigned *minLbPos,
unsigned *minUbPos)
const {
952 assert(pos < getNumDimVars() &&
"Invalid identifier position");
956 for (
int i = getNumDimAndSymbolVars(), e = cst.size() - 1; i < e; ++i) {
957 if (whiteListCols[i] && whiteListCols[i].isSymbolicOrConstant())
967 (void)computeLocalVars(memo, context);
971 int eqPos = findEqualityToConstant(pos,
true);
974 if (eqPos != -1 && freeOfUnknownLocalVars(getEquality64(eqPos), memo)) {
976 if (lb &&
detectAsExpr(*
this, pos, eqPos, context, memo)) {
994 getLowerAndUpperBoundIndices(pos, &lbIndices, &ubIndices,
998 std::optional<int64_t> minDiff = std::nullopt;
999 unsigned minLbPosition = 0, minUbPosition = 0;
1004 for (
unsigned ubPos : ubIndices) {
1006 std::optional<AffineExpr> maybeUbExpr =
1007 getAsExpr(*
this, pos, context, memo, ubPos,
false);
1008 if (!maybeUbExpr.has_value() || !(*maybeUbExpr).isSymbolicOrConstant())
1023 assert(-atIneq64(ubPos, pos) > 0 &&
"invalid upper bound index");
1026 for (
unsigned lbPos : lbIndices) {
1029 std::optional<AffineExpr> maybeLbExpr =
1030 getAsExpr(*
this, pos, context, memo, lbPos,
false);
1031 if (!maybeLbExpr.has_value() || !(*maybeLbExpr).isSymbolicOrConstant())
1045 int64_t divisor = atIneq64(lbPos, pos);
1050 AffineExpr lbExpr = (-(*maybeLbExpr) + divisor - 1).floorDiv(divisor);
1051 assert(atIneq64(lbPos, pos) > 0 &&
"invalid lower bound index");
1057 auto constantDiff = dyn_cast<AffineConstantExpr>(difference);
1061 int64_t diffValue = constantDiff.getValue();
1063 diffValue = std::max<int64_t>(diffValue, 0);
1064 if (!minDiff || diffValue < *minDiff) {
1065 minDiff = diffValue;
1066 minLbPosition = lbPos;
1067 minUbPosition = ubPos;
1075 if (lb && minDiff) {
1081 *minLbPos = minLbPosition;
1083 *minUbPos = minUbPosition;
1089 if (getNumConstraints() == 0)
1098 if (failed(computeLocalVars(memo, context))) {
1102 unsigned numDimsSymbols = getNumDimAndSymbolVars();
1103 for (
unsigned i = numDimsSymbols, e = getNumVars(); i < e; ++i) {
1104 if (!memo[i] && !isColZero(i))
1105 noLocalRepVars.push_back(i - numDimsSymbols);
1107 if (!noLocalRepVars.empty()) {
1109 llvm::dbgs() <<
"local variables at position(s) ";
1110 llvm::interleaveComma(noLocalRepVars, llvm::dbgs());
1111 llvm::dbgs() <<
" do not have an explicit representation in:\n";
1122 unsigned numDims = getNumDimVars();
1123 unsigned numSyms = getNumSymbolVars();
1126 std::fill(eqFlags.begin(), eqFlags.begin() + getNumEqualities(),
true);
1127 std::fill(eqFlags.begin() + getNumEqualities(), eqFlags.end(),
false);
1130 exprs.reserve(getNumConstraints());
1132 for (
unsigned i = 0, e = getNumEqualities(); i < e; ++i)
1134 numSyms, localExprs, context));
1135 for (
unsigned i = 0, e = getNumInequalities(); i < e; ++i)
1137 numSyms, localExprs, context));
1149 set.getNumDims() + set.getNumSymbols() + 1,
1150 set.getNumDims(), set.getNumSymbols(),
1152 assert((operands.empty() || set.
getNumInputs() == operands.size()) &&
1153 "operand count mismatch");
1155 for (
unsigned i = 0, e = operands.size(); i < e; ++i)
1159 std::vector<SmallVector<int64_t, 8>> flatExprs;
1162 assert(
false &&
"flattening unimplemented for semi-affine integer sets");
1169 for (
unsigned i = 0, e = flatExprs.size(); i < e; ++i) {
1170 const auto &flatExpr = flatExprs[i];
1184 return insertVar(VarKind::SetDim, pos, vals);
1189 return insertVar(VarKind::Symbol, pos, vals);
1194 return insertVar(VarKind::SetDim, pos, vals);
1199 return insertVar(VarKind::Symbol, pos, vals);
1204 unsigned absolutePos = IntegerPolyhedron::insertVar(
kind, pos, num);
1211 assert(!vals.empty() &&
"expected ValueRange with Values.");
1212 assert(
kind != VarKind::Local &&
1213 "values cannot be attached to local variables.");
1214 unsigned num = vals.size();
1215 unsigned absolutePos = IntegerPolyhedron::insertVar(
kind, pos, num);
1218 for (
unsigned i = 0, e = vals.size(); i < e; ++i)
1220 setValue(absolutePos + i, vals[i]);
1235 return std::equal(aMaybeValues.begin(), aMaybeValues.end(),
1236 bMaybeValues.begin(), bMaybeValues.end());
1252 "Start position out of bounds");
1261 maybeValuesAll.data() + end};
1263 for (std::optional<Value> val : maybeValues)
1264 if (val && !uniqueVars.insert(*val).second)
1271 static bool LLVM_ATTRIBUTE_UNUSED
1278 static bool LLVM_ATTRIBUTE_UNUSED
1281 if (
kind == VarKind::SetDim)
1283 if (
kind == VarKind::Symbol)
1286 llvm_unreachable(
"Unexpected VarKind");
1303 assert(offset <= a->getNumDimVars() && offset <= b->getNumDimVars());
1305 assert(llvm::all_of(
1307 [](
const std::optional<Value> &var) { return var.has_value(); }));
1309 assert(llvm::all_of(
1311 [](
const std::optional<Value> &var) { return var.has_value(); }));
1318 unsigned d = offset;
1319 for (
Value aDimValue : aDimValues) {
1324 if (b->
findVar(aDimValue, &loc, d)) {
1325 assert(loc >= offset &&
"A's dim appears in B's aligned range");
1326 assert(loc < b->getNumDimVars() &&
1327 "A's dim appears in B's non-dim position");
1339 "expected same number of dims");
1368 for (
Value aSymValue : aSymValues) {
1388 "expected same number of symbols");
1392 unsigned varLimit) {
1393 IntegerPolyhedron::removeVarRange(
kind, varStart, varLimit);
1399 assert(map.
getNumInputs() == operands.size() &&
"number of inputs mismatch");
1411 for (
unsigned i = 0, e =
getNumVarKind(VarKind::SetDim); i < e; ++i) {
1415 for (
unsigned i = 0, e =
getNumVarKind(VarKind::Symbol); i < e; ++i) {
1423 assert(syms.size() == newSymsPtr->size() &&
"unexpected new/missing symbols");
1424 assert(std::equal(syms.begin(), syms.end(), newSymsPtr->begin()) &&
1425 "unexpected new/missing symbols");
1430 unsigned offset)
const {
1432 for (
unsigned i = offset, e = maybeValues.size(); i < e; ++i)
1433 if (maybeValues[i] && maybeValues[i].value() == val) {
1450 assert(0 &&
"var not found");
1484 bool ret =
findVar(val, &pos);
1496 assert(std::equal(maybeValues.begin(), maybeValues.begin() +
getNumDimVars(),
1497 otherMaybeValues.begin(),
1499 "dim values mismatch");
1500 assert(otherCst.
getNumLocalVars() == 0 &&
"local vars not supported here");
1501 assert(
getNumLocalVars() == 0 &&
"local vars not supported yet here");
1507 return IntegerPolyhedron::unionBoundingBox(otherCopy);
1510 return IntegerPolyhedron::unionBoundingBox(otherCst);
1521 "expected same number of operands and map inputs");
1525 unsigned numSymbols = syms.size();
1529 newSyms->append(syms.begin(), syms.end());
1535 auto dimIt = llvm::find(dims, operand.value());
1536 auto symIt = llvm::find(syms, operand.value());
1537 if (dimIt != dims.end()) {
1540 }
else if (symIt != syms.end()) {
1548 newSyms->push_back(operand.value());
1552 dimReplacements[operand.index()] = replacement;
1554 symReplacements[operand.index() - map.
getNumDims()] = replacement;
1559 dims.size(), numSymbols);
1566 std::vector<SmallVector<int64_t, 8>> flattenedExprs;
1569 if (result.failed())
1574 "AffineMap cannot produce divs without local representation");
1579 for (
unsigned i = 0, e = flattenedExprs.size(); i < e; ++i)
1580 for (
unsigned j = 0, f = flattenedExprs[i].size();
j < f; ++
j)
1581 mat(i,
j) = flattenedExprs[i][
j];
static bool detectAsFloorDiv(const FlatLinearConstraints &cst, unsigned pos, MLIRContext *context, SmallVectorImpl< AffineExpr > &exprs)
Check if the pos^th variable can be expressed as a floordiv of an affine function of other variables ...
static bool detectAsMod(const FlatLinearConstraints &cst, unsigned pos, unsigned offset, unsigned num, int64_t lbConst, int64_t ubConst, MLIRContext *context, SmallVectorImpl< AffineExpr > &memo)
static bool LLVM_ATTRIBUTE_UNUSED areVarsUnique(const FlatLinearValueConstraints &cst, unsigned start, unsigned end)
Checks if the SSA values associated with cst's variables in range [start, end) are unique.
static void computeUnknownVars(const FlatLinearConstraints &cst, MLIRContext *context, unsigned offset, unsigned num, SmallVectorImpl< AffineExpr > &memo)
Compute a representation of num identifiers starting at offset in cst as affine expressions involving...
static LogicalResult getFlattenedAffineExprs(ArrayRef< AffineExpr > exprs, unsigned numDims, unsigned numSymbols, std::vector< SmallVector< int64_t, 8 >> *flattenedExprs, FlatLinearConstraints *localVarCst, bool addConservativeSemiAffineBounds=false)
static bool areVarsAligned(const FlatLinearValueConstraints &a, const FlatLinearValueConstraints &b)
Checks if two constraint systems are in the same space, i.e., if they are associated with the same se...
static bool detectAsExpr(const FlatLinearConstraints &cst, unsigned pos, unsigned idx, MLIRContext *context, SmallVectorImpl< AffineExpr > &exprs)
Express the pos^th identifier of cst as an affine expression in terms of other identifiers,...
static void mergeAndAlignVars(unsigned offset, FlatLinearValueConstraints *a, FlatLinearValueConstraints *b)
Merge and align the variables of A and B starting at 'offset', so that both constraint systems get th...
static std::optional< AffineExpr > getAsExpr(const FlatLinearConstraints &cst, unsigned pos, MLIRContext *context, ArrayRef< AffineExpr > exprs, unsigned idx, bool isEquality)
Given an equality or inequality (isEquality used to disambiguate) of cst at idx, traverse and sum up ...
union mlir::linalg::@1183::ArityGroupAndKind::Kind kind
Base type for affine expression.
AffineExpr floorDiv(uint64_t v) const
AffineExprKind getKind() const
Return the classification for this type.
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
MLIRContext * getContext() const
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
unsigned getNumSymbols() const
unsigned getNumDims() const
ArrayRef< AffineExpr > getResults() const
unsigned getNumResults() const
AffineMap replaceDimsAndSymbols(ArrayRef< AffineExpr > dimReplacements, ArrayRef< AffineExpr > symReplacements, unsigned numResultDims, unsigned numResultSyms) const
This method substitutes any uses of dimensions and symbols (e.g.
unsigned getNumInputs() const
This class is a general helper class for creating context-global objects like types,...
AffineExpr getAffineSymbolExpr(unsigned position)
AffineExpr getAffineDimExpr(unsigned position)
FlatLinearConstraints is an extension of IntegerPolyhedron.
IntegerSet getAsIntegerSet(MLIRContext *context) const
Returns the constraint system as an integer set.
LogicalResult flattenAlignedMapAndMergeLocals(AffineMap map, std::vector< SmallVector< int64_t, 8 >> *flattenedExprs, bool addConservativeSemiAffineBounds=false)
Given an affine map that is aligned with this constraint system:
unsigned appendLocalVar(unsigned num=1)
void printSpace(raw_ostream &os) const override
Prints the number of constraints, dimensions, symbols and locals in the FlatLinearConstraints.
void dumpRow(ArrayRef< int64_t > row, bool fixedColWidth=true) const
An easier to read dump of a row of the same width as the number of columns.
void dumpPretty() const
A more human-readable version of dump().
AddConservativeSemiAffineBounds
Flag to control if conservative semi-affine bounds should be added in addBound().
LogicalResult composeMatchingMap(AffineMap other)
Composes an affine map whose dimensions and symbols match one to one with the dimensions and symbols ...
void getSliceBounds(unsigned offset, unsigned num, MLIRContext *context, SmallVectorImpl< AffineMap > *lbMaps, SmallVectorImpl< AffineMap > *ubMaps, bool closedUB=false)
Computes the lower and upper bounds of the first num dimensional variables (starting at offset) as an...
LogicalResult addBound(presburger::BoundType type, unsigned pos, AffineMap boundMap, bool isClosedBound, AddConservativeSemiAffineBounds=AddConservativeSemiAffineBounds::No)
Adds a bound for the variable at the specified position with constraints being drawn from the specifi...
std::pair< AffineMap, AffineMap > getLowerAndUpperBound(unsigned pos, unsigned offset, unsigned num, unsigned symStartPos, ArrayRef< AffineExpr > localExprs, MLIRContext *context, bool closedUB=false) const
Gets the lower and upper bound of the offset + posth variable treating [0, offset) U [offset + num,...
LogicalResult computeLocalVars(SmallVectorImpl< AffineExpr > &memo, MLIRContext *context) const
Compute an explicit representation for local vars.
std::optional< int64_t > getConstantBoundOnDimSize(MLIRContext *context, unsigned pos, AffineMap *lb=nullptr, AffineMap *ub=nullptr, unsigned *minLbPos=nullptr, unsigned *minUbPos=nullptr) const
Returns a non-negative constant bound on the extent (upper bound - lower bound) of the specified vari...
FlatLinearValueConstraints represents an extension of FlatLinearConstraints where each non-local vari...
unsigned appendDimVar(unsigned num=1)
Append variables of the specified kind after the last variable of that kind.
unsigned insertDimVar(unsigned pos, ValueRange vals)
LogicalResult unionBoundingBox(const FlatLinearValueConstraints &other)
Updates the constraints to be the smallest bounding (enclosing) box that contains the points of this ...
void mergeAndAlignVarsWithOther(unsigned offset, FlatLinearValueConstraints *other)
Merge and align the variables of this and other starting at offset, so that both constraint systems g...
SmallVector< std::optional< Value > > getMaybeValues() const
unsigned insertSymbolVar(unsigned pos, unsigned num=1)
bool hasValue(unsigned pos) const
Returns true if the pos^th variable has an associated Value.
Value getValue(unsigned pos) const
Returns the Value associated with the pos^th variable.
void printSpace(raw_ostream &os) const override
Prints the number of constraints, dimensions, symbols and locals in the FlatAffineValueConstraints.
void mergeSymbolVars(FlatLinearValueConstraints &other)
Merge and align symbols of this and other such that both get union of of symbols that are unique.
void projectOut(Value val)
Projects out the variable that is associate with Value.
bool containsVar(Value val) const
Returns true if a variable with the specified Value exists, false otherwise.
void removeVarRange(presburger::VarKind kind, unsigned varStart, unsigned varLimit) override
Removes variables in the column range [varStart, varLimit), and copies any remaining valid data into ...
unsigned appendDimVar(ValueRange vals)
unsigned appendSymbolVar(unsigned num=1)
unsigned insertSymbolVar(unsigned pos, ValueRange vals)
bool findVar(Value val, unsigned *pos, unsigned offset=0) const
Looks up the position of the variable with the specified Value starting with variables at offset offs...
LogicalResult addBound(presburger::BoundType type, unsigned pos, AffineMap boundMap, bool isClosedBound, AddConservativeSemiAffineBounds=AddConservativeSemiAffineBounds::No)
Adds a bound for the variable at the specified position with constraints being drawn from the specifi...
bool areVarsAlignedWithOther(const FlatLinearConstraints &other)
Returns true if this constraint system and other are in the same space, i.e., if they are associated ...
AffineMap computeAlignedMap(AffineMap map, ValueRange operands) const
Align map with this constraint system based on operands.
void getValues(unsigned start, unsigned end, SmallVectorImpl< Value > *values) const
Returns the Values associated with variables in range [start, end).
FlatLinearValueConstraints(unsigned numReservedInequalities, unsigned numReservedEqualities, unsigned numReservedCols, unsigned numDims, unsigned numSymbols, unsigned numLocals, ArrayRef< std::optional< Value >> valArgs)
Constructs a constraint system reserving memory for the specified number of constraints and variables...
void setValue(unsigned pos, Value val)
Sets the Value associated with the pos^th variable.
unsigned insertDimVar(unsigned pos, unsigned num=1)
Insert variables of the specified kind at position pos.
unsigned insertVar(presburger::VarKind kind, unsigned pos, unsigned num=1) override
Insert num variables of the specified kind at position pos.
An integer set representing a conjunction of one or more affine equalities and inequalities.
unsigned getNumDims() const
static IntegerSet get(unsigned dimCount, unsigned symbolCount, ArrayRef< AffineExpr > constraints, ArrayRef< bool > eqFlags)
unsigned getNumInputs() const
unsigned getNumConstraints() const
ArrayRef< AffineExpr > getConstraints() const
ArrayRef< bool > getEqFlags() const
Returns the equality bits, which specify whether each of the constraints is an equality or inequality...
unsigned getNumSymbols() const
MLIRContext is the top-level object for a collection of MLIR operations.
virtual void addLocalFloorDivId(ArrayRef< int64_t > dividend, int64_t divisor, AffineExpr localExpr)
virtual LogicalResult addLocalIdSemiAffine(ArrayRef< int64_t > lhs, ArrayRef< int64_t > rhs, AffineExpr localExpr)
Add a local identifier (needed to flatten a mod, floordiv, ceildiv, mul expr) when the rhs is a symbo...
SimpleAffineExprFlattener(unsigned numDims, unsigned numSymbols)
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Class storing division representation of local variables of a constraint system.
unsigned getNumDivs() const
An Identifier stores a pointer to an object, such as a Value or an Operation.
An IntegerPolyhedron represents the set of points from a PresburgerSpace that satisfy a list of affin...
virtual void swapVar(unsigned posA, unsigned posB)
Swap the posA^th variable with the posB^th variable.
int64_t atEq64(unsigned i, unsigned j) const
The same, but casts to int64_t.
unsigned getVarKindEnd(VarKind kind) const
Return the index at Which the specified kind of vars ends.
std::optional< unsigned > findConstraintWithNonZeroAt(unsigned colIdx, bool isEq) const
Finds a constraint with a non-zero coefficient at colIdx in equality (isEq=true) or inequality (isEq=...
SmallVector< int64_t, 8 > getEquality64(unsigned idx) const
The same, but casts to int64_t.
unsigned getNumSymbolVars() const
std::optional< int64_t > getConstantBound64(BoundType type, unsigned pos) const
The same, but casts to int64_t.
unsigned getNumVarKind(VarKind kind) const
Get the number of vars of the specified kind.
void addLocalFloorDiv(ArrayRef< DynamicAPInt > dividend, const DynamicAPInt &divisor)
Adds a new local variable as the floordiv of an affine function of other variables,...
unsigned getNumDomainVars() const
unsigned getNumVars() const
void append(const IntegerRelation &other)
Appends constraints from other into this.
void addEquality(ArrayRef< DynamicAPInt > eq)
Adds an equality from the coefficients specified in eq.
unsigned getNumRangeVars() const
unsigned getNumLocalVars() const
unsigned getNumDimAndSymbolVars() const
unsigned getNumCols() const
Returns the number of columns in the constraint system.
DivisionRepr getLocalReprs(std::vector< MaybeLocalRepr > *repr=nullptr) const
Returns a DivisonRepr representing the division representation of local variables in the constraint s...
virtual void clearAndCopyFrom(const IntegerRelation &other)
Replaces the contents of this IntegerRelation with other.
void addInequality(ArrayRef< DynamicAPInt > inEq)
Adds an inequality (>= 0) from the coefficients specified in inEq.
unsigned mergeLocalVars(IntegerRelation &other)
Adds additional local vars to the sets such that they both have the union of the local vars in each s...
SmallVector< int64_t, 8 > getInequality64(unsigned idx) const
unsigned getNumEqualities() const
unsigned getVarKindOffset(VarKind kind) const
Return the index at which the specified kind of vars starts.
unsigned getNumDimVars() const
virtual void fourierMotzkinEliminate(unsigned pos, bool darkShadow=false, bool *isResultIntegerExact=nullptr)
Eliminates the variable at the specified position using Fourier-Motzkin variable elimination,...
This class represents a multi-affine function with the domain as Z^d, where d is the number of domain...
Identifier getId(VarKind kind, unsigned pos) const
Get the identifier of pos^th variable of the specified kind.
static PresburgerSpace getSetSpace(unsigned numDims=0, unsigned numSymbols=0, unsigned numLocals=0)
static void printSpace(std::ostream &os, int count)
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
BoundType
The type of bound: equal, lower bound or upper bound.
MaybeLocalRepr computeSingleVarRepr(const IntegerRelation &cst, ArrayRef< bool > foundRepr, unsigned pos, MutableArrayRef< DynamicAPInt > dividend, DynamicAPInt &divisor)
Returns the MaybeLocalRepr struct which contains the indices of the constraints that can be expressed...
Fraction abs(const Fraction &f)
Include the generated interface declarations.
const FrozenRewritePatternSet GreedyRewriteConfig bool * changed
AffineMap alignAffineMapWithValues(AffineMap map, ValueRange operands, ValueRange dims, ValueRange syms, SmallVector< Value > *newSyms=nullptr)
Re-indexes the dimensions and symbols of an affine map with given operands values to align with dims ...
@ Mod
RHS of mod is always a constant or a symbolic expression with a positive value.
AffineExpr getAffineExprFromFlatForm(ArrayRef< int64_t > flatExprs, unsigned numDims, unsigned numSymbols, ArrayRef< AffineExpr > localExprs, MLIRContext *context)
Constructs an affine expression from a flat ArrayRef.
AffineExpr getAffineConstantExpr(int64_t constant, MLIRContext *context)
LogicalResult getFlattenedAffineExpr(AffineExpr expr, unsigned numDims, unsigned numSymbols, SmallVectorImpl< int64_t > *flattenedExpr, FlatLinearConstraints *cst=nullptr, bool addConservativeSemiAffineBounds=false)
Flattens 'expr' into 'flattenedExpr', which contains the coefficients of the dimensions,...
LogicalResult getFlattenedAffineExprs(AffineMap map, std::vector< SmallVector< int64_t, 8 >> *flattenedExprs, FlatLinearConstraints *cst=nullptr, bool addConservativeSemiAffineBounds=false)
Flattens the result expressions of the map to their corresponding flattened forms and set in 'flatten...
AffineExpr simplifyAffineExpr(AffineExpr expr, unsigned numDims, unsigned numSymbols)
Simplify an affine expression by flattening and some amount of simple analysis.
AffineExpr getAffineDimExpr(unsigned position, MLIRContext *context)
These free functions allow clients of the API to not use classes in detail.
LogicalResult getMultiAffineFunctionFromMap(AffineMap map, presburger::MultiAffineFunction &multiAff)
AffineExpr getAffineSymbolExpr(unsigned position, MLIRContext *context)
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.