28 if (getLowerBounds().size() != getBoundedValues().size())
29 return emitOpError() <<
"incorrect number of lower bounds, expected "
30 << getBoundedValues().size() <<
" but found "
31 << getLowerBounds().size();
32 if (getUpperBounds().size() != getBoundedValues().size())
33 return emitOpError() <<
"incorrect number of upper bounds, expected "
34 << getBoundedValues().size() <<
" but found "
35 << getUpperBounds().size();
42 template <
typename OpTy>
50 LogicalResult matchAndRewrite(OpTy op,
52 FailureOr<AffineValueMap> simplified =
54 if (failed(simplified))
57 simplified->getOperands());
74 for (
const auto &it : llvm::zip_equal(getBoundedValues(), getLowerBounds(),
76 Value handle = std::get<0>(it);
77 for (
Operation *op : state.getPayloadOps(handle)) {
78 if (op->getNumResults() != 1 || !op->getResult(0).getType().isIndex()) {
81 <<
"expected bounded value handle to point to one or multiple "
82 "single-result index-typed ops";
83 diag.attachNote(op->getLoc()) <<
"multiple/non-index result";
86 boundedValues.push_back(op->getResult(0));
87 boundedOps.insert(op);
88 lbs.push_back(std::get<1>(it));
89 ubs.push_back(std::get<2>(it));
95 for (
const auto &it : llvm::zip(boundedValues, lbs, ubs)) {
97 if (!cstr.
findVar(std::get<0>(it), &pos))
106 for (
Operation *target : state.getPayloadOps(getTarget())) {
107 if (!isa<AffineMinOp, AffineMaxOp>(target)) {
109 <<
"target must be affine.min or affine.max";
110 diag.attachNote(target->getLoc()) <<
"target op";
113 if (boundedOps.contains(target)) {
115 <<
"target op result must not be constrainted";
116 diag.attachNote(target->getLoc()) <<
"target/constrained op";
119 targets.push_back(target);
125 AffineMaxOp::getCanonicalizationPatterns(patterns,
getContext());
126 AffineMinOp::getCanonicalizationPatterns(patterns,
getContext());
127 patterns.insert<SimplifyAffineMinMaxOp<AffineMinOp>,
128 SimplifyAffineMinMaxOp<AffineMaxOp>>(
getContext(), cstr);
137 <<
"affine.min/max simplification did not converge";
143 void SimplifyBoundedAffineOpsOp::getEffects(
146 for (
OpOperand &operand : getBoundedValuesMutable())
156 class AffineTransformDialectExtension
158 AffineTransformDialectExtension> {
165 declareGeneratedDialect<AffineDialect>();
167 registerTransformOps<
169 #include "mlir/Dialect/Affine/TransformOps/AffineTransformOps.cpp.inc"
175 #define GET_OP_CLASSES
176 #include "mlir/Dialect/Affine/TransformOps/AffineTransformOps.cpp.inc"
static MLIRContext * getContext(OpFoldResult val)
static std::string diag(const llvm::Value &value)
#define MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CLASS_NAME)
The result of a transform IR operation application.
static DiagnosedSilenceableFailure success()
Constructs a DiagnosedSilenceableFailure in the success state.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
void addExtensions()
Add the given extensions to the registry.
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...
unsigned appendSymbolVar(ValueRange vals)
This class represents a frozen set of patterns that can be processed by a pattern applicator.
This class allows control over how the GreedyPatternRewriteDriver works.
GreedyRewriteStrictness strictMode
Strict mode can restrict the ops that are added to the worklist during the rewrite.
RewriterBase::Listener * listener
An optional listener that should be notified about IR modifications.
MLIRContext is the top-level object for a collection of MLIR operations.
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
This class represents an operand of an operation.
Operation is the basic unit of execution within MLIR.
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
FlatAffineValueConstraints is an extension of FlatLinearValueConstraints with helper functions for Af...
LogicalResult addBound(presburger::BoundType type, unsigned pos, AffineMap boundMap, ValueRange operands)
Adds a bound for the variable at the specified position with constraints being drawn from the specifi...
Base class for extensions of the Transform dialect that supports injecting operations into the Transf...
void registerTransformDialectExtension(DialectRegistry ®istry)
FailureOr< AffineValueMap > simplifyConstrainedMinMaxOp(Operation *op, FlatAffineValueConstraints constraints)
Try to simplify the given affine.min or affine.max op to an affine map with a single result and opera...
Include the generated interface declarations.
LogicalResult applyOpPatternsAndFold(ArrayRef< Operation * > ops, const FrozenRewritePatternSet &patterns, GreedyRewriteConfig config=GreedyRewriteConfig(), bool *changed=nullptr, bool *allErased=nullptr)
Rewrite the specified ops by repeatedly applying the highest benefit patterns in a greedy worklist dr...
DiagnosedDefiniteFailure emitDefiniteFailure(Location loc, const Twine &message={})
Emits a definite failure with the given message.
@ ExistingAndNewOps
Only pre-existing and newly created ops are processed.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...