22 :
public ValueBoundsOpInterface::ExternalModel<ForOpInterface, ForOp> {
25 static void populateIterArgBounds(scf::ForOp forOp,
Value value,
26 std::optional<int64_t> dim,
30 if (
auto iterArg = llvm::dyn_cast<BlockArgument>(value)) {
31 iterArgIdx = iterArg.getArgNumber() - forOp.getNumInductionVars();
33 iterArgIdx = llvm::cast<OpResult>(value).getResultNumber();
38 Value yieldedValue = cast<scf::YieldOp>(forOp.getBody()->getTerminator())
39 .getOperand(iterArgIdx);
40 Value iterArg = forOp.getRegionIterArg(iterArgIdx);
41 Value initArg = forOp.getInitArgs()[iterArgIdx];
43 auto addEqBound = [&]() {
44 if (dim.has_value()) {
47 cstr.
bound(value) == initArg;
51 if (yieldedValue == iterArg) {
60 bound, boundOperands, BoundType::EQ, yieldedValue, dim,
61 [&](
Value v, std::optional<int64_t> d) {
63 if (
auto bbArg = llvm::dyn_cast<BlockArgument>(v))
64 return bbArg.getOwner()->getParentOp() == forOp;
76 Value singleValue =
nullptr;
77 std::optional<int64_t> singleDim;
78 if (
auto dimExpr = dyn_cast<AffineDimExpr>(bound.
getResult(0))) {
79 int64_t idx = dimExpr.getPosition();
80 singleValue = boundOperands[idx].first;
81 singleDim = boundOperands[idx].second;
82 }
else if (
auto symExpr = dyn_cast<AffineSymbolExpr>(bound.
getResult(0))) {
83 int64_t idx = symExpr.getPosition() + bound.
getNumDims();
84 singleValue = boundOperands[idx].first;
85 singleDim = boundOperands[idx].second;
87 if (singleValue == iterArg && singleDim == dim)
93 auto forOp = cast<ForOp>(op);
95 if (value == forOp.getInductionVar()) {
97 cstr.
bound(value) >= forOp.getLowerBound();
98 cstr.
bound(value) < forOp.getUpperBound();
103 populateIterArgBounds(forOp, value, std::nullopt, cstr);
106 void populateBoundsForShapedValueDim(
Operation *op,
Value value, int64_t dim,
108 auto forOp = cast<ForOp>(op);
110 populateIterArgBounds(forOp, value, dim, cstr);
121 scf::ForOp::attachInterface<scf::ForOpInterface>(*ctx);
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
unsigned getNumDims() const
unsigned getNumResults() const
AffineExpr getResult(unsigned idx) const
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
void addExtension(std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
MLIRContext is the top-level object for a collection of MLIR operations.
Operation is the basic unit of execution within MLIR.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Operation * findAncestorOpInRegion(Operation &op)
Returns 'op' if 'op' lies in this region, or otherwise finds the ancestor of 'op' that lies in this r...
A helper class to be used with ValueBoundsOpInterface.
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.
static LogicalResult computeBound(AffineMap &resultMap, ValueDimList &mapOperands, presburger::BoundType type, Value value, std::optional< int64_t > dim, StopConditionFn stopCondition, bool closedUB=false)
Compute a bound for the given index-typed value or shape dimension size.
BoundBuilder bound(Value value)
Add a bound for the given index-typed value or shaped value.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
BoundType
The type of bound: equal, lower bound or upper bound.
void registerValueBoundsOpInterfaceExternalModels(DialectRegistry ®istry)
Include the generated interface declarations.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class represents an efficient way to signal success or failure.