Halide
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"
7 #include "ExternFuncArgument.h"
8 #include "IR.h"
9 
10 /** \file
11  *
12  * Classes for declaring scalar parameters to halide pipelines
13  */
14 
15 namespace 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. */
21 template<typename T = void>
22 class Param {
23  /** A reference-counted handle on the internal parameter object */
24  Internal::Parameter param;
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  // Allow all Param<> variants friend access to each other
43  template<typename OTHER_TYPE>
44  friend class Param;
45 
46 public:
47  /** True if the Halide type is not void (or const void). */
48  static constexpr bool has_static_type = !std::is_void<T>::value;
49 
50  /** Get the Halide type of T. Callers should not use the result if
51  * has_static_halide_type is false. */
52  static Type static_type() {
54  return type_of<T>();
55  }
56 
57  /** Construct a scalar parameter of type T with a unique
58  * auto-generated name */
59  // @{
61  : param(type_of<T>(), false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
62  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
63  }
64  explicit Param(Type t)
65  : param(t, false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
66  static_assert(!has_static_type, "Cannot use this ctor with an explicit type.");
67  }
68  // @}
69 
70  /** Construct a scalar parameter of type T with the given name. */
71  // @{
72  explicit Param(const std::string &n)
73  : param(type_of<T>(), false, 0, n) {
74  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
75  check_name();
76  }
77  explicit Param(const char *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  Param(Type t, const std::string &n)
83  : param(t, false, 0, n) {
84  static_assert(!has_static_type, "Cannot use this ctor with an explicit type.");
85  check_name();
86  }
87  // @}
88 
89  /** Construct a scalar parameter of type T an initial value of
90  * 'val'. Only triggers for non-pointer types. */
91  template<typename T2 = T, typename std::enable_if<!std::is_pointer<T2>::value>::type * = nullptr>
92  explicit Param(not_void_T val)
93  : param(type_of<T>(), false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
94  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
95  set<not_void_T>(val);
96  }
97 
98  /** Construct a scalar parameter of type T with the given name
99  * and an initial value of 'val'. */
100  Param(const std::string &n, not_void_T val)
101  : param(type_of<T>(), false, 0, n) {
102  check_name();
103  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
104  set<not_void_T>(val);
105  }
106 
107  /** Construct a scalar parameter of type T with an initial value of 'val'
108  * and a given min and max. */
109  Param(not_void_T val, const Expr &min, const Expr &max)
110  : param(type_of<T>(), false, 0, Internal::make_entity_name(this, "Halide:.*:Param<.*>", 'p')) {
111  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
112  set_range(min, max);
113  set<not_void_T>(val);
114  }
115 
116  /** Construct a scalar parameter of type T with the given name
117  * and an initial value of 'val' and a given min and max. */
118  Param(const std::string &n, not_void_T val, const Expr &min, const Expr &max)
119  : param(type_of<T>(), false, 0, n) {
120  static_assert(has_static_type, "Cannot use this ctor without an explicit type.");
121  check_name();
122  set_range(min, max);
123  set<not_void_T>(val);
124  }
125 
126  /** Construct a Param<void> from any other Param. */
127  template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<std::is_void<T2>::value>::type * = nullptr>
128  Param(const Param<OTHER_TYPE> &other)
129  : param(other.param) {
130  // empty
131  }
132 
133  /** Construct a Param<non-void> from a Param with matching type.
134  * (Do the check at runtime so that we can assign from Param<void> if the types are compatible.) */
135  template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<!std::is_void<T2>::value>::type * = nullptr>
136  Param(const Param<OTHER_TYPE> &other)
137  : param(other.param) {
138  user_assert(other.type() == type_of<T>())
139  << "Param<" << type_of<T>() << "> cannot be constructed from a Param with type " << other.type();
140  }
141 
142  /** Copy a Param<void> from any other Param. */
143  template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<std::is_void<T2>::value>::type * = nullptr>
145  param = other.param;
146  return *this;
147  }
148 
149  /** Copy a Param<non-void> from a Param with matching type.
150  * (Do the check at runtime so that we can assign from Param<void> if the types are compatible.) */
151  template<typename OTHER_TYPE, typename T2 = T, typename std::enable_if<!std::is_void<T2>::value>::type * = nullptr>
153  user_assert(other.type() == type_of<T>())
154  << "Param<" << type_of<T>() << "> cannot be copied from a Param with type " << other.type();
155  param = other.param;
156  return *this;
157  }
158 
159  /** Get the name of this parameter */
160  const std::string &name() const {
161  return param.name();
162  }
163 
164  /** Get the current value of this parameter. Only meaningful when jitting.
165  Asserts if type does not exactly match the Parameter's type. */
166  template<typename T2 = not_void_T>
168  return param.scalar<T2>();
169  }
170 
171  /** Set the current value of this parameter. Only meaningful when jitting.
172  Asserts if type is not losslessly-convertible to Parameter's type. */
173  template<typename SOME_TYPE>
174  HALIDE_NO_USER_CODE_INLINE void set(const SOME_TYPE &val) {
175  if constexpr (!std::is_void<T>::value) {
177  << "The value " << val << " cannot be losslessly converted to type " << type();
178  param.set_scalar<T>(val);
179  } else {
180  // clang-format off
181 
182  // Specialized version for when T = void (thus the type is only known at runtime,
183  // not compiletime). Note that this actually works fine for all Params; we specialize
184  // it just to reduce code size for the common case of T != void.
185 
186  #define HALIDE_HANDLE_TYPE_DISPATCH(CODE, BITS, TYPE) \
187  case halide_type_t(CODE, BITS).as_u32(): \
188  user_assert(Internal::IsRoundtrippable<TYPE>::value(val)) \
189  << "The value " << val << " cannot be losslessly converted to type " << type; \
190  param.set_scalar<TYPE>(Internal::StaticCast<TYPE>::value(val)); \
191  break;
192 
193  const Type type = param.type();
194  switch (((halide_type_t)type).element_of().as_u32()) {
206  HALIDE_HANDLE_TYPE_DISPATCH(halide_type_handle, 64, uint64_t) // Handle types are always set via set_scalar<uint64_t>, not set_scalar<void*>
207  default:
208  internal_error << "Unsupported type in Param::set<" << type << ">\n";
209  }
210 
211  #undef HALIDE_HANDLE_TYPE_DISPATCH
212 
213  // clang-format on
214  }
215  }
216 
217  /** Get the halide type of the Param */
218  Type type() const {
219  return param.type();
220  }
221 
222  /** Get or set the possible range of this parameter. Use undefined
223  * Exprs to mean unbounded. */
224  // @{
225  void set_range(const Expr &min, const Expr &max) {
228  }
229 
231  if (min.defined() && min.type() != param.type()) {
232  min = Internal::Cast::make(param.type(), min);
233  }
234  param.set_min_value(min);
235  }
236 
238  if (max.defined() && max.type() != param.type()) {
239  max = Internal::Cast::make(param.type(), max);
240  }
241  param.set_max_value(max);
242  }
243 
244  Expr min_value() const {
245  return param.min_value();
246  }
247 
248  Expr max_value() const {
249  return param.max_value();
250  }
251  // @}
252 
253  template<typename SOME_TYPE>
254  HALIDE_NO_USER_CODE_INLINE void set_estimate(const SOME_TYPE &val) {
255  if constexpr (!std::is_void<T>::value) {
257  << "The value " << val << " cannot be losslessly converted to type " << type();
258  param.set_estimate(Expr(val));
259  } else {
260  // clang-format off
261 
262  // Specialized version for when T = void (thus the type is only known at runtime,
263  // not compiletime). Note that this actually works fine for all Params; we specialize
264  // it just to reduce code size for the common case of T != void.
265 
266  #define HALIDE_HANDLE_TYPE_DISPATCH(CODE, BITS, TYPE) \
267  case halide_type_t(CODE, BITS).as_u32(): \
268  user_assert(Internal::IsRoundtrippable<TYPE>::value(val)) \
269  << "The value " << val << " cannot be losslessly converted to type " << type; \
270  param.set_estimate(Expr(Internal::StaticCast<TYPE>::value(val))); \
271  break;
272 
273  const Type type = param.type();
274  switch (((halide_type_t)type).element_of().as_u32()) {
286  HALIDE_HANDLE_TYPE_DISPATCH(halide_type_handle, 64, uint64_t) // Handle types are always set via set_scalar<uint64_t>, not set_scalar<void*>
287  default:
288  internal_error << "Unsupported type in Param::set<" << type << ">\n";
289  }
290 
291  #undef HALIDE_HANDLE_TYPE_DISPATCH
292 
293  // clang-format on
294  }
295  }
296 
297  /** You can use this parameter as an expression in a halide
298  * function definition */
299  operator Expr() const {
300  return Internal::Variable::make(param.type(), name(), param);
301  }
302 
303  /** Using a param as the argument to an external stage treats it
304  * as an Expr */
305  operator ExternFuncArgument() const {
306  return Expr(*this);
307  }
308 
309  /** Construct the appropriate argument matching this parameter,
310  * for the purpose of generating the right type signature when
311  * statically compiling halide pipelines. */
312  operator Argument() const {
313  return Argument(name(), Argument::InputScalar, type(), 0,
314  param.get_argument_estimates());
315  }
316 
318  return param;
319  }
320 
322  return param;
323  }
324 };
325 
326 /** Returns an Expr corresponding to the user context passed to
327  * the function (if any). It is rare that this function is necessary
328  * (e.g. to pass the user context to an extern function written in C). */
330  return Internal::Variable::make(Handle(), "__user_context",
331  Internal::Parameter(Handle(), false, 0, "__user_context"));
332 }
333 
334 } // namespace Halide
335 
336 #endif
int32_t
signed __INT32_TYPE__ int32_t
Definition: runtime_internal.h:24
Halide::Internal::Cast::make
static Expr make(Type t, Expr v)
Halide::Internal::Parameter::set_scalar
HALIDE_NO_USER_CODE_INLINE void set_scalar(T val)
If the parameter is a scalar parameter, set its current value.
Definition: Parameter.h:90
Halide::Param::has_static_type
static constexpr bool has_static_type
True if the Halide type is not void (or const void).
Definition: Param.h:48
Halide::Param::min_value
Expr min_value() const
Definition: Param.h:244
internal_assert
#define internal_assert(c)
Definition: Errors.h:19
Halide::Argument::InputScalar
@ InputScalar
Definition: Argument.h:53
halide_type_handle
@ halide_type_handle
opaque pointer type (void *)
Definition: HalideRuntime.h:457
Halide::Param::operator=
Param< T > & operator=(const Param< OTHER_TYPE > &other)
Copy a Param<void> from any other Param.
Definition: Param.h:144
Halide::Internal::Parameter::set_max_value
void set_max_value(const Expr &e)
uint8_t
unsigned __INT8_TYPE__ uint8_t
Definition: runtime_internal.h:29
Halide::Internal::Parameter::max_value
Expr max_value() const
uint16_t
unsigned __INT16_TYPE__ uint16_t
Definition: runtime_internal.h:27
Halide::Param::type
Type type() const
Get the halide type of the Param.
Definition: Param.h:218
Halide::Internal::Parameter
A reference-counted handle to a parameter to a halide pipeline.
Definition: Parameter.h:28
Halide::Internal::Parameter::min_value
Expr min_value() const
halide_type_float
@ halide_type_float
IEEE floating point numbers.
Definition: HalideRuntime.h:456
Halide::Param::name
const std::string & name() const
Get the name of this parameter.
Definition: Param.h:160
Halide::user_context_value
Expr user_context_value()
Returns an Expr corresponding to the user context passed to the function (if any).
Definition: Param.h:329
Halide::min
Expr min(const FuncRef &a, const FuncRef &b)
Explicit overloads of min and max for FuncRef.
Definition: Func.h:584
Halide::Internal::make_entity_name
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.
int8_t
signed __INT8_TYPE__ int8_t
Definition: runtime_internal.h:28
Halide::Argument
A struct representing an argument to a halide-generated function.
Definition: Argument.h:37
user_assert
#define user_assert(c)
Definition: test.h:10
Halide::Param::Param
Param()
Construct a scalar parameter of type T with a unique auto-generated name.
Definition: Param.h:60
Halide::Param::Param
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:100
IR.h
halide_type_t
A runtime tag for a type in the halide type system.
Definition: HalideRuntime.h:476
Halide::Param::Param
Param(const char *n)
Definition: Param.h:77
Halide::Param::set_max_value
void set_max_value(Expr max)
Definition: Param.h:237
Halide::Param::get
HALIDE_NO_USER_CODE_INLINE T2 get() const
Get the current value of this parameter.
Definition: Param.h:167
Halide::Param::set_estimate
HALIDE_NO_USER_CODE_INLINE void set_estimate(const SOME_TYPE &val)
Definition: Param.h:254
Halide::Param::Param
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:118
uint64_t
unsigned __INT64_TYPE__ uint64_t
Definition: runtime_internal.h:23
Halide::Type
Types in the halide type system.
Definition: Type.h:276
Halide::Param::static_type
static Type static_type()
Get the Halide type of T.
Definition: Param.h:52
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition: AbstractGenerator.h:19
Halide::Internal::Parameter::type
Type type() const
Get the type of this parameter.
Halide::ExternFuncArgument
An argument to an extern-defined Func.
Definition: ExternFuncArgument.h:17
Halide::LinkageType::Internal
@ Internal
Not visible externally, similar to 'static' linkage in C.
Halide::Handle
Type Handle(int lanes=1, const halide_handle_cplusplus_type *handle_type=nullptr)
Construct a handle type.
Definition: Type.h:551
Argument.h
ExternFuncArgument.h
Halide::Internal::Parameter::set_estimate
void set_estimate(Expr e)
Halide::Param::parameter
const Internal::Parameter & parameter() const
Definition: Param.h:317
Halide::Expr::type
HALIDE_ALWAYS_INLINE Type type() const
Get the type of this expression node.
Definition: Expr.h:321
Halide::Param::Param
Param(const Param< OTHER_TYPE > &other)
Construct a Param<void> from any other Param.
Definition: Param.h:128
Halide::Internal::Parameter::set_min_value
void set_min_value(const Expr &e)
Get and set constraints for scalar parameters.
int64_t
signed __INT64_TYPE__ int64_t
Definition: runtime_internal.h:22
halide_type_uint
@ halide_type_uint
unsigned integers
Definition: HalideRuntime.h:455
Halide::Param::set_range
void set_range(const Expr &min, const Expr &max)
Get or set the possible range of this parameter.
Definition: Param.h:225
Halide::Param::set_min_value
void set_min_value(Expr min)
Definition: Param.h:230
HALIDE_NO_USER_CODE_INLINE
#define HALIDE_NO_USER_CODE_INLINE
Definition: Util.h:45
internal_error
#define internal_error
Definition: Errors.h:23
Halide::Param::Param
Param(not_void_T val)
Construct a scalar parameter of type T an initial value of 'val'.
Definition: Param.h:92
Halide::Internal::Parameter::get_argument_estimates
ArgumentEstimates get_argument_estimates() const
Get the ArgumentEstimates appropriate for this Parameter.
Halide::Param::Param
Param(Type t)
Definition: Param.h:64
Halide::Internal::Parameter::name
const std::string & name() const
Get the name of this parameter.
Halide::Internal::IntrusivePtr::defined
HALIDE_ALWAYS_INLINE bool defined() const
Definition: IntrusivePtr.h:161
Halide::Param::max_value
Expr max_value() const
Definition: Param.h:248
Halide::Param::Param
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:109
Halide::type_of
Type type_of()
Construct the halide equivalent of a C type.
Definition: Type.h:557
Halide::Internal::IsRoundtrippable
Definition: Util.h:422
Halide::Internal::Parameter::scalar
HALIDE_NO_USER_CODE_INLINE T scalar() const
If the parameter is a scalar parameter, get its currently bound value.
Definition: Parameter.h:78
int16_t
signed __INT16_TYPE__ int16_t
Definition: runtime_internal.h:26
Halide::Expr
A fragment of Halide syntax.
Definition: Expr.h:257
Halide::Param::Param
Param(Type t, const std::string &n)
Definition: Param.h:82
halide_type_int
@ halide_type_int
signed integers
Definition: HalideRuntime.h:454
Halide::Param::set
HALIDE_NO_USER_CODE_INLINE void set(const SOME_TYPE &val)
Set the current value of this parameter.
Definition: Param.h:174
uint32_t
unsigned __INT32_TYPE__ uint32_t
Definition: runtime_internal.h:25
Halide::max
Expr max(const FuncRef &a, const FuncRef &b)
Definition: Func.h:587
Halide::Internal::Variable::make
static Expr make(Type type, const std::string &name)
Definition: IR.h:754
Halide::Param
A scalar parameter to a halide pipeline.
Definition: Param.h:22
Halide::Param::parameter
Internal::Parameter & parameter()
Definition: Param.h:321
Halide::Param::Param
Param(const std::string &n)
Construct a scalar parameter of type T with the given name.
Definition: Param.h:72
HALIDE_HANDLE_TYPE_DISPATCH
#define HALIDE_HANDLE_TYPE_DISPATCH(CODE, BITS, TYPE)