MLIR 23.0.0git
Transforms.h
Go to the documentation of this file.
1//===- Transforms.h - Transforms Entrypoints --------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This header file defines a set of transforms specific for the AffineOps
10// dialect.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef MLIR_DIALECT_AFFINE_TRANSFORMS_TRANSFORMS_H
15#define MLIR_DIALECT_AFFINE_TRANSFORMS_TRANSFORMS_H
16
18#include "mlir/Support/LLVM.h"
19
20namespace mlir {
21class AffineMap;
22class Location;
23class OpBuilder;
24class OpFoldResult;
26class RewriterBase;
27class Value;
28
29namespace presburger {
30enum class BoundType;
31} // namespace presburger
32
33namespace affine {
34class AffineApplyOp;
35class AffineDelinearizeIndexOp;
36class AffineLinearizeIndexOp;
37class AffineMaxOp;
38class AffineMinOp;
39
40/// Lowers `affine.delinearize_index` into a sequence of division and remainder
41/// operations.
42LogicalResult lowerAffineDelinearizeIndexOp(RewriterBase &rewriter,
43 AffineDelinearizeIndexOp op);
44
45/// Lowers `affine.linearize_index` into a sequence of multiplications and
46/// additions. Make a best effort to sort the input indices so that
47/// the most loop-invariant terms are at the left of the additions
48/// to enable loop-invariant code motion.
49LogicalResult lowerAffineLinearizeIndexOp(RewriterBase &rewriter,
50 AffineLinearizeIndexOp op);
51
52/// Populate patterns that simplify `affine.delinearize_index` /
53/// `affine.linearize_index` pairs using value bounds analysis.
54void populateSimplifyAffineWithBoundsPatterns(RewritePatternSet &patterns);
55
56/// Populate patterns that expand affine index operations into more fundamental
57/// operations (not necessarily restricted to Affine dialect).
58void populateAffineExpandIndexOpsPatterns(RewritePatternSet &patterns);
59
60/// Populate patterns that expand affine index operations into their equivalent
61/// `affine.apply` representations.
62void populateAffineExpandIndexOpsAsAffinePatterns(RewritePatternSet &patterns);
63
64/// Helper function to rewrite `op`'s affine map and reorder its operands such
65/// that they are in increasing order of hoistability (i.e. the least hoistable)
66/// operands come first in the operand list.
67void reorderOperandsByHoistability(RewriterBase &rewriter, AffineApplyOp op);
68
69/// Split an "affine.apply" operation into smaller ops.
70/// This reassociates a large AffineApplyOp into an ordered list of smaller
71/// AffineApplyOps. This can be used right before lowering affine ops to arith
72/// to exhibit more opportunities for CSE and LICM.
73/// Return the sink AffineApplyOp on success or failure if `op` does not
74/// decompose into smaller AffineApplyOps.
75/// Note that this can be undone by canonicalization which tries to
76/// maximally compose chains of AffineApplyOps.
77FailureOr<AffineApplyOp> decompose(RewriterBase &rewriter, AffineApplyOp op);
78
79/// Reify a bound for the given variable in terms of SSA values for which
80/// `stopCondition` is met.
81///
82/// By default, lower/equal bounds are closed and upper bounds are open. If
83/// `closedUB` is set to "true", upper bounds are also closed.
84FailureOr<OpFoldResult>
85reifyValueBound(OpBuilder &b, Location loc, presburger::BoundType type,
86 const ValueBoundsConstraintSet::Variable &var,
88 bool closedUB = false);
89
90/// Reify a bound for the given index-typed value in terms of SSA values for
91/// which `stopCondition` is met. If no stop condition is specified, reify in
92/// terms of the operands of the owner op.
93///
94/// By default, lower/equal bounds are closed and upper bounds are open. If
95/// `closedUB` is set to "true", upper bounds are also closed.
96///
97/// Example:
98/// %0 = arith.addi %a, %b : index
99/// %1 = arith.addi %0, %c : index
100///
101/// * If `stopCondition` evaluates to "true" for %0 and %c, "%0 + %c" is an EQ
102/// bound for %1.
103/// * If `stopCondition` evaluates to "true" for %a, %b and %c, "%a + %b + %c"
104/// is an EQ bound for %1.
105/// * Otherwise, if the owners of %a, %b or %c do not implement the
106/// ValueBoundsOpInterface, no bound can be computed.
107FailureOr<OpFoldResult> reifyIndexValueBound(
108 OpBuilder &b, Location loc, presburger::BoundType type, Value value,
109 ValueBoundsConstraintSet::StopConditionFn stopCondition = nullptr,
110 bool closedUB = false);
111
112/// Reify a bound for the specified dimension of the given shaped value in terms
113/// of SSA values for which `stopCondition` is met. If no stop condition is
114/// specified, reify in terms of the operands of the owner op.
115///
116/// By default, lower/equal bounds are closed and upper bounds are open. If
117/// `closedUB` is set to "true", upper bounds are also closed.
118FailureOr<OpFoldResult> reifyShapedValueDimBound(
119 OpBuilder &b, Location loc, presburger::BoundType type, Value value,
120 int64_t dim,
121 ValueBoundsConstraintSet::StopConditionFn stopCondition = nullptr,
122 bool closedUB = false);
123
124/// Materialize an already computed bound with Affine dialect ops.
125///
126/// * `ValueBoundsOpInterface::computeBound` computes bounds but does not
127/// create IR. It is dialect independent.
128/// * `materializeComputedBound` materializes computed bounds with Affine
129/// dialect ops.
130/// * `reifyIndexValueBound`/`reifyShapedValueDimBound` are a combination of
131/// the two functions mentioned above.
132OpFoldResult materializeComputedBound(
133 OpBuilder &b, Location loc, AffineMap boundMap,
134 ArrayRef<std::pair<Value, std::optional<int64_t>>> mapOperands);
135
136/// This transform tries to simplify the affine min operation `op`, by finding a
137/// common lower bound for a set of expressions in the affine map results. It
138/// returns whether the transform updated `op`'s affine map.
139///
140/// In concrete terms, given an operation like:
141/// `affine.min affine_map<(d0)[s0, s1] -> (d0, s1, s0, 128)>(%i)[%s0, %s1]`
142/// If `d0 < 128` and `128 < s1 < s0`, the transform will update `op` to:
143/// `affine.min affine_map<(d0)[s0, s1] -> (d0, 128)>(%i)[%s0, %s1]`.
144bool simplifyAffineMinOp(RewriterBase &rewriter, AffineMinOp op);
145
146/// This transform tries to simplify the affine max operation `op`, by finding a
147/// common upper bound for a set of expressions in the affine map results. It
148/// returns whether the transform updated `op`'s affine map.
149///
150/// In concrete terms, given an operation like:
151/// `affine.max affine_map<(d0)[s0, s1] -> (d0, s1, s0, 128)>(%i)[%s0, %s1]`
152/// If `d0 > 128` and `s0 > s1 > 128`, the transform will update `op` to:
153/// `affine.max affine_map<(d0)[s0, s1] -> (d0, s0)>(%i)[%s0, %s1]`.
154bool simplifyAffineMaxOp(RewriterBase &rewriter, AffineMaxOp op);
155
156/// This transform applies `simplifyAffineMinOp` and `simplifyAffineMaxOp` to
157/// all the `affine.min` or `affine.max` operations in `ops`. After
158/// simplification, it invokes the `affine.min/max` canonicalization patterns on
159/// `ops`.
160///
161/// This transform returns failure if the greedy pattern rewriter failed to
162/// converge during canonicalization, otherwise it returns success. If provided,
163/// `modified` is set to `true` if the IR was modified in any way.
164LogicalResult simplifyAffineMinMaxOps(RewriterBase &rewriter,
165 ArrayRef<Operation *> ops,
166 bool *modified = nullptr);
167} // namespace affine
168} // namespace mlir
169
170#endif // MLIR_DIALECT_AFFINE_TRANSFORMS_TRANSFORMS_H
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition AffineMap.h:46
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
This class helps build Operations.
Definition Builders.h:209
This class represents a single result from folding an operation.
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
std::function< bool( Value, std::optional< int64_t >, ValueBoundsConstraintSet &cstr)> StopConditionFn
The stop condition when traversing the backward slice of a shaped value/ index-type value.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
bool simplifyAffineMaxOp(RewriterBase &rewriter, AffineMaxOp op)
This transform tries to simplify the affine max operation op, by finding a common upper bound for a s...
FailureOr< OpFoldResult > reifyValueBound(OpBuilder &b, Location loc, presburger::BoundType type, const ValueBoundsConstraintSet::Variable &var, ValueBoundsConstraintSet::StopConditionFn stopCondition, bool closedUB=false)
Reify a bound for the given variable in terms of SSA values for which stopCondition is met.
LogicalResult lowerAffineDelinearizeIndexOp(RewriterBase &rewriter, AffineDelinearizeIndexOp op)
Lowers affine.delinearize_index into a sequence of division and remainder operations.
FailureOr< OpFoldResult > reifyIndexValueBound(OpBuilder &b, Location loc, presburger::BoundType type, Value value, ValueBoundsConstraintSet::StopConditionFn stopCondition=nullptr, bool closedUB=false)
Reify a bound for the given index-typed value in terms of SSA values for which stopCondition is met.
FailureOr< AffineApplyOp > decompose(RewriterBase &rewriter, AffineApplyOp op)
Split an "affine.apply" operation into smaller ops.
LogicalResult lowerAffineLinearizeIndexOp(RewriterBase &rewriter, AffineLinearizeIndexOp op)
Lowers affine.linearize_index into a sequence of multiplications and additions.
OpFoldResult materializeComputedBound(OpBuilder &b, Location loc, AffineMap boundMap, ArrayRef< std::pair< Value, std::optional< int64_t > > > mapOperands)
Materialize an already computed bound with Affine dialect ops.
bool simplifyAffineMinOp(RewriterBase &rewriter, AffineMinOp op)
This transform tries to simplify the affine min operation op, by finding a common lower bound for a s...
LogicalResult simplifyAffineMinMaxOps(RewriterBase &rewriter, ArrayRef< Operation * > ops, bool *modified=nullptr)
This transform applies simplifyAffineMinOp and simplifyAffineMaxOp to all the affine....
void populateAffineExpandIndexOpsPatterns(RewritePatternSet &patterns)
Populate patterns that expand affine index operations into more fundamental operations (not necessari...
void populateSimplifyAffineWithBoundsPatterns(RewritePatternSet &patterns)
Populate patterns that simplify affine.delinearize_index / affine.linearize_index pairs using value b...
FailureOr< OpFoldResult > reifyShapedValueDimBound(OpBuilder &b, Location loc, presburger::BoundType type, Value value, int64_t dim, ValueBoundsConstraintSet::StopConditionFn stopCondition=nullptr, bool closedUB=false)
Reify a bound for the specified dimension of the given shaped value in terms of SSA values for which ...
void reorderOperandsByHoistability(RewriterBase &rewriter, AffineApplyOp op)
Helper function to rewrite op's affine map and reorder its operands such that they are in increasing ...
void populateAffineExpandIndexOpsAsAffinePatterns(RewritePatternSet &patterns)
Populate patterns that expand affine index operations into their equivalent affine....
BoundType
The type of bound: equal, lower bound or upper bound.
Include the generated interface declarations.