Halide
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 
8 #include "Expr.h"
9 #include "IntrusivePtr.h"
10 #include "FunctionPtr.h"
11 #include "Parameter.h"
12 #include "Schedule.h"
13 #include "Reduction.h"
14 #include "Definition.h"
15 #include "Buffer.h"
16 #include "Util.h"
17 
18 #include <map>
19 
20 namespace Halide {
21 
22 /** An argument to an extern-defined Func. May be a Function, Buffer,
23  * ImageParam or Expr. */
31 
33 
34  template<typename T>
35  ExternFuncArgument(Buffer<T> b): arg_type(BufferArg), buffer(b) {}
36  ExternFuncArgument(Expr e): arg_type(ExprArg), expr(e) {}
37  ExternFuncArgument(int e): arg_type(ExprArg), expr(e) {}
38  ExternFuncArgument(float e): arg_type(ExprArg), expr(e) {}
39 
40  ExternFuncArgument(Internal::Parameter p) : arg_type(ImageParamArg), image_param(p) {
41  // Scalar params come in via the Expr constructor.
43  }
45 
46  bool is_func() const {return arg_type == FuncArg;}
47  bool is_expr() const {return arg_type == ExprArg;}
48  bool is_buffer() const {return arg_type == BufferArg;}
49  bool is_image_param() const {return arg_type == ImageParamArg;}
50  bool defined() const {return arg_type != UndefinedArg;}
51 };
52 
53 /** An enum to specify calling convention for extern stages. */
54 enum class NameMangling {
55  Default, ///< Match whatever is specified in the Target
56  C, ///< No name mangling
57  CPlusPlus, ///< C++ name mangling
58 };
59 
60 namespace Internal {
61 
62 struct Call;
63 
64 /** A reference-counted handle to Halide's internal representation of
65  * a function. Similar to a front-end Func object, but with no
66  * syntactic sugar to help with definitions. */
67 class Function {
68 
69  FunctionPtr contents;
70 
71 public:
72  /** This lets you use a Function as a key in a map of the form
73  * map<Function, Foo, Function::Compare> */
74  struct Compare {
75  bool operator()(const Function &a, const Function &b) const {
76  internal_assert(a.contents.defined() && b.contents.defined());
77  return a.contents < b.contents;
78  }
79  };
80 
81  /** Construct a new function with no definitions and no name. This
82  * constructor only exists so that you can make vectors of
83  * functions, etc.
84  */
85  EXPORT Function();
86 
87  /** Construct a new function with the given name */
88  EXPORT explicit Function(const std::string &n);
89 
90  /** Construct a Function from an existing FunctionContents pointer. Must be non-null */
91  EXPORT explicit Function(const FunctionPtr &);
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  EXPORT void deep_copy(FunctionPtr copy, std::map<FunctionPtr, FunctionPtr> &copied_map) const;
109  EXPORT void deep_copy(std::string name, 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  EXPORT 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  EXPORT 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  EXPORT void accept(IRVisitor *visitor) const;
132 
133  /** Accept a mutator to mutator all of the definitions and
134  * arguments of this function. */
135  EXPORT void mutate(IRMutator2 *mutator);
136 
137  /** Get the name of the function. */
138  EXPORT const std::string &name() const;
139 
140  /** Get a mutable handle to the init definition. */
141  EXPORT Definition &definition();
142 
143  /** Get the init definition. */
144  EXPORT const Definition &definition() const;
145 
146  /** Get the pure arguments. */
147  EXPORT const std::vector<std::string> args() const;
148 
149  /** Get the dimensionality. */
150  EXPORT int dimensions() const;
151 
152  /** Get the number of outputs. */
153  int outputs() const {
154  return (int)output_types().size();
155  }
156 
157  /** Get the types of the outputs. */
158  EXPORT const std::vector<Type> &output_types() const;
159 
160  /** Get the right-hand-side of the pure definition. */
161  EXPORT const std::vector<Expr> &values() const;
162 
163  /** Does this function have a pure definition? */
164  EXPORT bool has_pure_definition() const;
165 
166  /** Does this function *only* have a pure definition? */
167  bool is_pure() const {
168  return (has_pure_definition() &&
169  !has_update_definition() &&
170  !has_extern_definition());
171  }
172 
173  /** Is it legal to inline this function? */
174  EXPORT bool can_be_inlined() const;
175 
176  /** Get a handle to the function-specific schedule for the purpose
177  * of modifying it. */
178  EXPORT FuncSchedule &schedule();
179 
180  /** Get a const handle to the function-specific schedule for inspecting it. */
181  EXPORT const FuncSchedule &schedule() const;
182 
183  /** Get a handle on the output buffer used for setting constraints
184  * on it. */
185  EXPORT const std::vector<Parameter> &output_buffers() const;
186 
187  /** Get a mutable handle to the stage-specfic schedule for the update
188  * stage. */
189  EXPORT StageSchedule &update_schedule(int idx = 0);
190 
191  /** Get a mutable handle to this function's update definition at
192  * index 'idx'. */
193  EXPORT Definition &update(int idx = 0);
194 
195  /** Get a const reference to this function's update definition at
196  * index 'idx'. */
197  EXPORT const Definition &update(int idx = 0) const;
198 
199  /** Get a const reference to this function's update definitions. */
200  EXPORT const std::vector<Definition> &updates() const;
201 
202  /** Does this function have an update definition? */
203  EXPORT bool has_update_definition() const;
204 
205  /** Check if the function has an extern definition. */
206  EXPORT bool has_extern_definition() const;
207 
208  /** Get the name mangling specified for the extern definition. */
209  EXPORT NameMangling extern_definition_name_mangling() const;
210 
211  /** Make a call node to the extern definition. An error if the
212  * function has no extern definition. */
213  EXPORT Expr make_call_to_extern_definition(const std::vector<Expr> &args,
214  const Target &t) const;
215 
216  /** Check if the extern function being called expects the legacy
217  * buffer_t type. */
218  EXPORT bool extern_definition_uses_old_buffer_t() const;
219 
220  /** Get the proxy Expr for the extern stage. This is an expression
221  * known to have the same data access pattern as the extern
222  * stage. It must touch at least all of the memory that the extern
223  * stage does, though it is permissible for it to be conservative
224  * and touch a superset. For most Functions, including those with
225  * extern definitions, this will be an undefined Expr. */
226  // @{
227  EXPORT Expr extern_definition_proxy_expr() const;
228  EXPORT Expr &extern_definition_proxy_expr();
229  // @}
230 
231  /** Add an external definition of this Func. */
232  EXPORT void define_extern(const std::string &function_name,
233  const std::vector<ExternFuncArgument> &args,
234  const std::vector<Type> &types,
235  int dimensionality,
236  NameMangling mangling,
237  DeviceAPI device_api,
238  bool uses_old_buffer_t);
239 
240  /** Retrive the arguments of the extern definition. */
241  // @{
242  EXPORT const std::vector<ExternFuncArgument> &extern_arguments() const;
243  EXPORT std::vector<ExternFuncArgument> &extern_arguments();
244  // @}
245 
246  /** Get the name of the extern function called for an extern
247  * definition. */
248  EXPORT const std::string &extern_function_name() const;
249 
250  /** Get the DeviceAPI declared for an extern function. */
251  EXPORT DeviceAPI extern_function_device_api() const;
252 
253  /** Test for equality of identity. */
254  bool same_as(const Function &other) const {
255  return contents.same_as(other.contents);
256  }
257 
258  /** Get a const handle to the debug filename. */
259  EXPORT const std::string &debug_file() const;
260 
261  /** Get a handle to the debug filename. */
262  EXPORT std::string &debug_file();
263 
264  /** Use an an extern argument to another function. */
265  operator ExternFuncArgument() const {
266  return ExternFuncArgument(contents);
267  }
268 
269  /** Tracing calls and accessors, passed down from the Func
270  * equivalents. */
271  // @{
272  EXPORT void trace_loads();
273  EXPORT void trace_stores();
274  EXPORT void trace_realizations();
275  EXPORT bool is_tracing_loads() const;
276  EXPORT bool is_tracing_stores() const;
277  EXPORT bool is_tracing_realizations() const;
278  // @}
279 
280  /** Mark function as frozen, which means it cannot accept new
281  * definitions. */
282  EXPORT void freeze();
283 
284  /** Check if a function has been frozen. If so, it is an error to
285  * add new definitions. */
286  EXPORT bool frozen() const;
287 
288  /** Make a new Function with the same lifetime as this one, and
289  * return a strong reference to it. Useful to create Functions which
290  * have circular references to this one - e.g. the wrappers
291  * produced by Func::in. */
292  Function new_function_in_same_group(const std::string &);
293 
294  /** Mark calls of this function by 'f' to be replaced with its wrapper
295  * during the lowering stage. If the string 'f' is empty, it means replace
296  * all calls to this function by all other functions (excluding itself) in
297  * the pipeline with the wrapper. This will also freeze 'wrapper' to prevent
298  * user from updating the values of the Function it wraps via the wrapper.
299  * See \ref Func::in for more details. */
300  // @{
301  EXPORT void add_wrapper(const std::string &f, Function &wrapper);
302  EXPORT const std::map<std::string, FunctionPtr> &wrappers() const;
303  // @}
304 
305  /** Check if a Function is a trivial wrapper around another
306  * Function, Buffer, or Parameter. Returns the Call node if it
307  * is. Otherwise returns null.
308  */
309  EXPORT const Call *is_wrapper() const;
310 
311  /** Replace every call to Functions in 'substitutions' keys by all Exprs
312  * referenced in this Function to call to their substitute Functions (i.e.
313  * the corresponding values in 'substitutions' map). */
314  // @{
315  EXPORT Function &substitute_calls(const std::map<FunctionPtr, FunctionPtr> &substitutions);
316  EXPORT Function &substitute_calls(const Function &orig, const Function &substitute);
317  // @}
318 
319  /** Find all Vars that are placeholders for ScheduleParams and substitute in
320  * the corresponding constant value. */
321  EXPORT Function &substitute_schedule_param_exprs();
322 
323  /** Return true iff the name matches one of the Function's pure args. */
324  EXPORT bool is_pure_arg(const std::string &name) const;
325 };
326 
327 /** Deep copy an entire Function DAG. */
328 std::pair<std::vector<Function>, std::map<std::string, Function>> deep_copy(
329  const std::vector<Function> &outputs,
330  const std::map<std::string, Function> &env);
331 
332 }}
333 
334 #endif
Various utility functions used internally Halide.
Internal::FunctionPtr func
Definition: Function.h:27
A base class for algorithms that need to recursively walk over the IR.
Definition: IRVisitor.h:22
A schedule for a single stage of a Halide pipeline.
Definition: Schedule.h:331
A fragment of Halide syntax.
Definition: Expr.h:276
bool is_image_param() const
Definition: Function.h:49
Internal::Parameter image_param
Definition: Function.h:30
FunctionPtr get_contents() const
Get a handle on the halide function contents that this Function represents.
Definition: Function.h:95
A base class for passes over the IR which modify it (e.g.
Definition: IRMutator.h:124
ExternFuncArgument(Buffer< T > b)
Definition: Function.h:35
A possibly-weak pointer to a Halide function.
Definition: FunctionPtr.h:27
A struct representing a target machine and os to generate code for.
Definition: Target.h:21
Defines methods for manipulating and analyzing boolean expressions.
bool is_pure() const
Does this function only have a pure definition?
Definition: Function.h:167
A schedule for a Function of a Halide pipeline.
Definition: Schedule.h:245
Base classes for Halide expressions (Halide::Expr) and statements (Halide::Internal::Stmt) ...
A function call.
Definition: IR.h:453
int outputs() const
Get the number of outputs.
Definition: Function.h:153
Match whatever is specified in the Target.
#define internal_assert(c)
Definition: Error.h:140
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:254
bool is_expr() const
Definition: Function.h:47
No name mangling.
Support classes for reference-counting via intrusive shared pointers.
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
Defines the internal representation of parameters to halide piplines.
A reference-counted handle to a parameter to a halide pipeline.
Definition: Parameter.h:21
bool is_buffer() const
Definition: Function.h:48
A reference-counted handle to Halide&#39;s internal representation of a function.
Definition: Function.h:67
bool operator()(const Function &a, const Function &b) const
Definition: Function.h:75
bool defined() const
Check if the reference is defined.
Definition: FunctionPtr.h:74
An argument to an extern-defined Func.
Definition: Function.h:24
NameMangling
An enum to specify calling convention for extern stages.
Definition: Function.h:54
bool defined() const
Definition: Function.h:50
bool is_func() const
Definition: Function.h:46
ExternFuncArgument(Internal::FunctionPtr f)
Definition: Function.h:32
A Function definition which can either represent a init or an update definition.
Definition: Definition.h:38
#define EXPORT
Definition: Util.h:30
Defines the internal representation of a halide function&#39;s definition and related classes...
ExternFuncArgument(Internal::Parameter p)
Definition: Function.h:40
Defines internal classes related to Reduction Domains.
DeviceAPI
An enum describing a type of device API.
Definition: Expr.h:317
EXPORT Expr substitute(const std::string &name, const Expr &replacement, const Expr &expr)
Substitute variables with the given name with the replacement expression within expr.
EXPORT bool is_buffer() const
Does this parameter refer to a buffer/image?
This lets you use a Function as a key in a map of the form map<Function, Foo, Function::Compare> ...
Definition: Function.h:74