1#ifndef HALIDE_IR_MUTATOR_H
2#define HALIDE_IR_MUTATOR_H
45 std::vector<Expr>
mutate(
const std::vector<Expr> &exprs) {
122template<
typename... Lambdas>
125 : handlers(std::move(lambdas)...) {
138 auto visit_impl(
const T *op) {
139 if constexpr (std::is_invocable_v<
decltype(handlers),
LambdaMutator *,
const T *>) {
140 return handlers(
this, op);
148 return this->visit_impl(op);
151 return this->visit_impl(op);
154 return this->visit_impl(op);
157 return this->visit_impl(op);
160 return this->visit_impl(op);
163 return this->visit_impl(op);
166 return this->visit_impl(op);
169 return this->visit_impl(op);
172 return this->visit_impl(op);
175 return this->visit_impl(op);
178 return this->visit_impl(op);
181 return this->visit_impl(op);
184 return this->visit_impl(op);
187 return this->visit_impl(op);
190 return this->visit_impl(op);
193 return this->visit_impl(op);
196 return this->visit_impl(op);
199 return this->visit_impl(op);
202 return this->visit_impl(op);
205 return this->visit_impl(op);
208 return this->visit_impl(op);
211 return this->visit_impl(op);
214 return this->visit_impl(op);
217 return this->visit_impl(op);
220 return this->visit_impl(op);
223 return this->visit_impl(op);
226 return this->visit_impl(op);
229 return this->visit_impl(op);
232 return this->visit_impl(op);
235 return this->visit_impl(op);
238 return this->visit_impl(op);
241 return this->visit_impl(op);
244 return this->visit_impl(op);
247 return this->visit_impl(op);
250 return this->visit_impl(op);
253 return this->visit_impl(op);
256 return this->visit_impl(op);
259 return this->visit_impl(op);
262 return this->visit_impl(op);
265 return this->visit_impl(op);
268 return this->visit_impl(op);
271 return this->visit_impl(op);
274 return this->visit_impl(op);
277 return this->visit_impl(op);
280 return this->visit_impl(op);
283 return this->visit_impl(op);
286 return this->visit_impl(op);
289 return this->visit_impl(op);
295template<
typename... Lambdas>
298 : handlers(std::move(lambdas)...) {
312 return handlers(
this, e);
320 return handlers(
this, e);
330template<
typename T,
typename... Lambdas>
334 if constexpr (std::is_invocable_v<Overloads, Generic *, const Expr &> ||
335 std::is_invocable_v<Overloads, Generic *, const Stmt &>) {
339 constexpr bool all_take_two_args =
340 (std::is_invocable_v<Lambdas,
decltype(&mutator),
decltype(
nullptr)> && ...);
341 static_assert(all_take_two_args);
342 return mutator.
mutate(ir);
347template<
typename Mutator,
typename... Args>
349 Region new_bounds(bounds.size());
350 bool bounds_changed =
false;
352 for (
size_t i = 0; i < bounds.size(); i++) {
353 Expr old_min = bounds[i].min;
354 Expr old_extent = bounds[i].extent;
355 Expr new_min = mutator->mutate(old_min, args...);
356 Expr new_extent = mutator->mutate(old_extent, args...);
357 if (!new_min.
same_as(old_min)) {
358 bounds_changed =
true;
360 if (!new_extent.
same_as(old_extent)) {
361 bounds_changed =
true;
363 new_bounds[i] =
Range(new_min, new_extent);
365 return {new_bounds, bounds_changed};
Subtypes for Halide expressions (Halide::Expr) and statements (Halide::Internal::Stmt)
A mutator that caches and reapplies previously done mutations so that it can handle graphs of IR that...
std::map< Expr, Expr, ExprCompare > expr_replacements
Expr mutate(const Expr &e) override
This is the main interface for using a mutator.
Stmt mutate(const Stmt &s) override
std::map< Stmt, Stmt, Stmt::Compare > stmt_replacements
A base class for passes over the IR which modify it (e.g.
std::vector< Expr > mutate(const std::vector< Expr > &exprs)
virtual Stmt visit(const Free *)
virtual Expr visit(const Broadcast *)
virtual Expr visit(const VectorReduce *)
virtual Expr visit(const Call *)
virtual Stmt visit(const Atomic *)
virtual Expr visit(const Let *)
virtual Stmt visit(const Provide *)
virtual Expr visit(const Ramp *)
virtual Expr visit(const Mod *)
virtual Expr visit(const LE *)
virtual Expr visit(const Reinterpret *)
virtual Stmt visit(const Store *)
virtual Expr visit(const Max *)
virtual Stmt visit(const HoistedStorage *)
virtual Expr visit(const Cast *)
virtual Stmt mutate(const Stmt &stmt)
virtual Stmt visit(const Block *)
virtual Expr visit(const Load *)
virtual Stmt visit(const Fork *)
virtual Stmt visit(const Allocate *)
virtual Stmt visit(const LetStmt *)
virtual Expr visit(const Or *)
virtual Expr visit(const And *)
virtual Stmt visit(const Acquire *)
std::pair< std::vector< Expr >, bool > mutate_with_changes(const std::vector< Expr > &)
virtual Stmt visit(const ProducerConsumer *)
virtual Expr visit(const Variable *)
virtual Expr visit(const Shuffle *)
virtual Expr visit(const LT *)
virtual Stmt visit(const For *)
virtual ~IRMutator()=default
virtual Expr visit(const Min *)
virtual Stmt visit(const AssertStmt *)
virtual Expr visit(const EQ *)
virtual Expr visit(const GT *)
virtual Expr visit(const Not *)
virtual Expr visit(const Add *)
virtual Expr visit(const NE *)
virtual Expr visit(const Div *)
virtual Expr visit(const Sub *)
virtual Stmt visit(const Evaluate *)
virtual Stmt visit(const Prefetch *)
virtual Stmt visit(const Realize *)
virtual Expr visit(const IntImm *)
virtual Expr mutate(const Expr &expr)
This is the main interface for using a mutator.
virtual Expr visit(const GE *)
virtual Expr visit(const UIntImm *)
virtual Stmt visit(const IfThenElse *)
virtual Expr visit(const FloatImm *)
virtual Expr visit(const Select *)
virtual Expr visit(const Mul *)
virtual Expr visit(const StringImm *)
auto mutate_with(const T &ir, Lambdas &&...lambdas)
std::pair< Region, bool > mutate_region(Mutator *mutator, const Region &bounds, Args &&...args)
A helper function for mutator-like things to mutate regions.
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
std::vector< Range > Region
A multi-dimensional box.
A fragment of Halide syntax.
The sum of two expressions.
Allocate a scratch area called with the given name, type, and size.
Logical and - are both expressions true.
If the 'condition' is false, then evaluate and return the message, which should be a call to an error...
Lock all the Store nodes in the body statement.
A sequence of statements to be executed in-order.
A vector with 'lanes' elements, in which every element is 'value'.
The actual IR nodes begin here.
The ratio of two expressions.
Is the first expression equal to the second.
Evaluate and discard an expression, presumably because it has some side-effect.
We use the "curiously recurring template pattern" to avoid duplicated code in the IR Nodes.
Floating point constants.
A pair of statements executed concurrently.
Free the resources associated with the given buffer.
Is the first expression greater than or equal to the second.
Is the first expression greater than the second.
Represents a location where storage will be hoisted to for a Func / Realize node with a given name.
HALIDE_ALWAYS_INLINE bool same_as(const IntrusivePtr &other) const
Is the first expression less than or equal to the second.
Is the first expression less than the second.
A lambda-based IR mutator that accepts multiple lambdas for overloading the base mutate() method.
LambdaMutatorGeneric(Lambdas... lambdas)
auto mutate_base(const T &op)
Public helper to call the base mutator from lambdas.
Stmt mutate(const Stmt &e) override
Expr mutate(const Expr &e) override
This is the main interface for using a mutator.
A lambda-based IR mutator that accepts multiple lambdas for different node types.
Expr visit(const UIntImm *op) override
Stmt visit(const Block *op) override
Expr visit(const Shuffle *op) override
Expr visit(const Call *op) override
Expr visit(const Cast *op) override
Expr visit(const And *op) override
Stmt visit(const Acquire *op) override
LambdaMutator(Lambdas... lambdas)
Expr visit(const Max *op) override
Stmt visit(const Atomic *op) override
Stmt visit(const HoistedStorage *op) override
Stmt visit(const Evaluate *op) override
Stmt visit(const Allocate *op) override
Expr visit(const Load *op) override
Stmt visit(const Provide *op) override
Stmt visit(const Realize *op) override
Expr visit(const Reinterpret *op) override
Expr visit(const NE *op) override
Expr visit(const GE *op) override
Expr visit(const GT *op) override
Expr visit(const Not *op) override
Expr visit(const Variable *op) override
Expr visit(const VectorReduce *op) override
Stmt visit(const Prefetch *op) override
Expr visit(const Sub *op) override
Stmt visit(const Fork *op) override
Stmt visit(const Store *op) override
Expr visit(const LE *op) override
Stmt visit(const LetStmt *op) override
Expr visit(const Ramp *op) override
Expr visit(const FloatImm *op) override
Stmt visit(const Free *op) override
Expr visit(const Min *op) override
Expr visit(const IntImm *op) override
Stmt visit(const IfThenElse *op) override
Stmt visit(const For *op) override
Stmt visit(const ProducerConsumer *op) override
Stmt visit(const AssertStmt *op) override
Expr visit(const EQ *op) override
Expr visit(const Mul *op) override
Expr visit(const Or *op) override
Expr visit(const Select *op) override
auto visit_base(const T *op)
Public helper to call the base visitor from lambdas.
Expr visit(const Mod *op) override
Expr visit(const Div *op) override
Expr visit(const Add *op) override
Expr visit(const Broadcast *op) override
Expr visit(const LT *op) override
Expr visit(const Let *op) override
Expr visit(const StringImm *op) override
A let expression, like you might find in a functional language.
The statement form of a let node.
Load a value from a named symbol if predicate is true.
The greater of two values.
The lesser of two values.
The product of two expressions.
Is the first expression not equal to the second.
Logical not - true if the expression false.
Logical or - is at least one of the expression true.
Represent a multi-dimensional region of a Func or an ImageParam that needs to be prefetched.
This node is a helpful annotation to do with permissions.
This defines the value of a function at a multi-dimensional location.
A linear ramp vector node.
Allocate a multi-dimensional buffer of the given type and size.
Reinterpret value as another type, without affecting any of the bits (on little-endian systems).
Construct a new vector by taking elements from another sequence of vectors.
A reference-counted handle to a statement node.
Store a 'value' to the buffer called 'name' at a given 'index' if 'predicate' is true.
The difference of two expressions.
Unsigned integer constants.
Horizontally reduce a vector to a scalar or narrower vector using the given commutative and associati...
A single-dimensional span.