Skip to content

Commit

Permalink
[mlir][Analysis][NFC] Make BoundType a top-level enum
Browse files Browse the repository at this point in the history
`BoundType` is no longer a nested member of `IntegerRelation` but a top-level enum in the `presburger` namespace.

This allows `BoundType` to be predeclared in header files. Nested members cannot be predeclared.

Differential Revision: https://reviews.llvm.org/D146210
  • Loading branch information
matthias-springer committed Mar 23, 2023
1 parent e50f131 commit 47bff1c
Show file tree
Hide file tree
Showing 13 changed files with 48 additions and 57 deletions.
9 changes: 5 additions & 4 deletions mlir/include/mlir/Analysis/FlatLinearValueConstraints.h
Expand Up @@ -87,8 +87,8 @@ class FlatLinearConstraints : public presburger::IntegerPolyhedron {
///
/// Note: The dimensions/symbols of this FlatLinearConstraints must match the
/// dimensions/symbols of the affine map.
LogicalResult addBound(BoundType type, unsigned pos, AffineMap boundMap,
bool isClosedBound);
LogicalResult addBound(presburger::BoundType type, unsigned pos,
AffineMap boundMap, bool isClosedBound);

/// Adds a bound for the variable at the specified position with constraints
/// being drawn from the specified bound map. In case of an EQ bound, the
Expand All @@ -98,7 +98,8 @@ class FlatLinearConstraints : public presburger::IntegerPolyhedron {
/// Note: The dimensions/symbols of this FlatLinearConstraints must match the
/// dimensions/symbols of the affine map. By default the lower bound is closed
/// and the upper bound is open.
LogicalResult addBound(BoundType type, unsigned pos, AffineMap boundMap);
LogicalResult addBound(presburger::BoundType type, unsigned pos,
AffineMap boundMap);

/// The `addBound` overload above hides the inherited overloads by default, so
/// we explicitly introduce them here.
Expand Down Expand Up @@ -315,7 +316,7 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
void clearAndCopyFrom(const IntegerRelation &other) override;

/// Adds a constant bound for the variable associated with the given Value.
void addBound(BoundType type, Value val, int64_t value);
void addBound(presburger::BoundType type, Value val, int64_t value);
using FlatLinearConstraints::addBound;

/// Returns the Value associated with the pos^th variable. Asserts if
Expand Down
6 changes: 3 additions & 3 deletions mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
Expand Up @@ -31,6 +31,9 @@ class PresburgerSet;
class PresburgerRelation;
struct SymbolicLexMin;

/// The type of bound: equal, lower bound or upper bound.
enum class BoundType { EQ, LB, UB };

/// An IntegerRelation represents the set of points from a PresburgerSpace that
/// satisfy a list of affine constraints. Affine constraints can be inequalities
/// or equalities in the form:
Expand Down Expand Up @@ -397,9 +400,6 @@ class IntegerRelation {
/// to None.
DivisionRepr getLocalReprs(std::vector<MaybeLocalRepr> *repr = nullptr) const;

/// The type of bound: equal, lower bound or upper bound.
enum BoundType { EQ, LB, UB };

/// Adds a constant bound for the specified variable.
void addBound(BoundType type, unsigned pos, const MPInt &value);
void addBound(BoundType type, unsigned pos, int64_t value) {
Expand Down
4 changes: 2 additions & 2 deletions mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h
Expand Up @@ -100,8 +100,8 @@ class FlatAffineValueConstraints : public FlatLinearValueConstraints {
/// EQ bound, the bound map is expected to have exactly one result. In case
/// of a LB/UB, the bound map may have more than one result, for each of which
/// an inequality is added.
LogicalResult addBound(BoundType type, unsigned pos, AffineMap boundMap,
ValueRange operands);
LogicalResult addBound(presburger::BoundType type, unsigned pos,
AffineMap boundMap, ValueRange operands);
using FlatLinearValueConstraints::addBound;

/// Add the specified values as a dim or symbol var depending on its nature,
Expand Down
3 changes: 1 addition & 2 deletions mlir/lib/Analysis/FlatLinearValueConstraints.cpp
Expand Up @@ -308,8 +308,7 @@ static bool detectAsMod(const FlatLinearConstraints &cst, unsigned pos,

// Express `var_r` as `var_n % divisor` and store the expression in `memo`.
if (quotientCount >= 1) {
auto ub = cst.getConstantBound64(FlatLinearConstraints::BoundType::UB,
dimExpr.getPosition());
auto ub = cst.getConstantBound64(BoundType::UB, dimExpr.getPosition());
// If `var_n` has an upperbound that is less than the divisor, mod can be
// eliminated altogether.
if (ub && *ub < divisor)
Expand Down
4 changes: 2 additions & 2 deletions mlir/lib/Analysis/Presburger/PWMAFunction.cpp
Expand Up @@ -231,14 +231,14 @@ MultiAffineFunction::getLexSet(OrderingKind comp,
// outA - outB <= -1
// outA <= outB - 1
// outA < outB
levelSet.addBound(IntegerPolyhedron::BoundType::UB, subExpr, MPInt(-1));
levelSet.addBound(BoundType::UB, subExpr, MPInt(-1));
break;
case OrderingKind::GT:
// For greater than, we add a lower bound of 1:
// outA - outB >= 1
// outA > outB + 1
// outA > outB
levelSet.addBound(IntegerPolyhedron::BoundType::LB, subExpr, MPInt(1));
levelSet.addBound(BoundType::LB, subExpr, MPInt(1));
break;
case OrderingKind::GE:
case OrderingKind::LE:
Expand Down
6 changes: 2 additions & 4 deletions mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp
Expand Up @@ -445,12 +445,10 @@ static void computeDirectionVector(
dependenceComponents->resize(numCommonLoops);
for (unsigned j = 0; j < numCommonLoops; ++j) {
(*dependenceComponents)[j].op = commonLoops[j].getOperation();
auto lbConst =
dependenceDomain->getConstantBound64(IntegerPolyhedron::LB, j);
auto lbConst = dependenceDomain->getConstantBound64(BoundType::LB, j);
(*dependenceComponents)[j].lb =
lbConst.value_or(std::numeric_limits<int64_t>::min());
auto ubConst =
dependenceDomain->getConstantBound64(IntegerPolyhedron::UB, j);
auto ubConst = dependenceDomain->getConstantBound64(BoundType::UB, j);
(*dependenceComponents)[j].ub =
ubConst.value_or(std::numeric_limits<int64_t>::max());
}
Expand Down
31 changes: 14 additions & 17 deletions mlir/lib/Dialect/Affine/Analysis/Utils.cpp
Expand Up @@ -98,7 +98,7 @@ ComputationSliceState::getAsConstraints(FlatAffineValueConstraints *cst) {
if (isValidSymbol(value)) {
// Check if the symbol is a constant.
if (auto cOp = value.getDefiningOp<arith::ConstantIndexOp>())
cst->addBound(FlatAffineValueConstraints::EQ, value, cOp.value());
cst->addBound(BoundType::EQ, value, cOp.value());
} else if (auto loop = getForInductionVarOwner(value)) {
if (failed(cst->addAffineForOpDomain(loop)))
return failure();
Expand Down Expand Up @@ -357,11 +357,11 @@ std::optional<int64_t> MemRefRegion::getConstantBoundingSizeAndShape(
// that will need non-trivials means to eliminate.
FlatAffineValueConstraints cstWithShapeBounds(cst);
for (unsigned r = 0; r < rank; r++) {
cstWithShapeBounds.addBound(FlatAffineValueConstraints::LB, r, 0);
cstWithShapeBounds.addBound(BoundType::LB, r, 0);
int64_t dimSize = memRefType.getDimSize(r);
if (ShapedType::isDynamic(dimSize))
continue;
cstWithShapeBounds.addBound(FlatAffineValueConstraints::UB, r, dimSize - 1);
cstWithShapeBounds.addBound(BoundType::UB, r, dimSize - 1);
}

// Find a constant upper bound on the extent of this memref region along each
Expand Down Expand Up @@ -516,7 +516,7 @@ LogicalResult MemRefRegion::compute(Operation *op, unsigned loopDepth,
// Check if the symbol is a constant.
Value symbol = operand;
if (auto constVal = getConstantIntValue(symbol))
cst.addBound(FlatAffineValueConstraints::EQ, symbol, constVal.value());
cst.addBound(BoundType::EQ, symbol, constVal.value());
} else {
LLVM_DEBUG(llvm::dbgs() << "unknown affine dimensional value");
return failure();
Expand Down Expand Up @@ -580,11 +580,10 @@ LogicalResult MemRefRegion::compute(Operation *op, unsigned loopDepth,
if (addMemRefDimBounds) {
auto memRefType = memref.getType().cast<MemRefType>();
for (unsigned r = 0; r < rank; r++) {
cst.addBound(FlatAffineValueConstraints::LB, /*pos=*/r, /*value=*/0);
cst.addBound(BoundType::LB, /*pos=*/r, /*value=*/0);
if (memRefType.isDynamicDim(r))
continue;
cst.addBound(FlatAffineValueConstraints::UB, /*pos=*/r,
memRefType.getDimSize(r) - 1);
cst.addBound(BoundType::UB, /*pos=*/r, memRefType.getDimSize(r) - 1);
}
}
cst.removeTrivialRedundancy();
Expand Down Expand Up @@ -695,7 +694,7 @@ LogicalResult mlir::boundCheckLoadOrStoreOp(LoadOrStoreOp loadOrStoreOp,
continue;

// Check for overflow: d_i >= memref dim size.
ucst.addBound(FlatAffineValueConstraints::LB, r, dimSize);
ucst.addBound(BoundType::LB, r, dimSize);
outOfBounds = !ucst.isEmpty();
if (outOfBounds && emitError) {
loadOrStoreOp.emitOpError()
Expand All @@ -706,7 +705,7 @@ LogicalResult mlir::boundCheckLoadOrStoreOp(LoadOrStoreOp loadOrStoreOp,
FlatAffineValueConstraints lcst(*region.getConstraints());
std::fill(ineq.begin(), ineq.end(), 0);
// d_i <= -1;
lcst.addBound(FlatAffineValueConstraints::UB, r, -1);
lcst.addBound(BoundType::UB, r, -1);
outOfBounds = !lcst.isEmpty();
if (outOfBounds && emitError) {
loadOrStoreOp.emitOpError()
Expand Down Expand Up @@ -1403,9 +1402,8 @@ static void unpackOptionalValues(ArrayRef<std::optional<Value>> source,
/// Note: This function adds a new symbol column to the `constraints` for each
/// dimension/symbol that exists in the affine map but not in `constraints`.
static LogicalResult alignAndAddBound(FlatAffineValueConstraints &constraints,
IntegerPolyhedron::BoundType type,
unsigned pos, AffineMap map,
ValueRange operands) {
BoundType type, unsigned pos,
AffineMap map, ValueRange operands) {
SmallVector<Value> dims, syms, newSyms;
unpackOptionalValues(constraints.getMaybeValues(VarKind::SetDim), dims);
unpackOptionalValues(constraints.getMaybeValues(VarKind::Symbol), syms);
Expand Down Expand Up @@ -1482,7 +1480,7 @@ mlir::simplifyConstrainedMinMaxOp(Operation *op,

// Add an inequality for each result expr_i of map:
// isMin: op <= expr_i, !isMin: op >= expr_i
auto boundType = isMin ? IntegerPolyhedron::UB : IntegerPolyhedron::LB;
auto boundType = isMin ? BoundType::UB : BoundType::LB;
// Upper bounds are exclusive, so add 1. (`affine.min` ops are inclusive.)
AffineMap mapLbUb = isMin ? addConstToResults(map, 1) : map;
if (failed(
Expand All @@ -1504,8 +1502,7 @@ mlir::simplifyConstrainedMinMaxOp(Operation *op,
// Add an equality: Set dimOpBound to computed bound.
// Add back dimension for op. (Was removed by `getSliceBounds`.)
AffineMap alignedBoundMap = boundMap.shiftDims(/*shift=*/1, /*offset=*/dimOp);
if (failed(constraints.addBound(IntegerPolyhedron::EQ, dimOpBound,
alignedBoundMap)))
if (failed(constraints.addBound(BoundType::EQ, dimOpBound, alignedBoundMap)))
return failure();

// If the constraint system is empty, there is an inconsistency. (E.g., this
Expand All @@ -1530,7 +1527,7 @@ mlir::simplifyConstrainedMinMaxOp(Operation *op,
// Note: These equalities could have been added earlier and used to express
// minOp <= expr_i. However, then we run the risk that `getSliceBounds`
// computes minOpUb in terms of r_i dims, which is not desired.
if (failed(alignAndAddBound(newConstr, IntegerPolyhedron::EQ, i,
if (failed(alignAndAddBound(newConstr, BoundType::EQ, i,
map.getSubMap({i - resultDimStart}), operands)))
return failure();

Expand All @@ -1557,7 +1554,7 @@ mlir::simplifyConstrainedMinMaxOp(Operation *op,
// Skip unused operands and operands that are already constants.
if (!newOperands[i] || getConstantIntValue(newOperands[i]))
continue;
if (auto bound = constraints.getConstantBound64(IntegerPolyhedron::EQ, i)) {
if (auto bound = constraints.getConstantBound64(BoundType::EQ, i)) {
AffineExpr expr =
i < newMap.getNumDims()
? builder.getAffineDimExpr(i)
Expand Down
6 changes: 2 additions & 4 deletions mlir/lib/Dialect/Affine/TransformOps/AffineTransformOps.cpp
Expand Up @@ -97,11 +97,9 @@ SimplifyBoundedAffineOpsOp::apply(TransformResults &results,
unsigned pos;
if (!cstr.findVar(std::get<0>(it), &pos))
pos = cstr.appendSymbolVar(std::get<0>(it));
cstr.addBound(FlatAffineValueConstraints::BoundType::LB, pos,
std::get<1>(it));
cstr.addBound(presburger::BoundType::LB, pos, std::get<1>(it));
// Note: addBound bounds are inclusive, but specified UB is exclusive.
cstr.addBound(FlatAffineValueConstraints::BoundType::UB, pos,
std::get<2>(it) - 1);
cstr.addBound(presburger::BoundType::UB, pos, std::get<2>(it) - 1);
}

// Transform all targets.
Expand Down
4 changes: 2 additions & 2 deletions mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp
Expand Up @@ -2371,8 +2371,8 @@ static bool getFullMemRefAsRegion(Operation *op, unsigned numParamLoopIVs,
for (unsigned d = 0; d < rank; d++) {
auto dimSize = memRefType.getDimSize(d);
assert(dimSize > 0 && "filtered dynamic shapes above");
regionCst->addBound(IntegerPolyhedron::LB, d, 0);
regionCst->addBound(IntegerPolyhedron::UB, d, dimSize - 1);
regionCst->addBound(BoundType::LB, d, 0);
regionCst->addBound(BoundType::UB, d, dimSize - 1);
}
return true;
}
Expand Down
7 changes: 3 additions & 4 deletions mlir/lib/Dialect/Affine/Utils/Utils.cpp
Expand Up @@ -1800,8 +1800,8 @@ MemRefType mlir::normalizeMemRefType(MemRefType memrefType,
for (unsigned d = 0; d < rank; ++d) {
// Use constraint system only in static dimensions.
if (shape[d] > 0) {
fac.addBound(IntegerPolyhedron::LB, d, 0);
fac.addBound(IntegerPolyhedron::UB, d, shape[d] - 1);
fac.addBound(BoundType::LB, d, 0);
fac.addBound(BoundType::UB, d, shape[d] - 1);
} else {
memrefTypeDynDims.emplace_back(d);
}
Expand All @@ -1824,8 +1824,7 @@ MemRefType mlir::normalizeMemRefType(MemRefType memrefType,
newShape[d] = ShapedType::kDynamic;
} else {
// The lower bound for the shape is always zero.
std::optional<int64_t> ubConst =
fac.getConstantBound64(IntegerPolyhedron::UB, d);
std::optional<int64_t> ubConst = fac.getConstantBound64(BoundType::UB, d);
// For a static memref and an affine map with no symbols, this is
// always bounded. However, when we have symbols, we may not be able to
// obtain a constant upper bound. Also, mapping to a negative space is
Expand Down
7 changes: 3 additions & 4 deletions mlir/lib/Dialect/Linalg/Utils/Utils.cpp
Expand Up @@ -270,7 +270,7 @@ void getUpperBoundForIndex(Value value, AffineMap &boundMap,
if (auto applyOp = dyn_cast<AffineApplyOp>(op)) {
AffineMap map = constraints.computeAlignedMap(applyOp.getAffineMap(),
applyOp.getOperands());
if (failed(constraints.addBound(IntegerPolyhedron::EQ,
if (failed(constraints.addBound(BoundType::EQ,
getPosition(applyOp.getResult()), map)))
return;
continue;
Expand All @@ -279,7 +279,7 @@ void getUpperBoundForIndex(Value value, AffineMap &boundMap,
auto minOp = cast<AffineMinOp>(op);
AffineMap map = constraints.computeAlignedMap(minOp.getAffineMap(),
minOp.getOperands());
if (failed(constraints.addBound(IntegerPolyhedron::UB,
if (failed(constraints.addBound(BoundType::UB,
getPosition(minOp.getResult()), map,
/*isClosedBound=*/true)))
return;
Expand All @@ -290,8 +290,7 @@ void getUpperBoundForIndex(Value value, AffineMap &boundMap,
// of the terminals of the index computation.
unsigned pos = getPosition(value);
if (constantRequired) {
auto ubConst = constraints.getConstantBound64(
FlatAffineValueConstraints::BoundType::UB, pos);
auto ubConst = constraints.getConstantBound64(BoundType::UB, pos);
if (!ubConst)
return;

Expand Down
10 changes: 5 additions & 5 deletions mlir/lib/Dialect/SCF/Utils/AffineCanonicalizationUtils.cpp
Expand Up @@ -98,9 +98,9 @@ LogicalResult scf::addLoopRangeConstraints(FlatAffineValueConstraints &cstr,
std::optional<int64_t> lbInt = getConstantIntValue(lb);
std::optional<int64_t> ubInt = getConstantIntValue(ub);
if (lbInt)
cstr.addBound(IntegerPolyhedron::EQ, symLb, *lbInt);
cstr.addBound(BoundType::EQ, symLb, *lbInt);
if (ubInt)
cstr.addBound(IntegerPolyhedron::EQ, symUb, *ubInt);
cstr.addBound(BoundType::EQ, symUb, *ubInt);

// Lower bound: iv >= lb (equiv.: iv - lb >= 0)
SmallVector<int64_t> ineqLb(cstr.getNumCols(), 0);
Expand Down Expand Up @@ -131,7 +131,7 @@ LogicalResult scf::addLoopRangeConstraints(FlatAffineValueConstraints &cstr,
/*dimCount=*/cstr.getNumDimVars(),
/*symbolCount=*/cstr.getNumSymbolVars(), /*result=*/ivUb);

return cstr.addBound(IntegerPolyhedron::UB, dimIv, map);
return cstr.addBound(BoundType::UB, dimIv, map);
}

/// Canonicalize min/max operations in the context of for loops with a known
Expand Down Expand Up @@ -202,9 +202,9 @@ LogicalResult scf::rewritePeeledMinMaxOp(RewriterBase &rewriter, Operation *op,
constraints.appendDimVar({iv});
constraints.appendSymbolVar({ub, step});
if (auto constUb = getConstantIntValue(ub))
constraints.addBound(IntegerPolyhedron::EQ, 1, *constUb);
constraints.addBound(BoundType::EQ, 1, *constUb);
if (auto constStep = getConstantIntValue(step))
constraints.addBound(IntegerPolyhedron::EQ, 2, *constStep);
constraints.addBound(BoundType::EQ, 2, *constStep);

// Add loop peeling invariant. This is the main piece of knowledge that
// enables AffineMinOp simplification.
Expand Down
8 changes: 4 additions & 4 deletions mlir/unittests/Analysis/Presburger/IntegerPolyhedronTest.cpp
Expand Up @@ -594,25 +594,25 @@ TEST(IntegerPolyhedronTest, removeRedundantConstraintsTest) {

TEST(IntegerPolyhedronTest, addConstantUpperBound) {
IntegerPolyhedron poly(PresburgerSpace::getSetSpace(2));
poly.addBound(IntegerPolyhedron::UB, 0, 1);
poly.addBound(BoundType::UB, 0, 1);
EXPECT_EQ(poly.atIneq(0, 0), -1);
EXPECT_EQ(poly.atIneq(0, 1), 0);
EXPECT_EQ(poly.atIneq(0, 2), 1);

poly.addBound(IntegerPolyhedron::UB, {1, 2, 3}, 1);
poly.addBound(BoundType::UB, {1, 2, 3}, 1);
EXPECT_EQ(poly.atIneq(1, 0), -1);
EXPECT_EQ(poly.atIneq(1, 1), -2);
EXPECT_EQ(poly.atIneq(1, 2), -2);
}

TEST(IntegerPolyhedronTest, addConstantLowerBound) {
IntegerPolyhedron poly(PresburgerSpace::getSetSpace(2));
poly.addBound(IntegerPolyhedron::LB, 0, 1);
poly.addBound(BoundType::LB, 0, 1);
EXPECT_EQ(poly.atIneq(0, 0), 1);
EXPECT_EQ(poly.atIneq(0, 1), 0);
EXPECT_EQ(poly.atIneq(0, 2), -1);

poly.addBound(IntegerPolyhedron::LB, {1, 2, 3}, 1);
poly.addBound(BoundType::LB, {1, 2, 3}, 1);
EXPECT_EQ(poly.atIneq(1, 0), 1);
EXPECT_EQ(poly.atIneq(1, 1), 2);
EXPECT_EQ(poly.atIneq(1, 2), 2);
Expand Down

0 comments on commit 47bff1c

Please sign in to comment.