Halide 19.0.0
Halide compiler and libraries
Loading...
Searching...
No Matches
Var.h
Go to the documentation of this file.
1#ifndef HALIDE_VAR_H
2#define HALIDE_VAR_H
3
4/** \file
5 * Defines the Var - the front-end variable
6 */
7#include <string>
8#include <vector>
9
10#include "Expr.h"
11
12namespace Halide {
13
14/** A Halide variable, to be used when defining functions. It is just
15 * a name, and can be reused in places where no name conflict will
16 * occur. It can be used in the left-hand-side of a function
17 * definition, or as an Expr. As an Expr, it always has type
18 * Int(32). */
19class Var {
20 /* The expression representing the Var. Guaranteed to be an
21 * Internal::Variable of type Int(32). Created once on
22 * construction of the Var to avoid making a fresh Expr every time
23 * the Var is used in a context in which is will be converted to
24 * one. */
25 Expr e;
26
27public:
28 /** Construct a Var with the given name */
29 Var(const std::string &n);
30
31 /** Construct a Var with an automatically-generated unique name. */
32 Var();
33
34 /** Get the name of a Var */
35 const std::string &name() const;
36
37 /** Test if two Vars are the same. This simply compares the names. */
38 bool same_as(const Var &other) const {
39 return name() == other.name();
40 }
41
42 /** Implicit var constructor. Implicit variables are injected
43 * automatically into a function call if the number of arguments
44 * to the function are fewer than its dimensionality and a
45 * placeholder ("_") appears in its argument list. Defining a
46 * function to equal an expression containing implicit variables
47 * similarly appends those implicit variables, in the same order,
48 * to the left-hand-side of the definition where the placeholder
49 * ('_') appears.
50 *
51 * For example, consider the definition:
52 *
53 \code
54 Func f, g;
55 Var x, y;
56 f(x, y) = 3;
57 \endcode
58 *
59 * A call to f with the placeholder symbol _
60 * will have implicit arguments injected automatically, so f(2, _)
61 * is equivalent to f(2, _0), where _0 = ImplicitVar<0>(), and f(_)
62 * (and indeed f when cast to an Expr) is equivalent to f(_0, _1).
63 * The following definitions are all equivalent, differing only in the
64 * variable names.
65 *
66 \code
67 g(_) = f*3;
68 g(_) = f(_)*3;
69 g(x, _) = f(x, _)*3;
70 g(x, y) = f(x, y)*3;
71 \endcode
72 *
73 * These are expanded internally as follows:
74 *
75 \code
76 g(_0, _1) = f(_0, _1)*3;
77 g(_0, _1) = f(_0, _1)*3;
78 g(x, _0) = f(x, _0)*3;
79 g(x, y) = f(x, y)*3;
80 \endcode
81 *
82 * The following, however, defines g as four dimensional:
83 \code
84 g(x, y, _) = f*3;
85 \endcode
86 *
87 * It is equivalent to:
88 *
89 \code
90 g(x, y, _0, _1) = f(_0, _1)*3;
91 \endcode
92 *
93 * Expressions requiring differing numbers of implicit variables
94 * can be combined. The left-hand-side of a definition injects
95 * enough implicit variables to cover all of them:
96 *
97 \code
98 Func h;
99 h(x) = x*3;
100 g(x) = h + (f + f(x)) * f(x, y);
101 \endcode
102 *
103 * expands to:
104 *
105 \code
106 Func h;
107 h(x) = x*3;
108 g(x, _0, _1) = h(_0) + (f(_0, _1) + f(x, _0)) * f(x, y);
109 \endcode
110 *
111 * The first ten implicits, _0 through _9, are predeclared in this
112 * header and can be used for scheduling. They should never be
113 * used as arguments in a declaration or used in a call.
114 *
115 * While it is possible to use Var::implicit or the predeclared
116 * implicits to create expressions that can be treated as small
117 * anonymous functions (e.g. Func(_0 + _1)) this is considered
118 * poor style. Instead use \ref lambda.
119 */
120 static Var implicit(int n);
121
122 /** Return whether a variable name is of the form for an implicit argument.
123 * TODO: This is almost guaranteed to incorrectly fire on user
124 * declared variables at some point. We should likely prevent
125 * user Var declarations from making names of this form.
126 */
127 //{
128 static bool is_implicit(const std::string &name);
129 bool is_implicit() const {
130 return is_implicit(name());
131 }
132 //}
133
134 /** Return the argument index for a placeholder argument given its
135 * name. Returns 0 for _0, 1 for _1, etc. Returns -1 if
136 * the variable is not of implicit form.
137 */
138 //{
139 static int implicit_index(const std::string &name) {
140 return is_implicit(name) ? atoi(name.c_str() + 1) : -1;
141 }
142 int implicit_index() const {
143 return implicit_index(name());
144 }
145 //}
146
147 /** Test if a var is the placeholder variable _ */
148 //{
149 static bool is_placeholder(const std::string &name) {
150 return name == "_";
151 }
152 bool is_placeholder() const {
153 return is_placeholder(name());
154 }
155 //}
156
157 /** A Var can be treated as an Expr of type Int(32) */
158 operator const Expr &() const {
159 return e;
160 }
161
162 /** A Var that represents the location outside the outermost loop. */
163 static Var outermost() {
164 return Var("__outermost");
165 }
166};
167
168template<int N = -1>
170 Var to_var() const {
171 if (N >= 0) {
172 return Var::implicit(N);
173 } else {
174 return Var("_");
175 }
176 }
177
178 operator Var() const {
179 return to_var();
180 }
181 operator Expr() const {
182 return to_var();
183 }
184};
185
186/** A placeholder variable for inferred arguments. See \ref Var::implicit */
187static constexpr ImplicitVar<> _;
188
189/** The first ten implicit Vars for use in scheduling. See \ref Var::implicit */
190// @{
191static constexpr ImplicitVar<0> _0;
192static constexpr ImplicitVar<1> _1;
193static constexpr ImplicitVar<2> _2;
194static constexpr ImplicitVar<3> _3;
195static constexpr ImplicitVar<4> _4;
196static constexpr ImplicitVar<5> _5;
197static constexpr ImplicitVar<6> _6;
198static constexpr ImplicitVar<7> _7;
199static constexpr ImplicitVar<8> _8;
200static constexpr ImplicitVar<9> _9;
201// @}
202
203namespace Internal {
204
205/** Make a list of unique arguments for definitions with unnamed
206 arguments. */
207std::vector<Var> make_argument_list(int dimensionality);
208
209} // namespace Internal
210
211} // namespace Halide
212
213#endif
Base classes for Halide expressions (Halide::Expr) and statements (Halide::Internal::Stmt)
A Halide variable, to be used when defining functions.
Definition Var.h:19
Var(const std::string &n)
Construct a Var with the given name.
static Var implicit(int n)
Implicit var constructor.
static int implicit_index(const std::string &name)
Return the argument index for a placeholder argument given its name.
Definition Var.h:139
bool is_placeholder() const
Definition Var.h:152
const std::string & name() const
Get the name of a Var.
bool is_implicit() const
Definition Var.h:129
static bool is_placeholder(const std::string &name)
Test if a var is the placeholder variable _.
Definition Var.h:149
static bool is_implicit(const std::string &name)
Return whether a variable name is of the form for an implicit argument.
int implicit_index() const
Definition Var.h:142
static Var outermost()
A Var that represents the location outside the outermost loop.
Definition Var.h:163
Var()
Construct a Var with an automatically-generated unique name.
bool same_as(const Var &other) const
Test if two Vars are the same.
Definition Var.h:38
std::vector< Var > make_argument_list(int dimensionality)
Make a list of unique arguments for definitions with unnamed arguments.
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
int atoi(const char *)
A fragment of Halide syntax.
Definition Expr.h:258
Var to_var() const
Definition Var.h:170