https://github.com/halide/Halide
Tip revision: 1836044836b117d93e6fe013e522975b173b4737 authored by Z Stern on 28 December 2017, 17:53:27 UTC
Merge branch 'master' into vulkan
Merge branch 'master' into vulkan
Tip revision: 1836044
Var.h
#ifndef HALIDE_VAR_H
#define HALIDE_VAR_H
/** \file
* Defines the Var - the front-end variable
*/
#include "IR.h"
namespace Halide {
/** A Halide variable, to be used when defining functions. It is just
* a name, and can be reused in places where no name conflict will
* occur. It can be used in the left-hand-side of a function
* definition, or as an Expr. As an Expr, it always has type
* Int(32). */
class Var {
std::string _name;
public:
/** Construct a Var with the given name */
EXPORT Var(const std::string &n);
/** Construct a Var with an automatically-generated unique name. */
EXPORT Var();
/** Get the name of a Var */
const std::string &name() const {return _name;}
/** Test if two Vars are the same. This simply compares the names. */
bool same_as(const Var &other) const {return _name == other._name;}
/** Implicit var constructor. Implicit variables are injected
* automatically into a function call if the number of arguments
* to the function are fewer than its dimensionality and a
* placeholder ("_") appears in its argument list. Defining a
* function to equal an expression containing implicit variables
* similarly appends those implicit variables, in the same order,
* to the left-hand-side of the definition where the placeholder
* ('_') appears.
*
* For example, consider the definition:
*
\code
Func f, g;
Var x, y;
f(x, y) = 3;
\endcode
*
* A call to f with the placeholder symbol \ref _
* will have implicit arguments injected automatically, so f(2, \ref _)
* is equivalent to f(2, \ref _0), where \ref _0 = Var::implicit(0), and f(\ref _)
* (and indeed f when cast to an Expr) is equivalent to f(\ref _0, \ref _1).
* The following definitions are all equivalent, differing only in the
* variable names.
*
\code
g(_) = f*3;
g(_) = f(_)*3;
g(x, _) = f(x, _)*3;
g(x, y) = f(x, y)*3;
\endcode
*
* These are expanded internally as follows:
*
\code
g(_0, _1) = f(_0, _1)*3;
g(_0, _1) = f(_0, _1)*3;
g(x, _0) = f(x, _0)*3;
g(x, y) = f(x, y)*3;
\endcode
*
* The following, however, defines g as four dimensional:
\code
g(x, y, _) = f*3;
\endcode
*
* It is equivalent to:
*
\code
g(x, y, _0, _1) = f(_0, _1)*3;
\endcode
*
* Expressions requiring differing numbers of implicit variables
* can be combined. The left-hand-side of a definition injects
* enough implicit variables to cover all of them:
*
\code
Func h;
h(x) = x*3;
g(x) = h + (f + f(x)) * f(x, y);
\endcode
*
* expands to:
*
\code
Func h;
h(x) = x*3;
g(x, _0, _1) = h(_0) + (f(_0, _1) + f(x, _0)) * f(x, y);
\endcode
*
* The first ten implicits, _0 through _9, are predeclared in this
* header and can be used for scheduling. They should never be
* used as arguments in a declaration or used in a call.
*
* While it is possible to use Var::implicit or the predeclared
* implicits to create expressions that can be treated as small
* anonymous functions (e.g. Func(_0 + _1)) this is considered
* poor style. Instead use \ref lambda.
*/
EXPORT static Var implicit(int n);
/** Return whether a variable name is of the form for an implicit argument.
* TODO: This is almost guaranteed to incorrectly fire on user
* declared variables at some point. We should likely prevent
* user Var declarations from making names of this form.
*/
//{
EXPORT static bool is_implicit(const std::string &name);
bool is_implicit() const {
return is_implicit(name());
}
//}
/** Return the argument index for a placeholder argument given its
* name. Returns 0 for \ref _0, 1 for \ref _1, etc. Returns -1 if
* the variable is not of implicit form.
*/
//{
static int implicit_index(const std::string &name) {
return is_implicit(name) ? atoi(name.c_str() + 1) : -1;
}
int implicit_index() const {
return implicit_index(name());
}
//}
/** Test if a var is the placeholder variable \ref _ */
//{
static bool is_placeholder(const std::string &name) {
return name == "_";
}
bool is_placeholder() const {
return is_placeholder(name());
}
//}
/** A Var can be treated as an Expr of type Int(32) */
operator Expr() const {
return Internal::Variable::make(Int(32), name());
}
/** Vars to use for scheduling producer/consumer pairs on the gpu. Deprecated. */
// @{
HALIDE_ATTRIBUTE_DEPRECATED("Var::gpu_blocks() is deprecated.")
static Var gpu_blocks() {
return Var("__deprecated_block_id_x");
}
HALIDE_ATTRIBUTE_DEPRECATED("Var::gpu_threads() is deprecated.")
static Var gpu_threads() {
return Var("__deprecated_thread_id_x");
}
// @}
/** A Var that represents the location outside the outermost loop. */
static Var outermost() {
return Var("__outermost");
}
};
/** A placeholder variable for infered arguments. See \ref Var::implicit */
EXPORT extern Var _;
/** The first ten implicit Vars for use in scheduling. See \ref Var::implicit */
// @{
EXPORT extern Var _0, _1, _2, _3, _4, _5, _6, _7, _8, _9;
// @}
namespace Internal {
/** Make a list of unique arguments for definitions with unnamed
arguments. */
EXPORT std::vector<Var> make_argument_list(int dimensionality);
}
}
#endif