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 12 namespace 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). */ 19 class 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 27 public: 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. */ same_as(const Var & other)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); is_implicit()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 //{ implicit_index(const std::string & name)139 static int implicit_index(const std::string &name) { 140 return is_implicit(name) ? atoi(name.c_str() + 1) : -1; 141 } implicit_index()142 int implicit_index() const { 143 return implicit_index(name()); 144 } 145 //} 146 147 /** Test if a var is the placeholder variable _ */ 148 //{ is_placeholder(const std::string & name)149 static bool is_placeholder(const std::string &name) { 150 return name == "_"; 151 } is_placeholder()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. */ outermost()163 static Var outermost() { 164 return Var("__outermost"); 165 } 166 }; 167 168 template<int N = -1> 169 struct ImplicitVar { to_varImplicitVar170 Var to_var() const { 171 if (N >= 0) { 172 return Var::implicit(N); 173 } else { 174 return Var("_"); 175 } 176 } 177 VarImplicitVar178 operator Var() const { 179 return to_var(); 180 } ExprImplicitVar181 operator Expr() const { 182 return to_var(); 183 } 184 }; 185 186 /** A placeholder variable for inferred arguments. See \ref Var::implicit */ 187 static constexpr ImplicitVar<> _; 188 189 /** The first ten implicit Vars for use in scheduling. See \ref Var::implicit */ 190 // @{ 191 static constexpr ImplicitVar<0> _0; 192 static constexpr ImplicitVar<1> _1; 193 static constexpr ImplicitVar<2> _2; 194 static constexpr ImplicitVar<3> _3; 195 static constexpr ImplicitVar<4> _4; 196 static constexpr ImplicitVar<5> _5; 197 static constexpr ImplicitVar<6> _6; 198 static constexpr ImplicitVar<7> _7; 199 static constexpr ImplicitVar<8> _8; 200 static constexpr ImplicitVar<9> _9; 201 // @} 202 203 namespace Internal { 204 205 /** Make a list of unique arguments for definitions with unnamed 206 arguments. */ 207 std::vector<Var> make_argument_list(int dimensionality); 208 209 } // namespace Internal 210 211 } // namespace Halide 212 213 #endif 214