Halide 13.0.2
Halide compiler and libraries
Param.h
Go to the documentation of this file.
1#ifndef HALIDE_PARAM_H
2#define HALIDE_PARAM_H
3
4#include <type_traits>
5
6#include "Argument.h"
8#include "IR.h"
9
10/** \file
11 *
12 * Classes for declaring scalar parameters to halide pipelines
13 */
14
15namespace Halide {
16
17/** A scalar parameter to a halide pipeline. If you're jitting, this
18 * should be bound to an actual value of type T using the set method
19 * before you realize the function uses this. If you're statically
20 * compiling, this param should appear in the argument list. */
21template<typename T = void>
22class Param {
23 /** A reference-counted handle on the internal parameter object */
25
26 // This is a deliberately non-existent type that allows us to compile Param<>
27 // but provide less-confusing error messages if you attempt to call get<> or set<>
28 // without explicit types.
29 struct DynamicParamType;
30
31 /** T unless T is (const) void, in which case pointer-to-useless-type.` */
32 using not_void_T = typename std::conditional<std::is_void<T>::value, DynamicParamType *, T>::type;
33
34 void check_name() const {
35 user_assert(param.name() != "__user_context")
36 << "Param<void*>(\"__user_context\") "
37 << "is no longer used to control whether Halide functions take explicit "
38 << "user_context arguments. Use set_custom_user_context() when jitting, "
39 << "or add Target::UserContext to the Target feature set when compiling ahead of time.";
40 }
41
42 // Must be constexpr to allow use in case clauses.
43 inline static constexpr int halide_type_code(halide_type_code_t code, int bits) {
44 return (((int)code) << 8) | bits;
45 }
46
47 // Allow all Param<> variants friend access to each other
48 template<typename OTHER_TYPE>
49 friend class Param;
50
51public:
52 /** True if the Halide type is not void (or const void). */
53 static constexpr bool has_static_type = !std::is_void<T>::value;
54
55 /** Get the Halide type of T. Callers should not use the result if
56 * has_static_halide_type is false. */
57 static Type static_type() {
59 return type_of<T>();
60 }
61
62 /** Construct a scalar parameter of type T with a unique
63 * auto-generated name */
64 // @{
66 : param(type_of<T>(), false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
67 static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
68 }
69 explicit Param(Type t)
70 : param(t, false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
71 static_assert(!has_static_type, "Cannot use this ctor with an explicit type.");
72 }
73 // @}
74
75 /** Construct a scalar parameter of type T with the given name. */
76 // @{
77 explicit Param(const std::string &n)
78 : param(type_of<T>(), false, 0, n) {
79 static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
80 check_name();
81 }
82 explicit Param(const char *n)
83 : param(type_of<T>(), false, 0, n) {
84 static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
85 check_name();
86 }
87 Param(Type t, const std::string &n)
88 : param(t, false, 0, n) {
89 static_assert(!has_static_type, "Cannot use this ctor with an explicit type.");
90 check_name();
91 }
92 // @}
93
94 /** Construct a scalar parameter of type T an initial value of
95 * 'val'. Only triggers for non-pointer types. */
96 template<typename T2 = T, typename std::enable_if<!std::is_pointer<T2>::value>::type * = nullptr>
97 explicit Param(not_void_T val)
98 : param(type_of<T>(), false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
99 static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
100 set<not_void_T>(val);
101 }
102
103 /** Construct a scalar parameter of type T with the given name
104 * and an initial value of 'val'. */
105 Param(const std::string &n, not_void_T val)
106 : param(type_of<T>(), false, 0, n) {
107 check_name();
108 static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
109 set<not_void_T>(val);
110 }
111
112 /** Construct a scalar parameter of type T with an initial value of 'val'
113 * and a given min and max. */
114 Param(not_void_T val, const Expr &min, const Expr &max)
115 : param(type_of<T>(), false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
116 static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
117 set_range(min, max);
118 set<not_void_T>(val);
119 }
120
121 /** Construct a scalar parameter of type T with the given name
122 * and an initial value of 'val' and a given min and max. */
123 Param(const std::string &n, not_void_T val, const Expr &min, const Expr &max)
124 : param(type_of<T>(), false, 0, n) {
125 static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
126 check_name();
127 set_range(min, max);
128 set<not_void_T>(val);
129 }
130
131 /** Construct a Param<void> from any other Param. */
132 template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<std::is_void<T2>::value>::type * = nullptr>
134 : param(other.param) {
135 // empty
136 }
137
138 /** Construct a Param<non-void> from a Param with matching type.
139 * (Do the check at runtime so that we can assign from Param<void> if the types are compatible.) */
140 template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<!std::is_void<T2>::value>::type * = nullptr>
142 : param(other.param) {
143 user_assert(other.type() == type_of<T>())
144 << "Param<" << type_of<T>() << "> cannot be constructed from a Param with type " << other.type();
145 }
146
147 /** Copy a Param<void> from any other Param. */
148 template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<std::is_void<T2>::value>::type * = nullptr>
150 param = other.param;
151 return *this;
152 }
153
154 /** Copy a Param<non-void> from a Param with matching type.
155 * (Do the check at runtime so that we can assign from Param<void> if the types are compatible.) */
156 template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<!std::is_void<T2>::value>::type * = nullptr>
158 user_assert(other.type() == type_of<T>())
159 << "Param<" << type_of<T>() << "> cannot be copied from a Param with type " << other.type();
160 param = other.param;
161 return *this;
162 }
163
164 /** Get the name of this parameter */
165 const std::string &name() const {
166 return param.name();
167 }
168
169 /** Get the current value of this parameter. Only meaningful when jitting.
170 Asserts if type does not exactly match the Parameter's type. */
171 template<typename T2 = not_void_T>
173 return param.scalar<T2>();
174 }
175
176 /** Set the current value of this parameter. Only meaningful when jitting.
177 Asserts if type is not losslessly-convertible to Parameter's type. */
178 // @{
179 template<typename SOME_TYPE, typename T2 = T, typename std::enable_if<!std::is_void<T2>::value>::type * = nullptr>
180 HALIDE_NO_USER_CODE_INLINE void set(const SOME_TYPE &val) {
182 << "The value " << val << " cannot be losslessly converted to type " << type();
183 param.set_scalar<T>(val);
184 }
185
186 // Specialized version for when T = void (thus the type is only known at runtime,
187 // not compiletime). Note that this actually works fine for all Params; we specialize
188 // it just to reduce code size for the common case of T != void.
189 template<typename SOME_TYPE, typename T2 = T, typename std::enable_if<std::is_void<T2>::value>::type * = nullptr>
190 HALIDE_NO_USER_CODE_INLINE void set(const SOME_TYPE &val) {
191#define HALIDE_HANDLE_TYPE_DISPATCH(CODE, BITS, TYPE) \
192 case halide_type_code(CODE, BITS): \
193 user_assert(Internal::IsRoundtrippable<TYPE>::value(val)) \
194 << "The value " << val << " cannot be losslessly converted to type " << type; \
195 param.set_scalar<TYPE>(Internal::StaticCast<TYPE>::value(val)); \
196 break;
197
198 const Type type = param.type();
199 switch (halide_type_code(type.code(), type.bits())) {
211 HALIDE_HANDLE_TYPE_DISPATCH(halide_type_handle, 64, uint64_t) // Handle types are always set via set_scalar<uint64_t>, not set_scalar<void*>
212 default:
213 internal_error << "Unsupported type in Param::set<" << type << ">\n";
214 }
215
216#undef HALIDE_HANDLE_TYPE_DISPATCH
217 }
218 // @}
219
220 /** Get the halide type of the Param */
221 Type type() const {
222 return param.type();
223 }
224
225 /** Get or set the possible range of this parameter. Use undefined
226 * Exprs to mean unbounded. */
227 // @{
228 void set_range(const Expr &min, const Expr &max) {
231 }
232
234 if (min.defined() && min.type() != param.type()) {
235 min = Internal::Cast::make(param.type(), min);
236 }
237 param.set_min_value(min);
238 }
239
241 if (max.defined() && max.type() != param.type()) {
242 max = Internal::Cast::make(param.type(), max);
243 }
244 param.set_max_value(max);
245 }
246
247 Expr min_value() const {
248 return param.min_value();
249 }
250
251 Expr max_value() const {
252 return param.max_value();
253 }
254 // @}
255
256 template<typename SOME_TYPE>
257 void set_estimate(const SOME_TYPE &value) {
259 << "The value " << value << " cannot be losslessly converted to type " << type();
260 param.set_estimate(Expr(value));
261 }
262
263 /** You can use this parameter as an expression in a halide
264 * function definition */
265 operator Expr() const {
266 return Internal::Variable::make(param.type(), name(), param);
267 }
268
269 /** Using a param as the argument to an external stage treats it
270 * as an Expr */
271 operator ExternFuncArgument() const {
272 return Expr(*this);
273 }
274
275 /** Construct the appropriate argument matching this parameter,
276 * for the purpose of generating the right type signature when
277 * statically compiling halide pipelines. */
278 operator Argument() const {
279 return Argument(name(), Argument::InputScalar, type(), 0,
280 param.get_argument_estimates());
281 }
282
284 return param;
285 }
286
288 return param;
289 }
290};
291
292/** Returns an Expr corresponding to the user context passed to
293 * the function (if any). It is rare that this function is necessary
294 * (e.g. to pass the user context to an extern function written in C). */
296 return Internal::Variable::make(Handle(), "__user_context",
297 Internal::Parameter(Handle(), false, 0, "__user_context"));
298}
299
300} // namespace Halide
301
302#endif
Defines a type used for expressing the type signature of a generated halide pipeline.
#define internal_error
Definition: Errors.h:23
#define internal_assert(c)
Definition: Errors.h:19
#define user_assert(c)
Definition: Errors.h:15
Defines the internal representation of a halide ExternFuncArgument.
halide_type_code_t
Types in the halide type system.
@ halide_type_float
IEEE floating point numbers.
@ halide_type_handle
opaque pointer type (void *)
@ halide_type_int
signed integers
@ halide_type_uint
unsigned integers
Subtypes for Halide expressions (Halide::Expr) and statements (Halide::Internal::Stmt)
#define HALIDE_HANDLE_TYPE_DISPATCH(CODE, BITS, TYPE)
#define HALIDE_NO_USER_CODE_INLINE
Definition: Util.h:45
A reference-counted handle to a parameter to a halide pipeline.
Definition: Parameter.h:29
ArgumentEstimates get_argument_estimates() const
Get the ArgumentEstimates appropriate for this Parameter.
HALIDE_NO_USER_CODE_INLINE T scalar() const
If the parameter is a scalar parameter, get its currently bound value.
Definition: Parameter.h:79
HALIDE_NO_USER_CODE_INLINE void set_scalar(T val)
If the parameter is a scalar parameter, set its current value.
Definition: Parameter.h:91
const std::string & name() const
Get the name of this parameter.
Type type() const
Get the type of this parameter.
void set_min_value(const Expr &e)
Get and set constraints for scalar parameters.
void set_max_value(const Expr &e)
A scalar parameter to a halide pipeline.
Definition: Param.h:22
Expr min_value() const
Definition: Param.h:247
const std::string & name() const
Get the name of this parameter.
Definition: Param.h:165
void set_range(const Expr &min, const Expr &max)
Get or set the possible range of this parameter.
Definition: Param.h:228
Param(const Param< OTHER_TYPE > &other)
Construct a Param<void> from any other Param.
Definition: Param.h:133
void set_estimate(const SOME_TYPE &value)
Definition: Param.h:257
const Internal::Parameter & parameter() const
Definition: Param.h:283
Param(Type t)
Definition: Param.h:69
Param(const char *n)
Definition: Param.h:82
void set_min_value(Expr min)
Definition: Param.h:233
HALIDE_NO_USER_CODE_INLINE void set(const SOME_TYPE &val)
Set the current value of this parameter.
Definition: Param.h:180
Param(not_void_T val)
Construct a scalar parameter of type T an initial value of 'val'.
Definition: Param.h:97
Expr max_value() const
Definition: Param.h:251
void set_max_value(Expr max)
Definition: Param.h:240
Type type() const
Get the halide type of the Param.
Definition: Param.h:221
Param(Type t, const std::string &n)
Definition: Param.h:87
static Type static_type()
Get the Halide type of T.
Definition: Param.h:57
static constexpr bool has_static_type
True if the Halide type is not void (or const void).
Definition: Param.h:53
Param(not_void_T val, const Expr &min, const Expr &max)
Construct a scalar parameter of type T with an initial value of 'val' and a given min and max.
Definition: Param.h:114
Param()
Construct a scalar parameter of type T with a unique auto-generated name.
Definition: Param.h:65
Param(const std::string &n)
Construct a scalar parameter of type T with the given name.
Definition: Param.h:77
Param(const std::string &n, not_void_T val, const Expr &min, const Expr &max)
Construct a scalar parameter of type T with the given name and an initial value of 'val' and a given ...
Definition: Param.h:123
Param< T > & operator=(const Param< OTHER_TYPE > &other)
Copy a Param<void> from any other Param.
Definition: Param.h:149
HALIDE_NO_USER_CODE_INLINE T2 get() const
Get the current value of this parameter.
Definition: Param.h:172
Internal::Parameter & parameter()
Definition: Param.h:287
Param(const std::string &n, not_void_T val)
Construct a scalar parameter of type T with the given name and an initial value of 'val'.
Definition: Param.h:105
std::string make_entity_name(void *stack_ptr, const std::string &type, char prefix)
Make a unique name for an object based on the name of the stack variable passed in.
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
Type type_of()
Construct the halide equivalent of a C type.
Definition: Type.h:525
Expr min(const FuncRef &a, const FuncRef &b)
Explicit overloads of min and max for FuncRef.
Definition: Func.h:595
Type Handle(int lanes=1, const halide_handle_cplusplus_type *handle_type=nullptr)
Construct a handle type.
Definition: Type.h:519
Expr user_context_value()
Returns an Expr corresponding to the user context passed to the function (if any).
Definition: Param.h:295
Expr max(const FuncRef &a, const FuncRef &b)
Definition: Func.h:598
unsigned __INT64_TYPE__ uint64_t
signed __INT64_TYPE__ int64_t
signed __INT32_TYPE__ int32_t
unsigned __INT8_TYPE__ uint8_t
unsigned __INT16_TYPE__ uint16_t
unsigned __INT32_TYPE__ uint32_t
signed __INT16_TYPE__ int16_t
signed __INT8_TYPE__ int8_t
A struct representing an argument to a halide-generated function.
Definition: Argument.h:37
A fragment of Halide syntax.
Definition: Expr.h:256
HALIDE_ALWAYS_INLINE Type type() const
Get the type of this expression node.
Definition: Expr.h:320
An argument to an extern-defined Func.
static Expr make(Type t, Expr v)
HALIDE_ALWAYS_INLINE bool defined() const
Definition: IntrusivePtr.h:161
static Expr make(Type type, const std::string &name)
Definition: IR.h:710
Types in the halide type system.
Definition: Type.h:265
HALIDE_ALWAYS_INLINE halide_type_code_t code() const
Return the underlying data type of an element as an enum value.
Definition: Type.h:321
HALIDE_ALWAYS_INLINE int bits() const
Return the bit size of a single element of this type.
Definition: Type.h:327