1 #ifndef HALIDE_GENERATOR_H_
2 #define HALIDE_GENERATOR_H_
262 #include <functional>
270 #include <type_traits>
281 #if !(__cplusplus >= 201703L || _MSVC_LANG >= 201703L)
282 #error "Halide requires C++17 or later; please upgrade your compiler."
322 std::map<std::string, std::vector<std::vector<Expr>>> values_history;
323 const size_t max_unique_values;
327 : max_unique_values(max_unique_values) {
329 void track_values(
const std::string &name,
const std::vector<Expr> &values);
336 for (
const auto &key_value : enum_map) {
337 if (t == key_value.second) {
338 return key_value.first;
341 user_error <<
"Enumeration value not found.\n";
347 auto it = enum_map.find(s);
348 user_assert(it != enum_map.end()) <<
"Enumeration value not found: " << s <<
"\n";
384 template<
bool B,
typename T>
390 template<
typename First,
typename... Rest>
391 struct select_type : std::conditional<First::value, typename First::type, typename select_type<Rest...>::type> {};
393 template<
typename First>
394 struct select_type<First> {
using type =
typename std::conditional<First::value, typename First::type, void>::type; };
404 inline const std::string &
name()
const {
416 #define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
417 virtual void set(const TYPE &new_value) = 0;
435 #undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
438 void set(
const std::string &new_value) {
441 void set(
const char *new_value) {
476 const std::string name_;
493 template<
typename FROM,
typename TO>
495 template<typename TO2 = TO, typename std::enable_if<!std::is_same<TO2, bool>::value>::type * =
nullptr>
496 inline static TO2
value(
const FROM &from) {
497 return static_cast<TO2
>(from);
500 template<typename TO2 = TO, typename std::enable_if<std::is_same<TO2, bool>::value>::type * =
nullptr>
501 inline static TO2
value(
const FROM &from) {
521 return this->
value();
528 #define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
529 void set(const TYPE &new_value) override { \
530 typed_setter_impl<TYPE>(new_value, #TYPE); \
549 #undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
552 void set(
const std::string &new_value) {
568 template<
typename FROM,
typename std::enable_if<
569 !std::is_convertible<FROM, T>::value>
::type * =
nullptr>
575 template<
typename FROM,
typename std::enable_if<
576 std::is_same<FROM, T>::value>
::type * =
nullptr>
583 template<
typename FROM,
typename std::enable_if<
584 !std::is_same<FROM, T>::value &&
585 std::is_convertible<FROM, T>::value &&
586 std::is_convertible<T, FROM>::value>
::type * =
nullptr>
591 if (value2 !=
value) {
598 template<
typename FROM,
typename std::enable_if<
599 !std::is_same<FROM, T>::value &&
600 std::is_convertible<FROM, T>::value &&
601 !std::is_convertible<T, FROM>::value>
::type * =
nullptr>
625 return this->
value().to_string();
629 std::ostringstream oss;
630 oss << v <<
".to_string()";
651 return this->
value().to_string();
655 std::ostringstream oss;
656 oss << v <<
".to_string()";
661 return "MachineParams";
694 if (new_value_string ==
"root") {
696 }
else if (new_value_string ==
"inlined") {
699 user_error <<
"Unable to parse " << this->
name() <<
": " << new_value_string;
716 return "LoopLevel::inlined()";
718 return "LoopLevel::root()";
727 return std::string();
744 const T &min = std::numeric_limits<T>::lowest(),
752 user_assert(new_value >= min && new_value <= max) <<
"Value out of range: " << new_value;
757 std::istringstream iss(new_value_string);
762 if (
sizeof(T) ==
sizeof(
char) && !std::is_same<T, bool>::value) {
769 user_assert(!iss.fail() && iss.get() == EOF) <<
"Unable to parse: " << new_value_string;
774 std::ostringstream oss;
775 oss << this->
value();
776 if (std::is_same<T, float>::value) {
779 if (oss.str().find(
'.') == std::string::npos) {
788 std::ostringstream oss;
789 oss <<
"std::to_string(" << v <<
")";
794 std::ostringstream oss;
795 if (std::is_same<T, float>::value) {
797 }
else if (std::is_same<T, double>::value) {
799 }
else if (std::is_integral<T>::value) {
800 if (std::is_unsigned<T>::value) {
803 oss <<
"int" << (
sizeof(T) * 8) <<
"_t";
824 if (new_value_string ==
"true" || new_value_string ==
"True") {
826 }
else if (new_value_string ==
"false" || new_value_string ==
"False") {
829 user_assert(
false) <<
"Unable to parse bool: " << new_value_string;
835 return this->
value() ?
"true" :
"false";
839 std::ostringstream oss;
840 oss <<
"std::string((" << v <<
") ? \"true\" : \"false\")";
859 template<typename T2 = T, typename std::enable_if<!std::is_same<T2, Type>::value>
::type * =
nullptr>
865 auto it = enum_map.find(new_value_string);
866 user_assert(it != enum_map.end()) <<
"Enumeration value not found: " << new_value_string;
871 return "Enum_" + this->
name() +
"_map().at(" + v +
")";
875 return "Enum_" + this->
name();
883 std::ostringstream oss;
884 oss <<
"enum class Enum_" << this->
name() <<
" {\n";
885 for (
auto key_value : enum_map) {
886 oss <<
" " << key_value.first <<
",\n";
893 oss <<
"inline HALIDE_NO_USER_CODE_INLINE const std::map<Enum_" << this->
name() <<
", std::string>& Enum_" << this->
name() <<
"_map() {\n";
894 oss <<
" static const std::map<Enum_" << this->
name() <<
", std::string> m = {\n";
895 for (
auto key_value : enum_map) {
896 oss <<
" { Enum_" << this->
name() <<
"::" << key_value.first <<
", \"" << key_value.first <<
"\"},\n";
899 oss <<
" return m;\n";
905 const std::map<std::string, T> enum_map;
916 return "Halide::Internal::halide_type_to_enum_string(" + v +
")";
939 this->
set(new_value_string);
943 return "\"" + this->
value() +
"\"";
951 return "std::string";
1000 template<
typename T>
1003 template<typename T2 = T, typename std::enable_if<!std::is_same<T2, std::string>::value>::type * =
nullptr>
1012 GeneratorParam(
const std::string &name,
const T &value,
const std::map<std::string, T> &enum_map)
1024 template<
typename Other,
typename T>
1028 template<
typename Other,
typename T>
1037 template<
typename Other,
typename T>
1041 template<
typename Other,
typename T>
1050 template<
typename Other,
typename T>
1054 template<
typename Other,
typename T>
1063 template<
typename Other,
typename T>
1067 template<
typename Other,
typename T>
1076 template<
typename Other,
typename T>
1080 template<
typename Other,
typename T>
1089 template<
typename Other,
typename T>
1093 template<
typename Other,
typename T>
1102 template<
typename Other,
typename T>
1106 template<
typename Other,
typename T>
1115 template<
typename Other,
typename T>
1119 template<
typename Other,
typename T>
1128 template<
typename Other,
typename T>
1132 template<
typename Other,
typename T>
1141 template<
typename Other,
typename T>
1145 template<
typename Other,
typename T>
1154 template<
typename Other,
typename T>
1158 template<
typename Other,
typename T>
1167 template<
typename Other,
typename T>
1171 template<
typename Other,
typename T>
1175 template<
typename T>
1177 return (T)a && (T)b;
1184 template<
typename Other,
typename T>
1188 template<
typename Other,
typename T>
1192 template<
typename T>
1194 return (T)a || (T)b;
1202 namespace Internal {
1203 namespace GeneratorMinMax {
1208 template<
typename Other,
typename T>
1210 return min(a, (T)b);
1212 template<
typename Other,
typename T>
1214 return min((T)a, b);
1217 template<
typename Other,
typename T>
1219 return max(a, (T)b);
1221 template<
typename Other,
typename T>
1223 return max((T)a, b);
1232 template<
typename Other,
typename T>
1236 template<
typename Other,
typename T>
1245 template<
typename Other,
typename T>
1249 template<
typename Other,
typename T>
1256 template<
typename T>
1261 namespace Internal {
1263 template<
typename T2>
1264 class GeneratorInput_Buffer;
1279 template<
typename T =
void>
1282 template<
typename T2>
1296 template<
typename T2>
1312 template<
typename T2>
1314 : parameter_(parameter_from_buffer(b)) {
1332 template<
typename... Args>
1338 template<
typename Dst>
1357 template<
typename T =
void>
1359 template<
typename T2>
1383 template<
typename T2>
1385 : kind_(
IOKind::
Buffer), parameter_(b.parameter_), func_(), expr_() {
1391 : kind_(
IOKind::
Scalar), parameter_(), func_(), expr_(e) {
1462 const std::string &
name,
1464 const std::vector<Type> &
types,
1497 template<
typename ElemType>
1507 template<
typename T>
1518 inline const std::vector<Expr> &GIOBase::get_values<Expr>()
const {
1523 inline const std::vector<Func> &GIOBase::get_values<Func>()
const {
1530 const std::string &
name,
1532 const std::vector<Type> &t,
1568 template<
typename T,
typename ValueType>
1571 using TBase =
typename std::remove_all_extents<T>::type;
1574 return std::is_array<T>::value;
1577 template<
typename T2 = T,
typename std::enable_if<
1579 !std::is_array<T2>::value>
::type * =
nullptr>
1584 template<
typename T2 = T,
typename std::enable_if<
1586 std::is_array<T2>::value && std::rank<T2>::value == 1 && (std::extent<T2, 0>::value > 0)>::
type * =
nullptr>
1591 template<
typename T2 = T,
typename std::enable_if<
1593 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>
::type * =
nullptr>
1599 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1602 return get_values<ValueType>().size();
1605 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1608 return get_values<ValueType>()[i];
1611 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1612 const ValueType &
at(
size_t i)
const {
1614 return get_values<ValueType>().at(i);
1617 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1618 typename std::vector<ValueType>::const_iterator
begin()
const {
1620 return get_values<ValueType>().begin();
1623 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1624 typename std::vector<ValueType>::const_iterator
end()
const {
1626 return get_values<ValueType>().end();
1638 #define HALIDE_FORWARD_METHOD(Class, Method) \
1639 template<typename... Args> \
1640 inline auto Method(Args &&...args)->typename std::remove_reference<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))>::type { \
1641 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1644 #define HALIDE_FORWARD_METHOD_CONST(Class, Method) \
1645 template<typename... Args> \
1646 inline auto Method(Args &&...args) const-> \
1647 typename std::remove_reference<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))>::type { \
1648 this->check_gio_access(); \
1649 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1652 template<
typename T>
1660 friend class ::Halide::Func;
1661 friend class ::Halide::Stage;
1664 if (TBase::has_static_halide_type) {
1665 return "Halide::Internal::StubInputBuffer<" +
1669 return "Halide::Internal::StubInputBuffer<>";
1673 template<
typename T2>
1681 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
1687 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Input<Buffer<T>> if T is void or omitted.");
1694 template<
typename... Args>
1697 return Func(*
this)(std::forward<Args>(args)...);
1702 return Func(*
this)(std::move(args));
1705 template<
typename T2>
1707 user_assert(!this->
is_array()) <<
"Cannot assign an array type to a non-array type for Input " << this->
name();
1713 return this->
funcs().at(0);
1740 return Func(*this).
in(other);
1745 return Func(*this).
in(others);
1750 user_assert(!this->
is_array()) <<
"Cannot convert an Input<Buffer<>[]> to an ImageParam; use an explicit subscript operator: " << this->
name();
1754 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1760 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1766 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1772 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1773 typename std::vector<ImageParam>::const_iterator
begin()
const {
1774 user_error <<
"Input<Buffer<>>::begin() is not supported.";
1778 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1779 typename std::vector<ImageParam>::const_iterator
end()
const {
1780 user_error <<
"Input<Buffer<>>::end() is not supported.";
1804 template<
typename T>
1816 template<
typename T2>
1860 template<
typename... Args>
1863 return this->
funcs().at(0)(std::forward<Args>(args)...);
1868 return this->
funcs().at(0)(args);
1873 return this->
funcs().at(0);
1900 return Func(*this).
in(other);
1905 return Func(*this).
in(others);
1926 template<
typename T>
1931 static_assert(std::is_same<
typename std::remove_all_extents<T>::type,
Expr>::value,
"GeneratorInput_DynamicScalar is only legal to use with T=Expr for now");
1941 user_assert(!std::is_array<T>::value) <<
"Input<Expr[]> is not allowed";
1948 return this->
exprs().at(0);
1966 template<
typename T>
1990 template<typename TBase2 = TBase, typename std::enable_if<!std::is_pointer<TBase2>::value>
::type * =
nullptr>
1992 return cast<TBase>(
Expr(value));
1995 template<typename TBase2 = TBase, typename std::enable_if<std::is_pointer<TBase2>::value>
::type * =
nullptr>
1997 user_assert(value == 0) <<
"Zero is the only legal default value for Inputs which are pointer types.\n";
2011 const std::string &
name)
2016 const std::string &
name,
2025 return this->
exprs().at(0);
2035 template<typename T2 = T, typename std::enable_if<std::is_pointer<T2>::value>
::type * =
nullptr>
2038 user_assert(value ==
nullptr) <<
"nullptr is the only valid estimate for Input<PointerType>";
2045 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value && !std::is_pointer<T2>::value>
::type * =
nullptr>
2049 if (std::is_same<T2, bool>::value) {
2057 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2061 if (std::is_same<T2, bool>::value) {
2068 template<
typename T>
2081 if (!std::is_same<TBase, bool>::value) {
2104 const std::string &
name)
2109 const std::string &
name,
2122 const std::string &
name,
2133 template<
typename T2,
typename =
void>
2136 template<
typename T2>
2139 template<typename T, typename TBase = typename std::remove_all_extents<T>::type>
2150 template<
typename T>
2174 : Super(name, def) {
2178 : Super(array_size, name, def) {
2183 : Super(name, def,
min,
max) {
2188 : Super(array_size, name, def,
min,
max) {
2192 : Super(name, t, d) {
2205 : Super(array_size, name, t, d) {
2209 : Super(array_size, name, t) {
2215 : Super(array_size, name, d) {
2219 : Super(array_size, name) {
2223 namespace Internal {
2227 template<typename T2, typename std::enable_if<std::is_same<T2, Func>::value>
::type * =
nullptr>
2229 static_assert(std::is_same<T2, Func>::value,
"Only Func allowed here");
2232 user_assert(
funcs_.size() == 1) <<
"Use [] to access individual Funcs in Output<Func[]>";
2294 #undef HALIDE_OUTPUT_FORWARD
2295 #undef HALIDE_OUTPUT_FORWARD_CONST
2299 const std::string &
name,
2301 const std::vector<Type> &t,
2306 const std::vector<Type> &t,
2329 template<
typename T>
2332 using TBase =
typename std::remove_all_extents<T>::type;
2336 return std::is_array<T>::value;
2339 template<
typename T2 = T,
typename std::enable_if<
2341 !std::is_array<T2>::value>
::type * =
nullptr>
2346 template<
typename T2 = T,
typename std::enable_if<
2348 std::is_array<T2>::value && std::rank<T2>::value == 1 && (std::extent<T2, 0>::value > 0)>::
type * =
nullptr>
2353 template<
typename T2 = T,
typename std::enable_if<
2355 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>
::type * =
nullptr>
2361 template<
typename... Args,
typename T2 = T,
typename std::enable_if<!std::is_array<T2>::value>
::type * =
nullptr>
2364 return get_values<ValueType>().at(0)(std::forward<Args>(args)...);
2367 template<typename ExprOrVar, typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>
::type * =
nullptr>
2370 return get_values<ValueType>().at(0)(args);
2373 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>
::type * =
nullptr>
2376 return get_values<ValueType>().at(0);
2379 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>
::type * =
nullptr>
2382 return get_values<ValueType>().at(0);
2385 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2388 return get_values<ValueType>().size();
2391 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2394 return get_values<ValueType>()[i];
2397 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2400 return get_values<ValueType>().at(i);
2403 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2404 typename std::vector<ValueType>::const_iterator
begin()
const {
2406 return get_values<ValueType>().begin();
2409 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2410 typename std::vector<ValueType>::const_iterator
end()
const {
2412 return get_values<ValueType>().end();
2415 template<
typename T2 = T,
typename std::enable_if<
2417 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>
::type * =
nullptr>
2424 template<
typename T>
2437 <<
"Cannot assign Func \"" << f.
name()
2438 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2439 <<
"Output " << this->
name()
2440 <<
" is declared to have " <<
my_types.size() <<
" tuple elements"
2441 <<
" but Func " << f.
name()
2442 <<
" has " << f.
output_types().size() <<
" tuple elements.\n";
2443 for (
size_t i = 0; i <
my_types.size(); i++) {
2445 <<
"Cannot assign Func \"" << f.
name()
2446 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2447 << (
my_types.size() > 1 ?
"In tuple element " + std::to_string(i) +
", " :
"")
2448 <<
"Output " << this->
name()
2449 <<
" has declared type " <<
my_types[i]
2450 <<
" but Func " << f.
name()
2456 <<
"Cannot assign Func \"" << f.
name()
2457 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2458 <<
"Output " << this->
name()
2459 <<
" has declared dimensionality " << this->
dims()
2460 <<
" but Func " << f.
name()
2461 <<
" has dimensionality " << f.
dimensions() <<
"\n";
2472 static std::vector<Type>
my_types(
const std::vector<Type> &t) {
2473 if (TBase::has_static_halide_type) {
2474 user_assert(t.empty()) <<
"Cannot pass a Type argument for an Output<Buffer> with a non-void static type\n";
2475 return std::vector<Type>{TBase::static_halide_type()};
2489 if (TBase::has_static_halide_type) {
2490 return "Halide::Internal::StubOutputBuffer<" +
2494 return "Halide::Internal::StubOutputBuffer<>";
2498 template<typename T2, typename std::enable_if<!std::is_same<T2, Func>::value>
::type * =
nullptr>
2510 template<
typename T2>
2516 <<
"Cannot assign to the Output \"" << this->
name()
2517 <<
"\": the expression is not convertible to the same Buffer type and/or dimensions.\n";
2521 <<
"Output " << this->
name() <<
" should have type=" << this->
type() <<
" but saw type=" <<
Type(buffer.
type()) <<
"\n";
2525 <<
"Output " << this->
name() <<
" should have dim=" << this->
dims() <<
" but saw dim=" << buffer.dimensions() <<
"\n";
2530 this->
funcs_.at(0)(_) = buffer(_);
2538 template<
typename T2>
2541 assign_from_func(stub_output_buffer.
f);
2550 assign_from_func(f);
2556 user_assert(!this->
is_array()) <<
"Cannot convert an Output<Buffer<>[]> to an ImageParam; use an explicit subscript operator: " << this->
name();
2558 return this->
funcs_.at(0).output_buffer();
2565 this->as<OutputImageParam>().set_estimates(estimates);
2587 template<
typename T>
2594 return this->
funcs_.at(i);
2614 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>
::type * =
nullptr>
2621 get_assignable_func_ref(0) = f;
2626 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2630 return get_assignable_func_ref(i);
2634 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2659 template<
typename T>
2676 template<typename T, typename TBase = typename std::remove_all_extents<T>::type>
2685 template<
typename T>
2703 : Super(array_size, name) {
2707 : Super(name, {}, d) {
2711 : Super(name, {t}, d) {
2715 : Super(name, t, d) {
2719 : Super(array_size, name, {}, d) {
2723 : Super(array_size, name, {t}, d) {
2726 GeneratorOutput(
size_t array_size,
const std::string &name,
const std::vector<Type> &t,
int d)
2727 : Super(array_size, name, t, d) {
2733 template<
typename T2>
2735 Super::operator=(buffer);
2739 template<
typename T2>
2741 Super::operator=(stub_output_buffer);
2746 Super::operator=(f);
2751 namespace Internal {
2753 template<
typename T>
2755 std::istringstream iss(value);
2758 user_assert(!iss.fail() && iss.get() == EOF) <<
"Unable to parse: " << value;
2770 template<
typename T>
2776 if (!error_msg.empty()) {
2779 set_from_string_impl<T>(new_value_string);
2784 return std::string();
2789 return std::string();
2794 return std::string();
2804 static std::unique_ptr<Internal::GeneratorParamBase> make(
2806 const std::string &generator_name,
2807 const std::string &gpname,
2811 std::string error_msg = defined ?
"Cannot set the GeneratorParam " + gpname +
" for " + generator_name +
" because the value is explicitly specified in the C++ source." :
"";
2812 return std::unique_ptr<GeneratorParam_Synthetic<T>>(
2820 template<typename T2 = T, typename std::enable_if<std::is_same<T2, ::Halide::Type>::value>
::type * =
nullptr>
2821 void set_from_string_impl(
const std::string &new_value_string) {
2826 template<typename T2 = T, typename std::enable_if<std::is_integral<T2>::value>
::type * =
nullptr>
2827 void set_from_string_impl(
const std::string &new_value_string) {
2829 gio.
dims_ = parse_scalar<T2>(new_value_string);
2831 gio.
array_size_ = parse_scalar<T2>(new_value_string);
2839 const std::string error_msg;
2842 class GeneratorStub;
2919 template<
typename T>
2921 return T::create(*
this);
2924 template<
typename T,
typename... Args>
2925 inline std::unique_ptr<T>
apply(
const Args &...args)
const {
2926 auto t = this->create<T>();
2978 template<
typename T>
2980 return Halide::cast<T>(e);
2985 template<
typename T>
2987 template<
typename T =
void>
2989 template<
typename T>
3005 namespace Internal {
3007 template<
typename... Args>
3013 template<
typename T,
typename... Args>
3015 static const bool value = !std::is_convertible<T, Realization>::value &&
NoRealizations<Args...>::value;
3043 std::set<std::string> names;
3046 std::vector<Internal::GeneratorParamBase *> filter_generator_params;
3049 std::vector<Internal::GeneratorInputBase *> filter_inputs;
3052 std::vector<Internal::GeneratorOutputBase *> filter_outputs;
3057 std::vector<std::unique_ptr<Internal::GeneratorParamBase>> owned_synthetic_params;
3060 std::vector<std::unique_ptr<Internal::GIOBase>> owned_extras;
3068 return filter_generator_params;
3070 const std::vector<Internal::GeneratorInputBase *> &
inputs()
const {
3071 return filter_inputs;
3073 const std::vector<Internal::GeneratorOutputBase *> &
outputs()
const {
3074 return filter_outputs;
3092 template<
typename data_t>
3130 template<
typename... Args>
3135 <<
"Expected exactly " << pi.
inputs().size()
3136 <<
" inputs but got " <<
sizeof...(args) <<
"\n";
3137 set_inputs_vector(build_inputs(std::forward_as_tuple<const Args &...>(args...), std::make_index_sequence<
sizeof...(Args)>{}));
3141 this->check_scheduled(
"realize");
3147 template<
typename... Args,
typename std::enable_if<
NoRealizations<Args...>::value>::type * =
nullptr>
3149 this->check_scheduled(
"realize");
3154 this->check_scheduled(
"realize");
3166 template<
typename T,
3167 typename std::enable_if<!std::is_arithmetic<T>::value>::type * =
nullptr>
3171 p->generator =
this;
3172 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3173 param_info_ptr->filter_inputs.push_back(p);
3178 template<
typename T,
3179 typename std::enable_if<T::has_static_halide_type>::type * =
nullptr>
3183 p->generator =
this;
3184 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3185 param_info_ptr->filter_inputs.push_back(p);
3190 template<
typename T,
3191 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3195 p->generator =
this;
3196 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3197 param_info_ptr->filter_inputs.push_back(p);
3202 template<
typename T,
3203 typename std::enable_if<std::is_same<T, Expr>::value>::type * =
nullptr>
3207 p->generator =
this;
3209 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3210 param_info_ptr->filter_inputs.push_back(p);
3215 template<
typename T,
3216 typename std::enable_if<!std::is_arithmetic<T>::value>::type * =
nullptr>
3220 p->generator =
this;
3221 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3222 param_info_ptr->filter_outputs.push_back(p);
3227 template<
typename T,
3228 typename std::enable_if<T::has_static_halide_type>::type * =
nullptr>
3232 p->generator =
this;
3233 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3234 param_info_ptr->filter_outputs.push_back(p);
3238 template<
typename... Args>
3269 template<
typename T>
3272 template<
typename T>
3320 std::unique_ptr<GeneratorParamInfo> param_info_ptr;
3322 mutable std::shared_ptr<ExternsMap> externs_map;
3324 bool inputs_set{
false};
3325 std::string generator_registered_name, generator_stub_name;
3333 void check_scheduled(
const char *m)
const;
3335 void build_params(
bool force =
false);
3348 std::vector<Func> get_outputs(
const std::string &n);
3350 void set_inputs_vector(
const std::vector<std::vector<StubInput>> &inputs);
3360 template<
typename T>
3361 std::vector<StubInput> build_input(
size_t i,
const Buffer<T> &arg) {
3362 auto *in = param_info().
inputs().at(i);
3363 check_input_is_singular(in);
3364 const auto k = in->kind();
3372 f(Halide::_) = arg(Halide::_);
3385 template<
typename T>
3386 std::vector<StubInput> build_input(
size_t i,
const GeneratorInput<Buffer<T>> &arg) {
3387 auto *in = param_info().
inputs().at(i);
3388 check_input_is_singular(in);
3389 const auto k = in->kind();
3391 StubInputBuffer<> sib = arg;
3405 std::vector<StubInput> build_input(
size_t i,
const Func &arg) {
3406 auto *in = param_info().
inputs().at(i);
3408 check_input_is_singular(in);
3415 std::vector<StubInput> build_input(
size_t i,
const std::vector<Func> &arg) {
3416 auto *in = param_info().
inputs().at(i);
3418 check_input_is_array(in);
3420 std::vector<StubInput> siv;
3421 siv.reserve(arg.size());
3422 for (
const auto &f : arg) {
3423 siv.emplace_back(f);
3429 std::vector<StubInput> build_input(
size_t i,
const Expr &arg) {
3430 auto *in = param_info().
inputs().at(i);
3432 check_input_is_singular(in);
3438 std::vector<StubInput> build_input(
size_t i,
const std::vector<Expr> &arg) {
3439 auto *in = param_info().
inputs().at(i);
3441 check_input_is_array(in);
3442 std::vector<StubInput> siv;
3443 siv.reserve(arg.size());
3444 for (
const auto &value : arg) {
3445 siv.emplace_back(value);
3452 template<
typename T,
3453 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3454 std::vector<StubInput> build_input(
size_t i,
const T &arg) {
3455 auto *in = param_info().
inputs().at(i);
3457 check_input_is_singular(in);
3465 template<
typename T,
3466 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3467 std::vector<StubInput> build_input(
size_t i,
const std::vector<T> &arg) {
3468 auto *in = param_info().
inputs().at(i);
3470 check_input_is_array(in);
3471 std::vector<StubInput> siv;
3472 siv.reserve(arg.size());
3473 for (
const auto &value : arg) {
3477 siv.emplace_back(e);
3482 template<
typename... Args,
size_t... Indices>
3483 std::vector<std::vector<StubInput>> build_inputs(
const std::tuple<const Args &...> &t, std::index_sequence<Indices...>) {
3484 return {build_input(Indices, std::get<Indices>(t))...};
3501 static std::unique_ptr<GeneratorBase>
create(
const std::string &name,
3505 using GeneratorFactoryMap = std::map<const std::string, GeneratorFactory>;
3507 GeneratorFactoryMap factories;
3535 auto g = std::unique_ptr<T>(
new T());
3536 g->init_from_context(context);
3542 const std::string ®istered_name,
3543 const std::string &stub_name) {
3544 auto g =
create(context);
3545 g->set_generator_names(registered_name, stub_name);
3552 template<
typename... Args>
3558 static_assert(has_generate_method<T>::value,
"apply() is not supported for old-style Generators.");
3570 struct type_sink {
typedef void type; };
3572 template<
typename T2,
typename =
void>
3573 struct has_configure_method : std::false_type {};
3575 template<
typename T2>
3576 struct has_configure_method<T2, typename type_sink<decltype(std::declval<T2>().configure())>::type> : std::true_type {};
3578 template<
typename T2,
typename =
void>
3579 struct has_generate_method : std::false_type {};
3581 template<
typename T2>
3582 struct has_generate_method<T2, typename type_sink<decltype(std::declval<T2>().generate())>::type> : std::true_type {};
3584 template<
typename T2,
typename =
void>
3585 struct has_schedule_method : std::false_type {};
3587 template<
typename T2>
3588 struct has_schedule_method<T2, typename type_sink<decltype(std::declval<T2>().
schedule())>::type> : std::true_type {};
3590 template<
typename T2 = T,
3591 typename std::enable_if<!has_generate_method<T2>::value>::type * =
nullptr>
3602 Pipeline build_pipeline_impl(
double) {
3603 static_assert(!has_configure_method<T2>::value,
"The configure() method is ignored if you define a build() method; use generate() instead.");
3604 static_assert(!has_schedule_method<T2>::value,
"The schedule() method is ignored if you define a build() method; use generate() instead.");
3611 template<
typename T2 = T,
3612 typename = decltype(std::declval<T2>().generate())>
3613 Pipeline build_pipeline_impl(
int) {
3619 ((T *)
this)->call_generate_impl(0);
3620 ((T *)
this)->call_schedule_impl(0, 0);
3627 void call_configure_impl(
double,
double) {
3634 template<
typename T2 = T,
3635 typename = decltype(std::declval<T2>().generate())>
3636 void call_configure_impl(
double,
int) {
3639 static_assert(!has_configure_method<T2>::value,
"Did not expect a configure method here.");
3643 template<
typename T2 = T,
3644 typename = decltype(std::declval<T2>().generate()),
3645 typename = decltype(std::declval<T2>().configure())>
3646 void call_configure_impl(
int,
int) {
3648 static_assert(std::is_void<decltype(t->configure())>::value,
"configure() must return void");
3657 void call_generate_impl(
double) {
3661 template<
typename T2 = T,
3662 typename = decltype(std::declval<T2>().generate())>
3663 void call_generate_impl(
int) {
3665 static_assert(std::is_void<decltype(t->generate())>::value,
"generate() must return void");
3674 void call_schedule_impl(
double,
double) {
3678 template<
typename T2 = T,
3679 typename = decltype(std::declval<T2>().generate())>
3680 void call_schedule_impl(
double,
int) {
3686 template<
typename T2 = T,
3687 typename = decltype(std::declval<T2>().generate()),
3688 typename = decltype(std::declval<T2>().
schedule())>
3689 void call_schedule_impl(
int,
int) {
3691 static_assert(std::is_void<decltype(t->schedule())>::value,
"schedule() must return void");
3699 return this->build_pipeline_impl(0);
3703 this->call_configure_impl(0, 0);
3707 this->call_generate_impl(0);
3711 this->call_schedule_impl(0, 0);
3717 friend class ::Halide::GeneratorContext;
3741 const std::vector<std::vector<Internal::StubInput>> &inputs);
3743 const std::vector<std::vector<Internal::StubInput>> &inputs);
3750 template<
typename T2>
3753 std::vector<T2> result;
3768 template<
typename T =
void>
3773 template<
typename T>
3775 std::vector<StubInput> r;
3776 std::copy(v.begin(), v.end(), std::back_inserter(r));
3796 struct halide_global_ns;
3799 #define _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
3800 namespace halide_register_generator { \
3801 struct halide_global_ns; \
3802 namespace GEN_REGISTRY_NAME##_ns { \
3803 std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext &context); \
3804 std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext &context) { \
3805 return GEN_CLASS_NAME::create(context, #GEN_REGISTRY_NAME, #FULLY_QUALIFIED_STUB_NAME); \
3808 static auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
3810 static_assert(std::is_same<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>::value, \
3811 "HALIDE_REGISTER_GENERATOR must be used at global scope");
3813 #define _HALIDE_REGISTER_GENERATOR2(GEN_CLASS_NAME, GEN_REGISTRY_NAME) \
3814 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, GEN_REGISTRY_NAME)
3816 #define _HALIDE_REGISTER_GENERATOR3(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
3817 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME)
3822 #define __HALIDE_REGISTER_ARGCOUNT_IMPL(_1, _2, _3, COUNT, ...) \
3825 #define _HALIDE_REGISTER_ARGCOUNT_IMPL(ARGS) \
3826 __HALIDE_REGISTER_ARGCOUNT_IMPL ARGS
3828 #define _HALIDE_REGISTER_ARGCOUNT(...) \
3829 _HALIDE_REGISTER_ARGCOUNT_IMPL((__VA_ARGS__, 3, 2, 1, 0))
3831 #define ___HALIDE_REGISTER_CHOOSER(COUNT) \
3832 _HALIDE_REGISTER_GENERATOR##COUNT
3834 #define __HALIDE_REGISTER_CHOOSER(COUNT) \
3835 ___HALIDE_REGISTER_CHOOSER(COUNT)
3837 #define _HALIDE_REGISTER_CHOOSER(COUNT) \
3838 __HALIDE_REGISTER_CHOOSER(COUNT)
3840 #define _HALIDE_REGISTER_GENERATOR_PASTE(A, B) \
3843 #define HALIDE_REGISTER_GENERATOR(...) \
3844 _HALIDE_REGISTER_GENERATOR_PASTE(_HALIDE_REGISTER_CHOOSER(_HALIDE_REGISTER_ARGCOUNT(__VA_ARGS__)), (__VA_ARGS__))
3860 #define HALIDE_REGISTER_GENERATOR_ALIAS(GEN_REGISTRY_NAME, ORIGINAL_REGISTRY_NAME, ...) \
3861 namespace halide_register_generator { \
3862 struct halide_global_ns; \
3863 namespace ORIGINAL_REGISTRY_NAME##_ns { \
3864 std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext &context); \
3866 namespace GEN_REGISTRY_NAME##_ns { \
3867 std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext &context); \
3868 std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext &context) { \
3869 auto g = ORIGINAL_REGISTRY_NAME##_ns::factory(context); \
3870 g->set_generator_param_values(__VA_ARGS__); \
3874 static auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
3876 static_assert(std::is_same<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>::value, \
3877 "HALIDE_REGISTER_GENERATOR_ALIAS must be used at global scope");
#define internal_assert(c)
Defines Func - the front-end handle on a halide function, and related classes.
#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE)
#define HALIDE_FORWARD_METHOD(Class, Method)
#define HALIDE_FORWARD_METHOD_CONST(Class, Method)
#define HALIDE_ALWAYS_INLINE
Classes for declaring image parameters to halide pipelines.
Defines methods for introspecting in C++.
Provides a single global registry of Generators, GeneratorParams, and Params indexed by this pointer.
Defines the structure that describes a Halide target.
#define HALIDE_NO_USER_CODE_INLINE
A Halide::Buffer is a named shared reference to a Halide::Runtime::Buffer.
bool defined() const
Check if this Buffer refers to an existing Buffer.
const std::string & name() const
Helper class for identifying purpose of an Expr passed to memoize.
bool defined() const
Does this function have at least a pure definition.
int dimensions() const
The dimensionality (number of arguments) of this function.
Func & set_estimates(const Region &estimates)
Set (min, extent) estimates for all dimensions in the Func at once; this is equivalent to calling set...
Realization realize(std::vector< int32_t > sizes={}, const Target &target=Target(), const ParamMap ¶m_map=ParamMap::empty_map())
Evaluate this function over some rectangular domain and return the resulting buffer or buffers.
const std::string & name() const
The name of this function, either given during construction, or automatically generated.
const std::vector< Type > & output_types() const
Get the types of the outputs of this Func.
Func in(const Func &f)
Creates and returns a new identity Func that wraps this Func.
Func & set_estimate(const Var &var, const Expr &min, const Expr &extent)
Statically declare the range over which the function will be evaluated in the general case.
A fragment of front-end syntax of the form f(x, y, z), where x, y, z are Vars or Exprs.
GeneratorContext is a base class that is used when using Generators (or Stubs) directly; it is used t...
GeneratorContext(GeneratorContext &&)=delete
std::map< std::string, ExternalCode > ExternsMap
std::shared_ptr< Internal::ValueTracker > value_tracker
std::unique_ptr< T > apply(const Args &...args) const
GeneratorContext & operator=(const GeneratorContext &)=delete
GeneratorParam< bool > auto_schedule
virtual void init_from_context(const Halide::GeneratorContext &context)
std::unique_ptr< T > create() const
bool get_auto_schedule() const
std::shared_ptr< Internal::ValueTracker > get_value_tracker() const
std::shared_ptr< ExternsMap > get_externs_map() const
Generators can register ExternalCode objects onto themselves.
Target get_target() const
GeneratorParam< MachineParams > machine_params
GeneratorContext(const Target &t, bool auto_schedule=false, const MachineParams &machine_params=MachineParams::generic())
virtual ~GeneratorContext()=default
std::shared_ptr< ExternsMap > externs_map
GeneratorContext & operator=(GeneratorContext &&)=delete
GeneratorContext(const GeneratorContext &)=delete
GeneratorParam< Target > target
MachineParams get_machine_params() const
void call_generate() override
Generator(Generator &&that)=delete
void call_schedule() override
static std::unique_ptr< T > create(const Halide::GeneratorContext &context)
Generator & operator=(Generator &&that)=delete
Generator & operator=(const Generator &)=delete
void apply(const Args &...args)
static std::unique_ptr< T > create(const Halide::GeneratorContext &context, const std::string ®istered_name, const std::string &stub_name)
void call_configure() override
Pipeline build_pipeline() override
Generator(const Generator &)=delete
typename Super::TBase TBase
GeneratorOutput(const std::string &name)
GeneratorOutput(const std::string &name, const std::vector< Type > &t, int d)
GeneratorOutput(const char *name)
GeneratorOutput(size_t array_size, const std::string &name, int d)
GeneratorOutput(size_t array_size, const std::string &name, const Type &t, int d)
GeneratorOutput(const std::string &name, const Type &t, int d)
GeneratorOutput< T > & operator=(const Internal::StubOutputBuffer< T2 > &stub_output_buffer)
GeneratorOutput(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
GeneratorOutput(const std::string &name, int d)
GeneratorOutput(size_t array_size, const std::string &name)
GeneratorOutput< T > & operator=(const Func &f)
GeneratorOutput< T > & operator=(Buffer< T2 > &buffer)
GeneratorParam is a templated class that can be used to modify the behavior of the Generator at code-...
GeneratorParam(const std::string &name, const std::string &value)
GeneratorParam(const std::string &name, const T &value, const T &min, const T &max)
GeneratorParam(const std::string &name, const T &value)
GeneratorParam(const std::string &name, const T &value, const std::map< std::string, T > &enum_map)
An Image parameter to a halide pipeline.
A reference-counted handle to Halide's internal representation of a function.
GIOBase is the base class for all GeneratorInput<> and GeneratorOutput<> instantiations; it is not pa...
size_t array_size() const
const std::vector< Func > & funcs() const
GIOBase & operator=(const GIOBase &)=delete
void check_matching_dims(int d) const
GIOBase(size_t array_size, const std::string &name, IOKind kind, const std::vector< Type > &types, int dims)
bool array_size_defined() const
virtual const char * input_or_output() const =0
bool dims_defined() const
GIOBase & operator=(GIOBase &&)=delete
std::vector< Type > types_
const std::vector< ElemType > & get_values() const
void check_matching_types(const std::vector< Type > &t) const
const std::vector< Type > & types() const
std::string array_name(size_t i) const
virtual void check_value_writable() const =0
GIOBase(const GIOBase &)=delete
void check_matching_array_size(size_t size) const
const std::vector< Expr > & exprs() const
GIOBase(GIOBase &&)=delete
void check_gio_access() const
void set_dimensions(int dims)
void set_array_size(int size)
std::vector< Func > funcs_
const std::string & name() const
bool types_defined() const
virtual bool is_array() const
virtual void verify_internals()
virtual ~GIOBase()=default
std::vector< Expr > exprs_
void set_type(const Type &type)
GeneratorBase * generator
void ensure_configure_has_been_called()
virtual void call_schedule()=0
GeneratorInput< T > * add_input(const std::string &name, const Type &t, int dimensions)
GeneratorBase(size_t size, const void *introspection_helper)
void init_from_context(const Halide::GeneratorContext &context) override
HALIDE_NO_USER_CODE_INLINE void add_requirement(Expr condition, Args &&...args)
GeneratorInput< T > * add_input(const std::string &name)
Realization realize(Args &&...args)
Module build_module(const std::string &function_name="", LinkageType linkage_type=LinkageType::ExternalPlusMetadata)
GeneratorBase(const GeneratorBase &)=delete
virtual void call_generate()=0
GeneratorInput< T > * add_input(const std::string &name, const Type &type)
int natural_vector_size() const
Given a data type, return an estimate of the "natural" vector size for that data type when compiling ...
GeneratorInput< T > * add_input(const std::string &name, int dimensions)
~GeneratorBase() override
void check_exact_phase(Phase expected_phase) const
void check_min_phase(Phase expected_phase) const
void realize(Realization r)
enum Halide::Internal::GeneratorBase::Phase Created
void set_generator_names(const std::string ®istered_name, const std::string &stub_name)
Realization realize(std::vector< int32_t > sizes)
GeneratorOutput< T > * add_output(const std::string &name, const Type &t, int dimensions)
Module build_gradient_module(const std::string &function_name)
Build a module that is suitable for using for gradient descent calculation in TensorFlow or PyTorch.
virtual void call_configure()=0
GeneratorBase(GeneratorBase &&that)=delete
GeneratorBase & operator=(const GeneratorBase &)=delete
GeneratorOutput< T > * add_output(const std::string &name, int dimensions)
void emit_cpp_stub(const std::string &stub_file_path)
virtual Pipeline build_pipeline()=0
void set_inputs(const Args &...args)
set_inputs is a variadic wrapper around set_inputs_vector, which makes usage much simpler in many cas...
void set_generator_param_values(const GeneratorParamsMap ¶ms)
int natural_vector_size(Halide::Type t) const
Given a data type, return an estimate of the "natural" vector size for that data type when compiling ...
void track_parameter_values(bool include_outputs)
void advance_phase(Phase new_phase)
GeneratorBase & operator=(GeneratorBase &&that)=delete
GeneratorOutput_Arithmetic(const std::string &name)
GeneratorOutput_Arithmetic(size_t array_size, const std::string &name)
GeneratorOutput_Buffer< T > & set_estimates(const Region &estimates)
GeneratorOutput_Buffer< T > & operator=(const Func &f)
HALIDE_NO_USER_CODE_INLINE std::string get_c_type() const override
GeneratorOutput_Buffer< T > & operator=(const StubOutputBuffer< T2 > &stub_output_buffer)
HALIDE_NO_USER_CODE_INLINE GeneratorOutput_Buffer< T > & operator=(Buffer< T2 > &buffer)
GeneratorOutput_Buffer(size_t array_size, const std::string &name, const std::vector< Type > &t={}, int d=-1)
HALIDE_NO_USER_CODE_INLINE T2 as() const
static std::vector< Type > my_types(const std::vector< Type > &t)
GeneratorOutput_Buffer(const std::string &name, const std::vector< Type > &t={}, int d=-1)
GeneratorOutput_Func< T > & set_estimate(const Var &var, const Expr &min, const Expr &extent)
GeneratorOutput_Func(const std::string &name)
GeneratorOutput_Func(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
GeneratorOutput_Func< T > & set_estimates(const Region &estimates)
Func & operator[](size_t i)
GeneratorOutput_Func< T > & operator=(const Func &f)
GeneratorOutput_Func(const std::string &name, const std::vector< Type > &t, int d=-1)
const Func & operator[](size_t i) const
~GeneratorOutputBase() override
GeneratorOutputBase(size_t array_size, const std::string &name, IOKind kind, const std::vector< Type > &t, int d)
Forward schedule-related methods to the underlying Func.
GeneratorOutputBase(const std::string &name, IOKind kind, const std::vector< Type > &t, int d)
virtual std::string get_c_type() const
HALIDE_NO_USER_CODE_INLINE T2 as() const
const char * input_or_output() const override
void check_value_writable() const override
GeneratorOutputImpl(const std::string &name, IOKind kind, const std::vector< Type > &t, int d)
std::vector< ValueType >::const_iterator begin() const
const ValueType & at(size_t i) const
const ValueType & operator[](size_t i) const
bool is_array() const override
std::vector< ValueType >::const_iterator end() const
FuncRef operator()(std::vector< ExprOrVar > args) const
typename std::remove_all_extents< T >::type TBase
FuncRef operator()(Args &&...args) const
void set_from_string(const std::string &new_value_string) override
std::string get_c_type() const override
GeneratorParam_Arithmetic(const std::string &name, const T &value, const T &min=std::numeric_limits< T >::lowest(), const T &max=std::numeric_limits< T >::max())
std::string get_default_value() const override
std::string call_to_string(const std::string &v) const override
void set_impl(const T &new_value) override
void set_from_string(const std::string &new_value_string) override
std::string get_default_value() const override
std::string call_to_string(const std::string &v) const override
GeneratorParam_Bool(const std::string &name, const T &value)
std::string get_c_type() const override
std::string call_to_string(const std::string &v) const override
std::string get_default_value() const override
GeneratorParam_Enum(const std::string &name, const T &value, const std::map< std::string, T > &enum_map)
void set_from_string(const std::string &new_value_string) override
std::string get_c_type() const override
std::string get_type_decls() const override
GeneratorParam_LoopLevel(const std::string &name, const LoopLevel &value)
std::string get_c_type() const override
std::string call_to_string(const std::string &v) const override
bool is_looplevel_param() const override
void set(const LoopLevel &value) override
void set_from_string(const std::string &new_value_string) override
std::string get_default_value() const override
GeneratorParam_MachineParams(const std::string &name, const T &value)
std::string get_c_type() const override
std::string call_to_string(const std::string &v) const override
std::string get_default_value() const override
void set_from_string(const std::string &new_value_string) override
GeneratorParam_String(const std::string &name, const std::string &value)
std::string get_c_type() const override
void set_from_string(const std::string &new_value_string) override
std::string get_default_value() const override
std::string call_to_string(const std::string &v) const override
bool is_synthetic_param() const override
std::string call_to_string(const std::string &v) const override
void set_from_string(const std::string &new_value_string) override
std::string get_default_value() const override
std::string get_c_type() const override
void set_from_string(const std::string &new_value_string) override
GeneratorParam_Target(const std::string &name, const T &value)
std::string get_c_type() const override
std::string get_default_value() const override
std::string call_to_string(const std::string &v) const override
std::string get_type_decls() const override
std::string get_c_type() const override
std::string call_to_string(const std::string &v) const override
std::string get_default_value() const override
GeneratorParam_Type(const std::string &name, const T &value)
const std::string & name() const
void check_value_readable() const
virtual bool is_synthetic_param() const
GeneratorParamBase(GeneratorParamBase &&)=delete
GeneratorParamBase & operator=(const GeneratorParamBase &)=delete
virtual std::string call_to_string(const std::string &v) const =0
void fail_wrong_type(const char *type)
GeneratorParamBase & operator=(GeneratorParamBase &&)=delete
virtual ~GeneratorParamBase()
virtual std::string get_type_decls() const
GeneratorParamBase(const std::string &name)
virtual std::string get_default_value() const =0
void set(const std::string &new_value)
GeneratorParamBase(const GeneratorParamBase &)=delete
virtual std::string get_c_type() const =0
virtual bool is_looplevel_param() const
virtual void set_from_string(const std::string &value_string)=0
void check_value_writable() const
void set(const char *new_value)
void set(const std::string &new_value)
GeneratorParamImpl(const std::string &name, const T &value)
virtual void set_impl(const T &new_value)
const std::vector< Internal::GeneratorParamBase * > & generator_params() const
const std::vector< Internal::GeneratorInputBase * > & inputs() const
GeneratorParamInfo(GeneratorBase *generator, size_t size)
const std::vector< Internal::GeneratorOutputBase * > & outputs() const
GeneratorRegistry & operator=(const GeneratorRegistry &)=delete
GeneratorRegistry(const GeneratorRegistry &)=delete
static std::unique_ptr< GeneratorBase > create(const std::string &name, const Halide::GeneratorContext &context)
GeneratorRegistry(GeneratorRegistry &&that)=delete
GeneratorRegistry & operator=(GeneratorRegistry &&that)=delete
static std::vector< std::string > enumerate()
static void register_factory(const std::string &name, GeneratorFactory generator_factory)
static void unregister_factory(const std::string &name)
static std::vector< StubInput > to_stub_input_vector(const Expr &e)
std::vector< std::vector< Func > > generate(const GeneratorParamsMap &generator_params, const std::vector< std::vector< Internal::StubInput >> &inputs)
GeneratorStub(const GeneratorContext &context, const GeneratorFactory &generator_factory, const GeneratorParamsMap &generator_params, const std::vector< std::vector< Internal::StubInput >> &inputs)
std::vector< Func > get_outputs(const std::string &n) const
static std::vector< StubInput > to_stub_input_vector(const Func &f)
std::shared_ptr< GeneratorBase > generator
GeneratorStub(const GeneratorContext &context, const GeneratorFactory &generator_factory)
static std::vector< StubInput > to_stub_input_vector(const StubInputBuffer< T > &b)
std::vector< T2 > get_output_buffers(const std::string &n) const
static std::vector< StubInput > to_stub_input_vector(const std::vector< T > &v)
A reference-counted handle to a parameter to a halide pipeline.
void set_estimate(Expr e)
void set_buffer(const Buffer< void > &b)
If the parameter is a buffer parameter, set its current value.
HALIDE_NO_USER_CODE_INLINE void set_scalar(T val)
If the parameter is a scalar parameter, set its current value.
void set_default_value(const Expr &e)
Get and set the default values for scalar parameters.
Type type() const
Get the type of this parameter.
void set_min_value(const Expr &e)
Get and set constraints for scalar parameters.
int dimensions() const
Get the dimensionality of this parameter.
void set_max_value(const Expr &e)
RegisterGenerator(const char *registered_name, GeneratorFactory generator_factory)
Target get_target() const
Realization realize(Args &&...args)
StubOutputBufferBase(const Func &f, const std::shared_ptr< GeneratorBase > &generator)
std::shared_ptr< GeneratorBase > generator
void check_scheduled(const char *m) const
Realization realize(std::vector< int32_t > sizes)
StubOutputBuffer is the placeholder that a Stub uses when it requires a Buffer for an output (rather ...
StubOutputBuffer()=default
ValueTracker is an internal utility class that attempts to track and flag certain obvious Stub-relate...
void track_values(const std::string &name, const std::vector< Expr > &values)
ValueTracker(size_t max_unique_values=2)
A reference to a site in a Halide statement at the top of the body of a particular for loop.
static LoopLevel root()
Construct a special LoopLevel value which represents the location outside of all for loops.
static LoopLevel inlined()
Construct a special LoopLevel value that implies that a function should be inlined away.
void set(const LoopLevel &other)
Mutate our contents to match the contents of 'other'.
static Type Bool(int lanes=1)
static Expr cast(Halide::Type t, Expr e)
static Type UInt(int bits, int lanes=1)
static Type Int(int bits, int lanes=1)
static Type Float(int bits, int lanes=1)
Halide::Pipeline Pipeline
A handle on the output buffer of a pipeline.
A scalar parameter to a halide pipeline.
A class representing a Halide pipeline.
void add_requirement(const Expr &condition, std::vector< Expr > &error)
Add a top-level precondition to the generated pipeline, expressed as a boolean Expr.
void trace_pipeline()
Generate begin_pipeline and end_pipeline tracing calls for this pipeline.
Realization realize(std::vector< int32_t > sizes={}, const Target &target=Target(), const ParamMap ¶m_map=ParamMap::empty_map())
See Func::realize.
A multi-dimensional domain over which to iterate.
A reduction variable represents a single dimension of a reduction domain (RDom).
A Realization is a vector of references to existing Buffer objects.
A single definition of a Func.
Create a small array of Exprs for defining and calling functions with multiple outputs.
A Halide variable, to be used when defining functions.
auto max_forward(const Other &a, const GeneratorParam< T > &b) -> decltype(max(a,(T) b))
auto min_forward(const Other &a, const GeneratorParam< T > &b) -> decltype(min(a,(T) b))
const void * get_introspection_helper()
Return the address of a global with type T *.
std::string halide_type_to_enum_string(const Type &t)
typename select_type< cond< std::is_same< T, Target >::value, GeneratorParam_Target< T > >, cond< std::is_same< T, MachineParams >::value, GeneratorParam_MachineParams< T > >, cond< std::is_same< T, LoopLevel >::value, GeneratorParam_LoopLevel >, cond< std::is_same< T, std::string >::value, GeneratorParam_String< T > >, cond< std::is_same< T, Type >::value, GeneratorParam_Type< T > >, cond< std::is_same< T, bool >::value, GeneratorParam_Bool< T > >, cond< std::is_arithmetic< T >::value, GeneratorParam_Arithmetic< T > >, cond< std::is_enum< T >::value, GeneratorParam_Enum< T > >>::type GeneratorParamImplBase
Expr make_const(Type t, int64_t val)
Construct an immediate of the given type from any numeric C++ type.
std::string halide_type_to_c_source(const Type &t)
std::function< std::unique_ptr< GeneratorBase >(const GeneratorContext &)> GeneratorFactory
std::vector< Type > parse_halide_type_list(const std::string &types)
HALIDE_NO_USER_CODE_INLINE std::string enum_to_string(const std::map< std::string, T > &enum_map, const T &t)
std::map< std::string, StringOrLoopLevel > GeneratorParamsMap
std::string halide_type_to_c_type(const Type &t)
std::vector< Expr > parameter_constraints(const Parameter &p)
std::string print_loop_nest(const std::vector< Function > &output_funcs)
Emit some simple pseudocode that shows the structure of the loop nest specified by this pipeline's sc...
typename select_type< cond< has_static_halide_type_method< TBase >::value, GeneratorOutput_Buffer< T > >, cond< std::is_same< TBase, Func >::value, GeneratorOutput_Func< T > >, cond< std::is_arithmetic< TBase >::value, GeneratorOutput_Arithmetic< T > >>::type GeneratorOutputImplBase
typename select_type< cond< has_static_halide_type_method< TBase >::value, GeneratorInput_Buffer< T > >, cond< std::is_same< TBase, Func >::value, GeneratorInput_Func< T > >, cond< std::is_arithmetic< TBase >::value, GeneratorInput_Arithmetic< T > >, cond< std::is_scalar< TBase >::value, GeneratorInput_Scalar< T > >, cond< std::is_same< TBase, Expr >::value, GeneratorInput_DynamicScalar< T > >>::type GeneratorInputImplBase
int generate_filter_main(int argc, char **argv, std::ostream &cerr)
generate_filter_main() is a convenient wrapper for GeneratorRegistry::create() + compile_to_files(); ...
T parse_scalar(const std::string &value)
const std::map< std::string, Halide::Type > & get_halide_type_enum_map()
T enum_from_string(const std::map< std::string, T > &enum_map, const std::string &s)
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
auto operator>=(const Other &a, const GeneratorParam< T > &b) -> decltype(a >=(T) b)
Greater than or equal comparison between GeneratorParam<T> and any type that supports operator>= with...
Target get_host_target()
Return the target corresponding to the host machine.
Type UInt(int bits, int lanes=1)
Constructing an unsigned integer type.
Expr reinterpret(Type t, Expr e)
Reinterpret the bits of one value as another type.
Type Float(int bits, int lanes=1)
Construct a floating-point type.
auto operator==(const Other &a, const GeneratorParam< T > &b) -> decltype(a==(T) b)
Equality comparison between GeneratorParam<T> and any type that supports operator== with T.
LinkageType
Type of linkage a function in a lowered Halide module can have.
@ ExternalPlusMetadata
Visible externally. Argument metadata and an argv wrapper are also generated.
@ Internal
Not visible externally, similar to 'static' linkage in C.
auto operator<(const Other &a, const GeneratorParam< T > &b) -> decltype(a<(T) b)
Less than comparison between GeneratorParam<T> and any type that supports operator< with T.
auto operator*(const Other &a, const GeneratorParam< T > &b) -> decltype(a *(T) b)
Multiplication between GeneratorParam<T> and any type that supports operator* with T.
auto operator||(const Other &a, const GeneratorParam< T > &b) -> decltype(a||(T) b)
Logical or between between GeneratorParam<T> and any type that supports operator|| with T.
PrefetchBoundStrategy
Different ways to handle accesses outside the original extents in a prefetch.
auto min(const GeneratorParam< T > &a, const Other &b) -> decltype(Internal::GeneratorMinMax::min_forward(a, b))
auto operator-(const Other &a, const GeneratorParam< T > &b) -> decltype(a -(T) b)
Subtraction between GeneratorParam<T> and any type that supports operator- with T.
Expr cast(Expr a)
Cast an expression to the halide type corresponding to the C++ type T.
auto operator!(const GeneratorParam< T > &a) -> decltype(!(T) a)
Not operator for GeneratorParam.
TailStrategy
Different ways to handle a tail case in a split when the factor does not provably divide the extent.
Type Int(int bits, int lanes=1)
Constructing a signed integer type.
auto operator+(const Other &a, const GeneratorParam< T > &b) -> decltype(a+(T) b)
Addition between GeneratorParam<T> and any type that supports operator+ with T.
Expr min(const FuncRef &a, const FuncRef &b)
Explicit overloads of min and max for FuncRef.
auto operator&&(const Other &a, const GeneratorParam< T > &b) -> decltype(a &&(T) b)
Logical and between between GeneratorParam<T> and any type that supports operator&& with T.
auto operator%(const Other &a, const GeneratorParam< T > &b) -> decltype(a %(T) b)
Modulo between GeneratorParam<T> and any type that supports operator% with T.
NameMangling
An enum to specify calling convention for extern stages.
Target get_jit_target_from_environment()
Return the target that Halide will use for jit-compilation.
auto operator<=(const Other &a, const GeneratorParam< T > &b) -> decltype(a<=(T) b)
Less than or equal comparison between GeneratorParam<T> and any type that supports operator<= with T.
Target get_target_from_environment()
Return the target that Halide will use.
auto operator>(const Other &a, const GeneratorParam< T > &b) -> decltype(a >(T) b)
Greater than comparison between GeneratorParam<T> and any type that supports operator> with T.
auto operator!=(const Other &a, const GeneratorParam< T > &b) -> decltype(a !=(T) b)
Inequality comparison between between GeneratorParam<T> and any type that supports operator!...
Type Bool(int lanes=1)
Construct a boolean type.
std::vector< Range > Region
A multi-dimensional box.
auto operator/(const Other &a, const GeneratorParam< T > &b) -> decltype(a/(T) b)
Division between GeneratorParam<T> and any type that supports operator/ with T.
Expr max(const FuncRef &a, const FuncRef &b)
auto max(const GeneratorParam< T > &a, const Other &b) -> decltype(Internal::GeneratorMinMax::max_forward(a, b))
MemoryType
An enum describing different address spaces to be used with Func::store_in.
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 fragment of Halide syntax.
An argument to an extern-defined Func.
static TO2 value(const FROM &from)
std::vector< std::string > inputs
std::vector< std::string > outputs
std::vector< std::string > generator_params
HALIDE_ALWAYS_INLINE bool defined() const
StringOrLoopLevel(const LoopLevel &loop_level)
StringOrLoopLevel(const std::string &s)
StringOrLoopLevel(const char *s)
StringOrLoopLevel()=default
static constexpr bool value
typename std::conditional< First::value, typename First::type, void >::type type
A struct representing the machine parameters to generate the auto-scheduled code for.
static MachineParams generic()
Default machine parameters for generic CPU architecture.
A struct representing a target machine and os to generate code for.
int natural_vector_size(const Halide::Type &t) const
Given a data type, return an estimate of the "natural" vector size for that data type when compiling ...
Types in the halide type system.