20struct ConstantOpInterface
21 :
public ValueBoundsOpInterface::ExternalModel<ConstantOpInterface,
23 void populateBoundsForIndexValue(Operation *op, Value value,
24 ValueBoundsConstraintSet &cstr)
const {
25 auto constantOp = cast<ConstantOp>(op);
26 assert(value == constantOp.getResult() &&
"invalid value");
28 if (
auto attr = llvm::dyn_cast<IntegerAttr>(constantOp.getValue()))
29 cstr.
bound(value) == attr.getInt();
33struct ExtSIOpInterface
34 :
public ValueBoundsOpInterface::ExternalModel<ExtSIOpInterface, ExtSIOp> {
35 void populateBoundsForIndexValue(Operation *op, Value value,
36 ValueBoundsConstraintSet &cstr)
const {
37 auto extSIOp = cast<ExtSIOp>(op);
38 assert(value == extSIOp.getOut() &&
"invalid value");
47 :
public ValueBoundsOpInterface::ExternalModel<AddIOpInterface, AddIOp> {
48 void populateBoundsForIndexValue(Operation *op, Value value,
49 ValueBoundsConstraintSet &cstr)
const {
50 auto addIOp = cast<AddIOp>(op);
51 assert(value == addIOp.getResult() &&
"invalid value");
59 AffineExpr
lhs = cstr.
getExpr(addIOp.getLhs());
60 AffineExpr
rhs = cstr.
getExpr(addIOp.getRhs());
65struct DivUIOpInterface
66 :
public ValueBoundsOpInterface::ExternalModel<DivUIOpInterface,
68 void populateBoundsForIndexValue(Operation *op, Value value,
69 ValueBoundsConstraintSet &cstr)
const {
70 auto divOp = cast<arith::DivUIOp>(op);
71 assert(value == divOp.getResult() &&
"invalid value");
77 if (!lhsNonNegative || !rhsPositive)
82 cstr.
bound(value) >= 0;
87struct DivSIOpInterface
88 :
public ValueBoundsOpInterface::ExternalModel<DivSIOpInterface,
90 void populateBoundsForIndexValue(Operation *op, Value value,
91 ValueBoundsConstraintSet &cstr)
const {
92 auto divOp = cast<arith::DivSIOp>(op);
93 assert(value == divOp.getResult() &&
"invalid value");
95 Value lhsValue = divOp.getLhs();
96 Value rhsValue = divOp.getRhs();
100 bool lhsNonPositive =
119 if ((lhsNonNegative && rhsPositive) || (lhsNonPositive && rhsNegative)) {
121 cstr.
bound(value) >= 0;
122 }
else if ((lhsNonPositive && rhsPositive) ||
123 (lhsNonNegative && rhsNegative)) {
125 cstr.
bound(value) <= 0;
130struct SubIOpInterface
131 :
public ValueBoundsOpInterface::ExternalModel<SubIOpInterface, SubIOp> {
132 void populateBoundsForIndexValue(Operation *op, Value value,
133 ValueBoundsConstraintSet &cstr)
const {
134 auto subIOp = cast<SubIOp>(op);
135 assert(value == subIOp.getResult() &&
"invalid value");
137 AffineExpr
lhs = cstr.
getExpr(subIOp.getLhs());
138 AffineExpr
rhs = cstr.
getExpr(subIOp.getRhs());
143struct MulIOpInterface
144 :
public ValueBoundsOpInterface::ExternalModel<MulIOpInterface, MulIOp> {
145 void populateBoundsForIndexValue(Operation *op, Value value,
146 ValueBoundsConstraintSet &cstr)
const {
147 auto mulIOp = cast<MulIOp>(op);
148 assert(value == mulIOp.getResult() &&
"invalid value");
150 AffineExpr
lhs = cstr.
getExpr(mulIOp.getLhs());
151 AffineExpr
rhs = cstr.
getExpr(mulIOp.getRhs());
156struct FloorDivSIOpInterface
157 :
public ValueBoundsOpInterface::ExternalModel<FloorDivSIOpInterface,
159 void populateBoundsForIndexValue(Operation *op, Value value,
160 ValueBoundsConstraintSet &cstr)
const {
161 auto divSIOp = cast<FloorDivSIOp>(op);
162 assert(value == divSIOp.getResult() &&
"invalid value");
164 AffineExpr
lhs = cstr.
getExpr(divSIOp.getLhs());
165 AffineExpr
rhs = cstr.
getExpr(divSIOp.getRhs());
170struct CeilDivSIOpInterface
171 :
public ValueBoundsOpInterface::ExternalModel<CeilDivSIOpInterface,
173 void populateBoundsForIndexValue(Operation *op, Value value,
174 ValueBoundsConstraintSet &cstr)
const {
175 auto divSIOp = cast<CeilDivSIOp>(op);
176 assert(value == divSIOp.getResult() &&
"invalid value");
178 AffineExpr
lhs = cstr.
getExpr(divSIOp.getLhs());
179 AffineExpr
rhs = cstr.
getExpr(divSIOp.getRhs());
184struct RemSIOpInterface
185 :
public ValueBoundsOpInterface::ExternalModel<RemSIOpInterface, RemSIOp> {
186 void populateBoundsForIndexValue(Operation *op, Value value,
187 ValueBoundsConstraintSet &cstr)
const {
188 auto remSIOp = cast<RemSIOp>(op);
189 assert(value == remSIOp.getResult() &&
"invalid value");
191 Value lhsValue = remSIOp.getLhs();
192 Value rhsValue = remSIOp.getRhs();
213 cstr.
bound(value) <= 0;
220 cstr.
bound(value) >= 0;
229struct RemUIOpInterface
230 :
public ValueBoundsOpInterface::ExternalModel<RemUIOpInterface, RemUIOp> {
231 void populateBoundsForIndexValue(Operation *op, Value value,
232 ValueBoundsConstraintSet &cstr)
const {
233 auto remUIOp = cast<RemUIOp>(op);
234 assert(value == remUIOp.getResult() &&
"invalid value");
236 Value rhsValue = remUIOp.getRhs();
242 cstr.
bound(value) >= 0;
248struct SelectOpInterface
249 :
public ValueBoundsOpInterface::ExternalModel<SelectOpInterface,
252 static void populateBounds(SelectOp selectOp, std::optional<int64_t> dim,
253 ValueBoundsConstraintSet &cstr) {
254 Value value = selectOp.getResult();
255 Value condition = selectOp.getCondition();
256 Value trueValue = selectOp.getTrueValue();
257 Value falseValue = selectOp.getFalseValue();
259 if (isa<ShapedType>(condition.
getType())) {
262 cstr.
bound(value)[*dim] == cstr.
getExpr(trueValue, dim);
263 cstr.
bound(value)[*dim] == cstr.
getExpr(falseValue, dim);
264 cstr.
bound(value)[*dim] == cstr.
getExpr(condition, dim);
272 auto boundsBuilder = cstr.
bound(value);
283 {falseValue, dim})) {
285 cstr.
bound(value)[*dim] >= cstr.
getExpr(trueValue, dim);
286 cstr.
bound(value)[*dim] <= cstr.
getExpr(falseValue, dim);
288 cstr.
bound(value) >= trueValue;
289 cstr.
bound(value) <= falseValue;
300 cstr.
bound(value)[*dim] >= cstr.
getExpr(falseValue, dim);
301 cstr.
bound(value)[*dim] <= cstr.
getExpr(trueValue, dim);
303 cstr.
bound(value) >= falseValue;
304 cstr.
bound(value) <= trueValue;
309 void populateBoundsForIndexValue(Operation *op, Value value,
310 ValueBoundsConstraintSet &cstr)
const {
311 populateBounds(cast<SelectOp>(op), std::nullopt, cstr);
314 void populateBoundsForShapedValueDim(Operation *op, Value value, int64_t dim,
315 ValueBoundsConstraintSet &cstr)
const {
316 populateBounds(cast<SelectOp>(op), dim, cstr);
320struct MinSIOpInterface
321 :
public ValueBoundsOpInterface::ExternalModel<MinSIOpInterface, MinSIOp> {
322 void populateBoundsForIndexValue(Operation *op, Value value,
323 ValueBoundsConstraintSet &cstr)
const {
324 auto minOp = cast<MinSIOp>(op);
325 assert(value == minOp.getResult() &&
"invalid value");
327 AffineExpr
lhs = cstr.
getExpr(minOp.getLhs());
328 AffineExpr
rhs = cstr.
getExpr(minOp.getRhs());
334struct MaxSIOpInterface
335 :
public ValueBoundsOpInterface::ExternalModel<MaxSIOpInterface, MaxSIOp> {
336 void populateBoundsForIndexValue(Operation *op, Value value,
337 ValueBoundsConstraintSet &cstr)
const {
338 auto maxOp = cast<MaxSIOp>(op);
339 assert(value == maxOp.getResult() &&
"invalid value");
341 AffineExpr
lhs = cstr.
getExpr(maxOp.getLhs());
342 AffineExpr
rhs = cstr.
getExpr(maxOp.getRhs());
348struct MinUIOpInterface
349 :
public ValueBoundsOpInterface::ExternalModel<MinUIOpInterface,
351 void populateBoundsForIndexValue(Operation *op, Value value,
352 ValueBoundsConstraintSet &cstr)
const {
353 auto minOp = cast<arith::MinUIOp>(op);
354 assert(value == minOp.getResult() &&
"invalid value");
360 bool lhsNonNegative =
362 bool rhsNonNegative =
364 if (!lhsNonNegative && !rhsNonNegative)
373 cstr.
bound(value) >= 0;
377 if (lhsNonNegative) {
378 AffineExpr
lhs = cstr.
getExpr(minOp.getLhs());
381 if (rhsNonNegative) {
382 AffineExpr
rhs = cstr.
getExpr(minOp.getRhs());
388struct MaxUIOpInterface
389 :
public ValueBoundsOpInterface::ExternalModel<MaxUIOpInterface,
391 void populateBoundsForIndexValue(Operation *op, Value value,
392 ValueBoundsConstraintSet &cstr)
const {
393 auto maxOp = cast<arith::MaxUIOp>(op);
394 assert(value == maxOp.getResult() &&
"invalid value");
397 bool lhsNonNegative =
399 bool rhsNonNegative =
402 if (lhsNonNegative) {
403 AffineExpr
lhs = cstr.
getExpr(maxOp.getLhs());
406 if (rhsNonNegative) {
407 AffineExpr
rhs = cstr.
getExpr(maxOp.getRhs());
419 arith::ConstantOp::attachInterface<arith::ConstantOpInterface>(*ctx);
420 arith::ExtSIOp::attachInterface<arith::ExtSIOpInterface>(*ctx);
421 arith::AddIOp::attachInterface<arith::AddIOpInterface>(*ctx);
422 arith::DivUIOp::attachInterface<arith::DivUIOpInterface>(*ctx);
423 arith::DivSIOp::attachInterface<arith::DivSIOpInterface>(*ctx);
424 arith::SubIOp::attachInterface<arith::SubIOpInterface>(*ctx);
425 arith::MulIOp::attachInterface<arith::MulIOpInterface>(*ctx);
426 arith::FloorDivSIOp::attachInterface<arith::FloorDivSIOpInterface>(*ctx);
427 arith::CeilDivSIOp::attachInterface<arith::CeilDivSIOpInterface>(*ctx);
428 arith::RemSIOp::attachInterface<arith::RemSIOpInterface>(*ctx);
429 arith::RemUIOp::attachInterface<arith::RemUIOpInterface>(*ctx);
430 arith::SelectOp::attachInterface<arith::SelectOpInterface>(*ctx);
431 arith::MinSIOp::attachInterface<arith::MinSIOpInterface>(*ctx);
432 arith::MaxSIOp::attachInterface<arith::MaxSIOpInterface>(*ctx);
433 arith::MinUIOp::attachInterface<arith::MinUIOpInterface>(*ctx);
434 arith::MaxUIOp::attachInterface<arith::MaxUIOpInterface>(*ctx);
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
MLIRContext is the top-level object for a collection of MLIR operations.
static bool isProvablyNegative(Value value, ValueBoundsConstraintSet &cstr)
Return "true" if the given value is provably negative.
static bool isProvablyPositive(Value value, ValueBoundsConstraintSet &cstr)
Return "true" if the given value is provably positive.
AffineExpr getExpr(Value value, std::optional< int64_t > dim=std::nullopt)
Return an expression that represents the given index-typed value or shaped value dimension.
BoundBuilder bound(Value value)
Add a bound for the given index-typed value or shaped value.
static bool isProvablyNonNegative(Value value, ValueBoundsConstraintSet &cstr)
Return "true" if the given value is provably non-negative.
static bool isProvablyNonPositive(Value value, ValueBoundsConstraintSet &cstr)
Return "true" if the given value is provably non-positive.
void populateConstraints(Value value, std::optional< int64_t > dim)
Traverse the IR starting from the given value/dim and populate constraints as long as the stop condit...
bool populateAndCompare(const Variable &lhs, ComparisonOperator cmp, const Variable &rhs)
Populate constraints for lhs/rhs (until the stop condition is met).
Type getType() const
Return the type of this value.
void registerValueBoundsOpInterfaceExternalModels(DialectRegistry ®istry)
Include the generated interface declarations.