Halide  17.0.2
Halide compiler and libraries
Function.h
Go to the documentation of this file.
1 #ifndef HALIDE_FUNCTION_H
2 #define HALIDE_FUNCTION_H
3 
4 /** \file
5  * Defines the internal representation of a halide function and related classes
6  */
7 #include <map>
8 #include <string>
9 #include <utility>
10 #include <vector>
11 
12 #include "Definition.h"
13 #include "Expr.h"
14 #include "FunctionPtr.h"
15 #include "Schedule.h"
16 
17 namespace Halide {
18 
19 struct ExternFuncArgument;
20 class Parameter;
21 class Tuple;
22 class Var;
23 
24 /** An enum to specify calling convention for extern stages. */
25 enum class NameMangling {
26  Default, ///< Match whatever is specified in the Target
27  C, ///< No name mangling
28  CPlusPlus, ///< C++ name mangling
29 };
30 
31 namespace Internal {
32 
33 struct Call;
34 
35 /** A reference-counted handle to Halide's internal representation of
36  * a function. Similar to a front-end Func object, but with no
37  * syntactic sugar to help with definitions. */
38 class Function {
39  FunctionPtr contents;
40 
41 public:
42  /** This lets you use a Function as a key in a map of the form
43  * map<Function, Foo, Function::Compare> */
44  struct Compare {
45  bool operator()(const Function &a, const Function &b) const {
46  internal_assert(a.contents.defined() && b.contents.defined());
47  return a.contents < b.contents;
48  }
49  };
50 
51  /** Construct a new function with no definitions and no name. This
52  * constructor only exists so that you can make vectors of
53  * functions, etc.
54  */
55  Function() = default;
56 
57  /** Construct a new function with the given name */
58  explicit Function(const std::string &n);
59 
60  /** Construct a new function with the given name,
61  * with a requirement that it can only represent Expr(s) of the given type(s),
62  * and must have exactly the give nnumber of dimensions.
63  * required_types.empty() means there are no constraints on the type(s).
64  * required_dims == AnyDims means there are no constraints on the dimensions. */
65  explicit Function(const std::vector<Type> &required_types, int required_dims, const std::string &n);
66 
67  /** Construct a Function from an existing FunctionContents pointer. Must be non-null */
68  explicit Function(const FunctionPtr &);
69 
70  /** Update a function with deserialized data */
71  void update_with_deserialization(const std::string &name,
72  const std::string &origin_name,
73  const std::vector<Halide::Type> &output_types,
74  const std::vector<Halide::Type> &required_types,
75  int required_dims,
76  const std::vector<std::string> &args,
77  const FuncSchedule &func_schedule,
78  const Definition &init_def,
79  const std::vector<Definition> &updates,
80  const std::string &debug_file,
81  const std::vector<Parameter> &output_buffers,
82  const std::vector<ExternFuncArgument> &extern_arguments,
83  const std::string &extern_function_name,
84  NameMangling name_mangling,
85  DeviceAPI device_api,
86  const Expr &extern_proxy_expr,
87  bool trace_loads,
88  bool trace_stores,
89  bool trace_realizations,
90  const std::vector<std::string> &trace_tags,
91  bool frozen);
92 
93  /** Get a handle on the halide function contents that this Function
94  * represents. */
96  return contents;
97  }
98 
99  /** Deep copy this Function into 'copy'. It recursively deep copies all called
100  * functions, schedules, update definitions, extern func arguments, specializations,
101  * and reduction domains. This method does not deep-copy the Parameter objects.
102  * This method also takes a map of <old Function, deep-copied version> as input
103  * and would use the deep-copied Function from the map if exists instead of
104  * creating a new deep-copy to avoid creating deep-copies of the same Function
105  * multiple times. If 'name' is specified, copy's name will be set to that.
106  */
107  // @{
108  void deep_copy(const FunctionPtr &copy, std::map<FunctionPtr, FunctionPtr> &copied_map) const;
109  void deep_copy(std::string name, const FunctionPtr &copy,
110  std::map<FunctionPtr, FunctionPtr> &copied_map) const;
111  // @}
112 
113  /** Add a pure definition to this function. It may not already
114  * have a definition. All the free variables in 'value' must
115  * appear in the args list. 'value' must not depend on any
116  * reduction domain */
117  void define(const std::vector<std::string> &args, std::vector<Expr> values);
118 
119  /** Add an update definition to this function. It must already
120  * have a pure definition but not an update definition, and the
121  * length of args must match the length of args used in the pure
122  * definition. 'value' must depend on some reduction domain, and
123  * may contain variables from that domain as well as pure
124  * variables. Any pure variables must also appear as Variables in
125  * the args array, and they must have the same name as the pure
126  * definition's argument in the same index. */
127  void define_update(const std::vector<Expr> &args, std::vector<Expr> values);
128 
129  /** Accept a visitor to visit all of the definitions and arguments
130  * of this function. */
131  void accept(IRVisitor *visitor) const;
132 
133  /** Accept a mutator to mutator all of the definitions and
134  * arguments of this function. */
135  void mutate(IRMutator *mutator);
136 
137  /** Get the name of the function. */
138  const std::string &name() const;
139 
140  /** If this is a wrapper of another func, created by a chain of in
141  * or clone_in calls, returns the name of the original
142  * Func. Otherwise returns the name. */
143  const std::string &origin_name() const;
144 
145  /** Get a mutable handle to the init definition. */
147 
148  /** Get the init definition. */
149  const Definition &definition() const;
150 
151  /** Get the pure arguments. */
152  const std::vector<std::string> &args() const;
153 
154  /** Get the dimensionality. */
155  int dimensions() const;
156 
157  /** Get the number of outputs. */
158  int outputs() const;
159 
160  /** Get the types of the outputs. */
161  const std::vector<Type> &output_types() const;
162 
163  /** Get the type constaints on the outputs (if any). */
164  const std::vector<Type> &required_types() const;
165 
166  /** Get the dimensionality constaints on the outputs (if any). */
167  int required_dimensions() const;
168 
169  /** Get the right-hand-side of the pure definition. Returns an
170  * empty vector if there is no pure definition.
171  *
172  * Warning: Any Vars in the Exprs are not qualified with the Func name, so
173  * the Exprs may contain names which collide with names provided by
174  * unique_name.
175  */
176  const std::vector<Expr> &values() const;
177 
178  /** Does this function have a pure definition? */
179  bool has_pure_definition() const;
180 
181  /** Does this function *only* have a pure definition? */
182  bool is_pure() const {
183  return (has_pure_definition() &&
186  }
187 
188  /** Is it legal to inline this function? */
189  bool can_be_inlined() const;
190 
191  /** Get a handle to the function-specific schedule for the purpose
192  * of modifying it. */
194 
195  /** Get a const handle to the function-specific schedule for inspecting it. */
196  const FuncSchedule &schedule() const;
197 
198  /** Get a handle on the output buffer used for setting constraints
199  * on it. */
200  const std::vector<Parameter> &output_buffers() const;
201 
202  /** Get a mutable handle to the stage-specfic schedule for the update
203  * stage. */
204  StageSchedule &update_schedule(int idx = 0);
205 
206  /** Get a mutable handle to this function's update definition at
207  * index 'idx'. */
208  Definition &update(int idx = 0);
209 
210  /** Get a const reference to this function's update definition at
211  * index 'idx'. */
212  const Definition &update(int idx = 0) const;
213 
214  /** Get a const reference to this function's update definitions. */
215  const std::vector<Definition> &updates() const;
216 
217  /** Does this function have an update definition? */
218  bool has_update_definition() const;
219 
220  /** Check if the function has an extern definition. */
221  bool has_extern_definition() const;
222 
223  /** Get the name mangling specified for the extern definition. */
225 
226  /** Make a call node to the extern definition. An error if the
227  * function has no extern definition. */
228  Expr make_call_to_extern_definition(const std::vector<Expr> &args,
229  const Target &t) const;
230 
231  /** Get the proxy Expr for the extern stage. This is an expression
232  * known to have the same data access pattern as the extern
233  * stage. It must touch at least all of the memory that the extern
234  * stage does, though it is permissible for it to be conservative
235  * and touch a superset. For most Functions, including those with
236  * extern definitions, this will be an undefined Expr. */
237  // @{
240  // @}
241 
242  /** Add an external definition of this Func. */
243  void define_extern(const std::string &function_name,
244  const std::vector<ExternFuncArgument> &args,
245  const std::vector<Type> &types,
246  const std::vector<Var> &dims,
247  NameMangling mangling, DeviceAPI device_api);
248 
249  /** Retrive the arguments of the extern definition. */
250  // @{
251  const std::vector<ExternFuncArgument> &extern_arguments() const;
252  std::vector<ExternFuncArgument> &extern_arguments();
253  // @}
254 
255  /** Get the name of the extern function called for an extern
256  * definition. */
257  const std::string &extern_function_name() const;
258 
259  /** Get the DeviceAPI declared for an extern function. */
261 
262  /** Test for equality of identity. */
263  bool same_as(const Function &other) const {
264  return contents.same_as(other.contents);
265  }
266 
267  /** Get a const handle to the debug filename. */
268  const std::string &debug_file() const;
269 
270  /** Get a handle to the debug filename. */
271  std::string &debug_file();
272 
273  /** Use an an extern argument to another function. */
274  operator ExternFuncArgument() const;
275 
276  /** Tracing calls and accessors, passed down from the Func
277  * equivalents. */
278  // @{
279  void trace_loads();
280  void trace_stores();
281  void trace_realizations();
282  void add_trace_tag(const std::string &trace_tag);
283  bool is_tracing_loads() const;
284  bool is_tracing_stores() const;
285  bool is_tracing_realizations() const;
286  const std::vector<std::string> &get_trace_tags() const;
287  // @}
288 
289  /** Replace this Function's LoopLevels with locked copies that
290  * cannot be mutated further. */
291  void lock_loop_levels();
292 
293  /** Mark function as frozen, which means it cannot accept new
294  * definitions. */
295  void freeze();
296 
297  /** Check if a function has been frozen. If so, it is an error to
298  * add new definitions. */
299  bool frozen() const;
300 
301  /** Make a new Function with the same lifetime as this one, and
302  * return a strong reference to it. Useful to create Functions which
303  * have circular references to this one - e.g. the wrappers
304  * produced by Func::in. */
305  Function new_function_in_same_group(const std::string &);
306 
307  /** Mark calls of this function by 'f' to be replaced with its wrapper
308  * during the lowering stage. If the string 'f' is empty, it means replace
309  * all calls to this function by all other functions (excluding itself) in
310  * the pipeline with the wrapper. This will also freeze 'wrapper' to prevent
311  * user from updating the values of the Function it wraps via the wrapper.
312  * See \ref Func::in for more details. */
313  // @{
314  void add_wrapper(const std::string &f, Function &wrapper);
315  const std::map<std::string, FunctionPtr> &wrappers() const;
316  // @}
317 
318  /** Check if a Function is a trivial wrapper around another
319  * Function, Buffer, or Parameter. Returns the Call node if it
320  * is. Otherwise returns null.
321  */
322  const Call *is_wrapper() const;
323 
324  /** Replace every call to Functions in 'substitutions' keys by all Exprs
325  * referenced in this Function to call to their substitute Functions (i.e.
326  * the corresponding values in 'substitutions' map). */
327  // @{
328  Function &substitute_calls(const std::map<FunctionPtr, FunctionPtr> &substitutions);
329  Function &substitute_calls(const Function &orig, const Function &substitute);
330  // @}
331 
332  /** Return true iff the name matches one of the Function's pure args. */
333  bool is_pure_arg(const std::string &name) const;
334 
335  /** If the Function has type requirements, check that the given argument
336  * is compatible with them. If not, assert-fail. (If there are no type requirements, do nothing.) */
337  void check_types(const Expr &e) const;
338  void check_types(const Tuple &t) const;
339  void check_types(const Type &t) const;
340  void check_types(const std::vector<Expr> &exprs) const;
341  void check_types(const std::vector<Type> &types) const;
342 
343  /** If the Function has dimension requirements, check that the given argument
344  * is compatible with them. If not, assert-fail. (If there are no dimension requirements, do nothing.) */
345  void check_dims(int dims) const;
346 
347  /** Define the output buffers. If the Function has types specified, this can be called at
348  * any time. If not, it can only be called for a Function with a pure definition. */
349  void create_output_buffers(const std::vector<Type> &types, int dims) const;
350 };
351 
352 /** Deep copy an entire Function DAG. */
353 std::pair<std::vector<Function>, std::map<std::string, Function>> deep_copy(
354  const std::vector<Function> &outputs,
355  const std::map<std::string, Function> &env);
356 
357 extern std::atomic<int> random_variable_counter;
358 
359 } // namespace Internal
360 } // namespace Halide
361 
362 #endif
Create a small array of Exprs for defining and calling functions with multiple outputs.
Definition: Tuple.h:18
void update_with_deserialization(const std::string &name, const std::string &origin_name, const std::vector< Halide::Type > &output_types, const std::vector< Halide::Type > &required_types, int required_dims, const std::vector< std::string > &args, const FuncSchedule &func_schedule, const Definition &init_def, const std::vector< Definition > &updates, const std::string &debug_file, const std::vector< Parameter > &output_buffers, const std::vector< ExternFuncArgument > &extern_arguments, const std::string &extern_function_name, NameMangling name_mangling, DeviceAPI device_api, const Expr &extern_proxy_expr, bool trace_loads, bool trace_stores, bool trace_realizations, const std::vector< std::string > &trace_tags, bool frozen)
Update a function with deserialized data.
A base class for algorithms that need to recursively walk over the IR.
Definition: IRVisitor.h:19
void trace_stores()
Tracing calls and accessors, passed down from the Func equivalents.
A schedule for a single stage of a Halide pipeline.
Definition: Schedule.h:695
A fragment of Halide syntax.
Definition: Expr.h:258
FunctionPtr get_contents() const
Get a handle on the halide function contents that this Function represents.
Definition: Function.h:95
int dimensions() const
Get the dimensionality.
const std::vector< Type > & required_types() const
Get the type constaints on the outputs (if any).
Expr make_call_to_extern_definition(const std::vector< Expr > &args, const Target &t) const
Make a call node to the extern definition.
Expr substitute(const std::string &name, const Expr &replacement, const Expr &expr)
Substitute variables with the given name with the replacement expression within expr.
A possibly-weak pointer to a Halide function.
Definition: FunctionPtr.h:27
bool is_tracing_stores() const
Tracing calls and accessors, passed down from the Func equivalents.
A struct representing a target machine and os to generate code for.
Definition: Target.h:19
bool has_pure_definition() const
Does this function have a pure definition?
int required_dimensions() const
Get the dimensionality constaints on the outputs (if any).
#define internal_assert(c)
Definition: Errors.h:19
void freeze()
Mark function as frozen, which means it cannot accept new definitions.
bool can_be_inlined() const
Is it legal to inline this function?
void add_trace_tag(const std::string &trace_tag)
Tracing calls and accessors, passed down from the Func equivalents.
bool has_extern_definition() const
Check if the function has an extern definition.
const std::vector< Type > & output_types() const
Get the types of the outputs.
const std::string & extern_function_name() const
Get the name of the extern function called for an extern definition.
This file defines the class FunctionDAG, which is our representation of a Halide pipeline, and contains methods to using Halide&#39;s bounds tools to query properties of it.
bool is_pure() const
Does this function only have a pure definition?
Definition: Function.h:182
Definition & definition()
Get a mutable handle to the init definition.
Function()=default
Construct a new function with no definitions and no name.
NameMangling extern_definition_name_mangling() const
Get the name mangling specified for the extern definition.
const std::string & debug_file() const
Get a const handle to the debug filename.
bool is_tracing_loads() const
Tracing calls and accessors, passed down from the Func equivalents.
const std::vector< std::string > & args() const
Get the pure arguments.
const std::vector< Parameter > & output_buffers() const
Get a handle on the output buffer used for setting constraints on it.
void check_types(const Expr &e) const
If the Function has type requirements, check that the given argument is compatible with them...
A schedule for a Function of a Halide pipeline.
Definition: Schedule.h:590
const std::string & name() const
Get the name of the function.
Base classes for Halide expressions (Halide::Expr) and statements (Halide::Internal::Stmt) ...
A function call.
Definition: IR.h:490
int outputs() const
Get the number of outputs.
bool has_update_definition() const
Does this function have an update definition?
Match whatever is specified in the Target.
Function new_function_in_same_group(const std::string &)
Make a new Function with the same lifetime as this one, and return a strong reference to it...
void create_output_buffers(const std::vector< Type > &types, int dims) const
Define the output buffers.
std::atomic< int > random_variable_counter
FuncSchedule & schedule()
Get a handle to the function-specific schedule for the purpose of modifying it.
DeviceAPI extern_function_device_api() const
Get the DeviceAPI declared for an extern function.
const std::vector< Expr > & values() const
Get the right-hand-side of the pure definition.
std::pair< std::vector< Function >, std::map< std::string, Function > > deep_copy(const std::vector< Function > &outputs, const std::map< std::string, Function > &env)
Deep copy an entire Function DAG.
bool same_as(const Function &other) const
Test for equality of identity.
Definition: Function.h:263
const std::vector< Definition > & updates() const
Get a const reference to this function&#39;s update definitions.
void add_wrapper(const std::string &f, Function &wrapper)
Mark calls of this function by &#39;f&#39; to be replaced with its wrapper during the lowering stage...
Function & substitute_calls(const std::map< FunctionPtr, FunctionPtr > &substitutions)
Replace every call to Functions in &#39;substitutions&#39; keys by all Exprs referenced in this Function to c...
No name mangling.
Defines the internal representation of the schedule for a function.
bool same_as(const FunctionPtr &other) const
Check if two FunctionPtrs refer to the same Function.
Definition: FunctionPtr.h:79
Expr extern_definition_proxy_expr() const
Get the proxy Expr for the extern stage.
const Call * is_wrapper() const
Check if a Function is a trivial wrapper around another Function, Buffer, or Parameter.
void define(const std::vector< std::string > &args, std::vector< Expr > values)
Add a pure definition to this function.
const std::string & origin_name() const
If this is a wrapper of another func, created by a chain of in or clone_in calls, returns the name of...
const std::vector< ExternFuncArgument > & extern_arguments() const
Retrive the arguments of the extern definition.
void check_dims(int dims) const
If the Function has dimension requirements, check that the given argument is compatible with them...
A reference-counted handle to Halide&#39;s internal representation of a function.
Definition: Function.h:38
bool operator()(const Function &a, const Function &b) const
Definition: Function.h:45
void mutate(IRMutator *mutator)
Accept a mutator to mutator all of the definitions and arguments of this function.
bool defined() const
Check if the reference is defined.
Definition: FunctionPtr.h:74
An argument to an extern-defined Func.
Types in the halide type system.
Definition: Type.h:276
bool is_tracing_realizations() const
Tracing calls and accessors, passed down from the Func equivalents.
StageSchedule & update_schedule(int idx=0)
Get a mutable handle to the stage-specfic schedule for the update stage.
NameMangling
An enum to specify calling convention for extern stages.
Definition: Function.h:25
A Function definition which can either represent a init or an update definition.
Definition: Definition.h:38
void trace_realizations()
Tracing calls and accessors, passed down from the Func equivalents.
const std::vector< std::string > & get_trace_tags() const
Tracing calls and accessors, passed down from the Func equivalents.
void define_extern(const std::string &function_name, const std::vector< ExternFuncArgument > &args, const std::vector< Type > &types, const std::vector< Var > &dims, NameMangling mangling, DeviceAPI device_api)
Add an external definition of this Func.
const std::map< std::string, FunctionPtr > & wrappers() const
Mark calls of this function by &#39;f&#39; to be replaced with its wrapper during the lowering stage...
Defines the internal representation of a halide function&#39;s definition and related classes...
void trace_loads()
Tracing calls and accessors, passed down from the Func equivalents.
Definition & update(int idx=0)
Get a mutable handle to this function&#39;s update definition at index &#39;idx&#39;.
A base class for passes over the IR which modify it (e.g.
Definition: IRMutator.h:26
void define_update(const std::vector< Expr > &args, std::vector< Expr > values)
Add an update definition to this function.
bool frozen() const
Check if a function has been frozen.
void deep_copy(const FunctionPtr &copy, std::map< FunctionPtr, FunctionPtr > &copied_map) const
Deep copy this Function into &#39;copy&#39;.
bool is_pure_arg(const std::string &name) const
Return true iff the name matches one of the Function&#39;s pure args.
DeviceAPI
An enum describing a type of device API.
Definition: DeviceAPI.h:15
void lock_loop_levels()
Replace this Function&#39;s LoopLevels with locked copies that cannot be mutated further.
void accept(IRVisitor *visitor) const
Accept a visitor to visit all of the definitions and arguments of this function.
This lets you use a Function as a key in a map of the form map<Function, Foo, Function::Compare> ...
Definition: Function.h:44