1 #ifndef HALIDE_GENERATOR_H_
2 #define HALIDE_GENERATOR_H_
262 #include <functional>
270 #include <type_traits>
318 std::map<std::string, std::vector<std::vector<Expr>>> values_history;
319 const size_t max_unique_values;
323 : max_unique_values(max_unique_values) {
325 void track_values(
const std::string &name,
const std::vector<Expr> &values);
332 for (
const auto &key_value : enum_map) {
333 if (t == key_value.second) {
334 return key_value.first;
337 user_error <<
"Enumeration value not found.\n";
343 auto it = enum_map.find(s);
344 user_assert(it != enum_map.end()) <<
"Enumeration value not found: " << s <<
"\n";
380 template<
bool B,
typename T>
386 template<
typename First,
typename... Rest>
387 struct select_type : std::conditional<First::value, typename First::type, typename select_type<Rest...>::type> {};
389 template<
typename First>
390 struct select_type<First> {
using type =
typename std::conditional<First::value, typename First::type, void>::type; };
400 inline const std::string &
name()
const {
412 #define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
413 virtual void set(const TYPE &new_value) = 0;
431 #undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
434 void set(
const std::string &new_value) {
437 void set(
const char *new_value) {
472 const std::string name_;
489 template<
typename FROM,
typename TO>
491 template<typename TO2 = TO, typename std::enable_if<!std::is_same<TO2, bool>::value>::type * =
nullptr>
492 inline static TO2
value(
const FROM &from) {
493 return static_cast<TO2
>(from);
496 template<typename TO2 = TO, typename std::enable_if<std::is_same<TO2, bool>::value>::type * =
nullptr>
497 inline static TO2
value(
const FROM &from) {
517 return this->
value();
524 #define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
525 void set(const TYPE &new_value) override { \
526 typed_setter_impl<TYPE>(new_value, #TYPE); \
545 #undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
548 void set(
const std::string &new_value) {
564 template<
typename FROM,
typename std::enable_if<
565 !std::is_convertible<FROM, T>::value>
::type * =
nullptr>
571 template<
typename FROM,
typename std::enable_if<
572 std::is_same<FROM, T>::value>
::type * =
nullptr>
579 template<
typename FROM,
typename std::enable_if<
580 !std::is_same<FROM, T>::value &&
581 std::is_convertible<FROM, T>::value &&
582 std::is_convertible<T, FROM>::value>
::type * =
nullptr>
587 if (value2 !=
value) {
594 template<
typename FROM,
typename std::enable_if<
595 !std::is_same<FROM, T>::value &&
596 std::is_convertible<FROM, T>::value &&
597 !std::is_convertible<T, FROM>::value>
::type * =
nullptr>
621 return this->
value().to_string();
625 std::ostringstream oss;
626 oss << v <<
".to_string()";
647 return this->
value().to_string();
651 std::ostringstream oss;
652 oss << v <<
".to_string()";
657 return "MachineParams";
690 if (new_value_string ==
"root") {
692 }
else if (new_value_string ==
"inlined") {
695 user_error <<
"Unable to parse " << this->
name() <<
": " << new_value_string;
712 return "LoopLevel::inlined()";
714 return "LoopLevel::root()";
723 return std::string();
740 const T &min = std::numeric_limits<T>::lowest(),
748 user_assert(new_value >= min && new_value <= max) <<
"Value out of range: " << new_value;
753 std::istringstream iss(new_value_string);
758 if (
sizeof(T) ==
sizeof(
char) && !std::is_same<T, bool>::value) {
765 user_assert(!iss.fail() && iss.get() == EOF) <<
"Unable to parse: " << new_value_string;
770 std::ostringstream oss;
771 oss << this->
value();
772 if (std::is_same<T, float>::value) {
775 if (oss.str().find(
'.') == std::string::npos) {
784 std::ostringstream oss;
785 oss <<
"std::to_string(" << v <<
")";
790 std::ostringstream oss;
791 if (std::is_same<T, float>::value) {
793 }
else if (std::is_same<T, double>::value) {
795 }
else if (std::is_integral<T>::value) {
796 if (std::is_unsigned<T>::value) {
799 oss <<
"int" << (
sizeof(T) * 8) <<
"_t";
820 if (new_value_string ==
"true" || new_value_string ==
"True") {
822 }
else if (new_value_string ==
"false" || new_value_string ==
"False") {
825 user_assert(
false) <<
"Unable to parse bool: " << new_value_string;
831 return this->
value() ?
"true" :
"false";
835 std::ostringstream oss;
836 oss <<
"std::string((" << v <<
") ? \"true\" : \"false\")";
855 template<typename T2 = T, typename std::enable_if<!std::is_same<T2, Type>::value>
::type * =
nullptr>
861 auto it = enum_map.find(new_value_string);
862 user_assert(it != enum_map.end()) <<
"Enumeration value not found: " << new_value_string;
867 return "Enum_" + this->
name() +
"_map().at(" + v +
")";
871 return "Enum_" + this->
name();
879 std::ostringstream oss;
880 oss <<
"enum class Enum_" << this->
name() <<
" {\n";
881 for (
auto key_value : enum_map) {
882 oss <<
" " << key_value.first <<
",\n";
889 oss <<
"inline HALIDE_NO_USER_CODE_INLINE const std::map<Enum_" << this->
name() <<
", std::string>& Enum_" << this->
name() <<
"_map() {\n";
890 oss <<
" static const std::map<Enum_" << this->
name() <<
", std::string> m = {\n";
891 for (
auto key_value : enum_map) {
892 oss <<
" { Enum_" << this->
name() <<
"::" << key_value.first <<
", \"" << key_value.first <<
"\"},\n";
895 oss <<
" return m;\n";
901 const std::map<std::string, T> enum_map;
912 return "Halide::Internal::halide_type_to_enum_string(" + v +
")";
935 this->
set(new_value_string);
939 return "\"" + this->
value() +
"\"";
947 return "std::string";
999 template<typename T2 = T, typename std::enable_if<!std::is_same<T2, std::string>::value>::type * =
nullptr>
1008 GeneratorParam(
const std::string &name,
const T &value,
const std::map<std::string, T> &enum_map)
1020 template<
typename Other,
typename T>
1024 template<
typename Other,
typename T>
1033 template<
typename Other,
typename T>
1037 template<
typename Other,
typename T>
1046 template<
typename Other,
typename T>
1050 template<
typename Other,
typename T>
1059 template<
typename Other,
typename T>
1063 template<
typename Other,
typename T>
1072 template<
typename Other,
typename T>
1076 template<
typename Other,
typename T>
1085 template<
typename Other,
typename T>
1089 template<
typename Other,
typename T>
1098 template<
typename Other,
typename T>
1102 template<
typename Other,
typename T>
1111 template<
typename Other,
typename T>
1115 template<
typename Other,
typename T>
1124 template<
typename Other,
typename T>
1128 template<
typename Other,
typename T>
1137 template<
typename Other,
typename T>
1141 template<
typename Other,
typename T>
1150 template<
typename Other,
typename T>
1154 template<
typename Other,
typename T>
1163 template<
typename Other,
typename T>
1167 template<
typename Other,
typename T>
1171 template<
typename T>
1173 return (T)a && (T)b;
1180 template<
typename Other,
typename T>
1184 template<
typename Other,
typename T>
1188 template<
typename T>
1190 return (T)a || (T)b;
1198 namespace Internal {
1199 namespace GeneratorMinMax {
1204 template<
typename Other,
typename T>
1206 return min(a, (T)b);
1208 template<
typename Other,
typename T>
1210 return min((T)a, b);
1213 template<
typename Other,
typename T>
1215 return max(a, (T)b);
1217 template<
typename Other,
typename T>
1219 return max((T)a, b);
1228 template<
typename Other,
typename T>
1232 template<
typename Other,
typename T>
1241 template<
typename Other,
typename T>
1245 template<
typename Other,
typename T>
1252 template<
typename T>
1257 namespace Internal {
1259 template<
typename T2>
1260 class GeneratorInput_Buffer;
1275 template<
typename T =
void>
1278 template<
typename T2>
1292 template<
typename T2>
1308 template<
typename T2>
1310 : parameter_(parameter_from_buffer(b)) {
1328 template<
typename... Args>
1334 template<
typename Dst>
1353 template<
typename T =
void>
1355 template<
typename T2>
1379 template<
typename T2>
1381 : kind_(
IOKind::
Buffer), parameter_(b.parameter_), func_(), expr_() {
1387 : kind_(
IOKind::
Scalar), parameter_(), func_(), expr_(e) {
1458 const std::string &
name,
1460 const std::vector<Type> &
types,
1493 template<
typename ElemType>
1503 template<
typename T>
1514 inline const std::vector<Expr> &GIOBase::get_values<Expr>()
const {
1519 inline const std::vector<Func> &GIOBase::get_values<Func>()
const {
1526 const std::string &
name,
1528 const std::vector<Type> &t,
1564 template<
typename T,
typename ValueType>
1567 using TBase =
typename std::remove_all_extents<T>::type;
1570 return std::is_array<T>::value;
1573 template<
typename T2 = T,
typename std::enable_if<
1575 !std::is_array<T2>::value>
::type * =
nullptr>
1580 template<
typename T2 = T,
typename std::enable_if<
1582 std::is_array<T2>::value && std::rank<T2>::value == 1 && (std::extent<T2, 0>::value > 0)>::
type * =
nullptr>
1587 template<
typename T2 = T,
typename std::enable_if<
1589 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>
::type * =
nullptr>
1595 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1598 return get_values<ValueType>().size();
1601 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1604 return get_values<ValueType>()[i];
1607 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1608 const ValueType &
at(
size_t i)
const {
1610 return get_values<ValueType>().at(i);
1613 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1614 typename std::vector<ValueType>::const_iterator
begin()
const {
1616 return get_values<ValueType>().begin();
1619 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1620 typename std::vector<ValueType>::const_iterator
end()
const {
1622 return get_values<ValueType>().end();
1634 #define HALIDE_FORWARD_METHOD(Class, Method) \
1635 template<typename... Args> \
1636 inline auto Method(Args &&...args)->typename std::remove_reference<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))>::type { \
1637 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1640 #define HALIDE_FORWARD_METHOD_CONST(Class, Method) \
1641 template<typename... Args> \
1642 inline auto Method(Args &&...args) const-> \
1643 typename std::remove_reference<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))>::type { \
1644 this->check_gio_access(); \
1645 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1648 template<
typename T>
1656 friend class ::Halide::Func;
1657 friend class ::Halide::Stage;
1660 if (TBase::has_static_halide_type) {
1661 return "Halide::Internal::StubInputBuffer<" +
1665 return "Halide::Internal::StubInputBuffer<>";
1669 template<
typename T2>
1677 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
1683 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Input<Buffer<T>> if T is void or omitted.");
1690 template<
typename... Args>
1693 return Func(*
this)(std::forward<Args>(args)...);
1698 return Func(*
this)(std::move(args));
1701 template<
typename T2>
1703 user_assert(!this->
is_array()) <<
"Cannot assign an array type to a non-array type for Input " << this->
name();
1709 return this->
funcs().at(0);
1736 return Func(*this).
in(other);
1741 return Func(*this).
in(others);
1746 user_assert(!this->
is_array()) <<
"Cannot convert an Input<Buffer<>[]> to an ImageParam; use an explicit subscript operator: " << this->
name();
1750 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1756 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1762 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1768 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1769 typename std::vector<ImageParam>::const_iterator
begin()
const {
1770 user_error <<
"Input<Buffer<>>::begin() is not supported.";
1774 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
1775 typename std::vector<ImageParam>::const_iterator
end()
const {
1776 user_error <<
"Input<Buffer<>>::end() is not supported.";
1800 template<
typename T>
1812 template<
typename T2>
1856 template<
typename... Args>
1859 return this->
funcs().at(0)(std::forward<Args>(args)...);
1864 return this->
funcs().at(0)(args);
1869 return this->
funcs().at(0);
1896 return Func(*this).
in(other);
1901 return Func(*this).
in(others);
1922 template<
typename T>
1927 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");
1937 user_assert(!std::is_array<T>::value) <<
"Input<Expr[]> is not allowed";
1944 return this->
exprs().at(0);
1962 template<
typename T>
1986 template<typename TBase2 = TBase, typename std::enable_if<!std::is_pointer<TBase2>::value>
::type * =
nullptr>
1988 return cast<TBase>(
Expr(value));
1991 template<typename TBase2 = TBase, typename std::enable_if<std::is_pointer<TBase2>::value>
::type * =
nullptr>
1993 user_assert(value == 0) <<
"Zero is the only legal default value for Inputs which are pointer types.\n";
2007 const std::string &
name)
2012 const std::string &
name,
2021 return this->
exprs().at(0);
2031 template<typename T2 = T, typename std::enable_if<std::is_pointer<T2>::value>
::type * =
nullptr>
2034 user_assert(value ==
nullptr) <<
"nullptr is the only valid estimate for Input<PointerType>";
2041 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value && !std::is_pointer<T2>::value>
::type * =
nullptr>
2045 if (std::is_same<T2, bool>::value) {
2053 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2057 if (std::is_same<T2, bool>::value) {
2064 template<
typename T>
2077 if (!std::is_same<TBase, bool>::value) {
2100 const std::string &
name)
2105 const std::string &
name,
2118 const std::string &
name,
2129 template<
typename T2,
typename =
void>
2132 template<
typename T2>
2135 template<typename T, typename TBase = typename std::remove_all_extents<T>::type>
2146 template<
typename T>
2170 : Super(name, def) {
2174 : Super(array_size, name, def) {
2179 : Super(name, def,
min,
max) {
2184 : Super(array_size, name, def,
min,
max) {
2188 : Super(name, t, d) {
2201 : Super(array_size, name, t, d) {
2205 : Super(array_size, name, t) {
2211 : Super(array_size, name, d) {
2215 : Super(array_size, name) {
2219 namespace Internal {
2223 template<typename T2, typename std::enable_if<std::is_same<T2, Func>::value>
::type * =
nullptr>
2225 static_assert(std::is_same<T2, Func>::value,
"Only Func allowed here");
2228 user_assert(
funcs_.size() == 1) <<
"Use [] to access individual Funcs in Output<Func[]>";
2290 #undef HALIDE_OUTPUT_FORWARD
2291 #undef HALIDE_OUTPUT_FORWARD_CONST
2295 const std::string &
name,
2297 const std::vector<Type> &t,
2302 const std::vector<Type> &t,
2325 template<
typename T>
2328 using TBase =
typename std::remove_all_extents<T>::type;
2332 return std::is_array<T>::value;
2335 template<
typename T2 = T,
typename std::enable_if<
2337 !std::is_array<T2>::value>
::type * =
nullptr>
2342 template<
typename T2 = T,
typename std::enable_if<
2344 std::is_array<T2>::value && std::rank<T2>::value == 1 && (std::extent<T2, 0>::value > 0)>::
type * =
nullptr>
2349 template<
typename T2 = T,
typename std::enable_if<
2351 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>
::type * =
nullptr>
2357 template<
typename... Args,
typename T2 = T,
typename std::enable_if<!std::is_array<T2>::value>
::type * =
nullptr>
2360 return get_values<ValueType>().at(0)(std::forward<Args>(args)...);
2363 template<typename ExprOrVar, typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>
::type * =
nullptr>
2366 return get_values<ValueType>().at(0)(args);
2369 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>
::type * =
nullptr>
2372 return get_values<ValueType>().at(0);
2375 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>
::type * =
nullptr>
2378 return get_values<ValueType>().at(0);
2381 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2384 return get_values<ValueType>().size();
2387 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2390 return get_values<ValueType>()[i];
2393 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2396 return get_values<ValueType>().at(i);
2399 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2400 typename std::vector<ValueType>::const_iterator
begin()
const {
2402 return get_values<ValueType>().begin();
2405 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2406 typename std::vector<ValueType>::const_iterator
end()
const {
2408 return get_values<ValueType>().end();
2411 template<
typename T2 = T,
typename std::enable_if<
2413 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>
::type * =
nullptr>
2420 template<
typename T>
2433 <<
"Cannot assign Func \"" << f.
name()
2434 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2435 <<
"Output " << this->
name()
2436 <<
" is declared to have " <<
my_types.size() <<
" tuple elements"
2437 <<
" but Func " << f.
name()
2438 <<
" has " << f.
output_types().size() <<
" tuple elements.\n";
2439 for (
size_t i = 0; i <
my_types.size(); i++) {
2441 <<
"Cannot assign Func \"" << f.
name()
2442 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2443 << (
my_types.size() > 1 ?
"In tuple element " + std::to_string(i) +
", " :
"")
2444 <<
"Output " << this->
name()
2445 <<
" has declared type " <<
my_types[i]
2446 <<
" but Func " << f.
name()
2452 <<
"Cannot assign Func \"" << f.
name()
2453 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2454 <<
"Output " << this->
name()
2455 <<
" has declared dimensionality " << this->
dims()
2456 <<
" but Func " << f.
name()
2457 <<
" has dimensionality " << f.
dimensions() <<
"\n";
2468 static std::vector<Type>
my_types(
const std::vector<Type> &t) {
2469 if (TBase::has_static_halide_type) {
2470 user_assert(t.empty()) <<
"Cannot pass a Type argument for an Output<Buffer> with a non-void static type\n";
2471 return std::vector<Type>{TBase::static_halide_type()};
2485 if (TBase::has_static_halide_type) {
2486 return "Halide::Internal::StubOutputBuffer<" +
2490 return "Halide::Internal::StubOutputBuffer<>";
2494 template<typename T2, typename std::enable_if<!std::is_same<T2, Func>::value>
::type * =
nullptr>
2506 template<
typename T2>
2512 <<
"Cannot assign to the Output \"" << this->
name()
2513 <<
"\": the expression is not convertible to the same Buffer type and/or dimensions.\n";
2517 <<
"Output " << this->
name() <<
" should have type=" << this->
type() <<
" but saw type=" <<
Type(buffer.
type()) <<
"\n";
2521 <<
"Output " << this->
name() <<
" should have dim=" << this->
dims() <<
" but saw dim=" << buffer.dimensions() <<
"\n";
2526 this->
funcs_.at(0)(_) = buffer(_);
2534 template<
typename T2>
2537 assign_from_func(stub_output_buffer.
f);
2546 assign_from_func(f);
2552 user_assert(!this->
is_array()) <<
"Cannot convert an Output<Buffer<>[]> to an ImageParam; use an explicit subscript operator: " << this->
name();
2554 return this->
funcs_.at(0).output_buffer();
2561 this->as<OutputImageParam>().set_estimates(estimates);
2583 template<
typename T>
2590 return this->
funcs_.at(i);
2610 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>
::type * =
nullptr>
2617 get_assignable_func_ref(0) = f;
2622 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2626 return get_assignable_func_ref(i);
2630 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>
::type * =
nullptr>
2655 template<
typename T>
2672 template<typename T, typename TBase = typename std::remove_all_extents<T>::type>
2681 template<
typename T>
2699 : Super(array_size, name) {
2703 : Super(name, {}, d) {
2707 : Super(name, {t}, d) {
2711 : Super(name, t, d) {
2715 : Super(array_size, name, {}, d) {
2719 : Super(array_size, name, {t}, d) {
2722 GeneratorOutput(
size_t array_size,
const std::string &name,
const std::vector<Type> &t,
int d)
2723 : Super(array_size, name, t, d) {
2729 template<
typename T2>
2731 Super::operator=(buffer);
2735 template<
typename T2>
2737 Super::operator=(stub_output_buffer);
2742 Super::operator=(f);
2747 namespace Internal {
2749 template<
typename T>
2751 std::istringstream iss(value);
2754 user_assert(!iss.fail() && iss.get() == EOF) <<
"Unable to parse: " << value;
2766 template<
typename T>
2772 if (!error_msg.empty()) {
2775 set_from_string_impl<T>(new_value_string);
2780 return std::string();
2785 return std::string();
2790 return std::string();
2800 static std::unique_ptr<Internal::GeneratorParamBase> make(
2802 const std::string &generator_name,
2803 const std::string &gpname,
2807 std::string error_msg = defined ?
"Cannot set the GeneratorParam " + gpname +
" for " + generator_name +
" because the value is explicitly specified in the C++ source." :
"";
2808 return std::unique_ptr<GeneratorParam_Synthetic<T>>(
2816 template<typename T2 = T, typename std::enable_if<std::is_same<T2, ::Halide::Type>::value>
::type * =
nullptr>
2817 void set_from_string_impl(
const std::string &new_value_string) {
2822 template<typename T2 = T, typename std::enable_if<std::is_integral<T2>::value>
::type * =
nullptr>
2823 void set_from_string_impl(
const std::string &new_value_string) {
2825 gio.
dims_ = parse_scalar<T2>(new_value_string);
2827 gio.
array_size_ = parse_scalar<T2>(new_value_string);
2835 const std::string error_msg;
2838 class GeneratorStub;
2915 template<
typename T>
2917 return T::create(*
this);
2920 template<
typename T,
typename... Args>
2921 inline std::unique_ptr<T>
apply(
const Args &...args)
const {
2922 auto t = this->create<T>();
2974 template<
typename T>
2976 return Halide::cast<T>(e);
2981 template<
typename T>
2983 template<
typename T =
void>
2985 template<
typename T>
3001 namespace Internal {
3003 template<
typename... Args>
3009 template<
typename T,
typename... Args>
3011 static const bool value = !std::is_convertible<T, Realization>::value &&
NoRealizations<Args...>::value;
3039 std::set<std::string> names;
3042 std::vector<Internal::GeneratorParamBase *> filter_generator_params;
3045 std::vector<Internal::GeneratorInputBase *> filter_inputs;
3048 std::vector<Internal::GeneratorOutputBase *> filter_outputs;
3053 std::vector<std::unique_ptr<Internal::GeneratorParamBase>> owned_synthetic_params;
3056 std::vector<std::unique_ptr<Internal::GIOBase>> owned_extras;
3064 return filter_generator_params;
3066 const std::vector<Internal::GeneratorInputBase *> &
inputs()
const {
3067 return filter_inputs;
3069 const std::vector<Internal::GeneratorOutputBase *> &
outputs()
const {
3070 return filter_outputs;
3088 template<
typename data_t>
3126 template<
typename... Args>
3131 <<
"Expected exactly " << pi.
inputs().size()
3132 <<
" inputs but got " <<
sizeof...(args) <<
"\n";
3133 set_inputs_vector(build_inputs(std::forward_as_tuple<const Args &...>(args...),
make_index_sequence<
sizeof...(Args)>{}));
3137 this->check_scheduled(
"realize");
3143 template<
typename... Args,
typename std::enable_if<
NoRealizations<Args...>::value>::type * =
nullptr>
3145 this->check_scheduled(
"realize");
3150 this->check_scheduled(
"realize");
3162 template<
typename T,
3163 typename std::enable_if<!std::is_arithmetic<T>::value>::type * =
nullptr>
3167 p->generator =
this;
3168 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3169 param_info_ptr->filter_inputs.push_back(p);
3174 template<
typename T,
3175 typename std::enable_if<T::has_static_halide_type>::type * =
nullptr>
3179 p->generator =
this;
3180 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3181 param_info_ptr->filter_inputs.push_back(p);
3186 template<
typename T,
3187 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3191 p->generator =
this;
3192 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3193 param_info_ptr->filter_inputs.push_back(p);
3198 template<
typename T,
3199 typename std::enable_if<std::is_same<T, Expr>::value>::type * =
nullptr>
3203 p->generator =
this;
3205 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3206 param_info_ptr->filter_inputs.push_back(p);
3211 template<
typename T,
3212 typename std::enable_if<!std::is_arithmetic<T>::value>::type * =
nullptr>
3216 p->generator =
this;
3217 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3218 param_info_ptr->filter_outputs.push_back(p);
3223 template<
typename T,
3224 typename std::enable_if<T::has_static_halide_type>::type * =
nullptr>
3228 p->generator =
this;
3229 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3230 param_info_ptr->filter_outputs.push_back(p);
3234 template<
typename... Args>
3265 template<
typename T>
3268 template<
typename T>
3316 std::unique_ptr<GeneratorParamInfo> param_info_ptr;
3318 mutable std::shared_ptr<ExternsMap> externs_map;
3320 bool inputs_set{
false};
3321 std::string generator_registered_name, generator_stub_name;
3329 void check_scheduled(
const char *m)
const;
3331 void build_params(
bool force =
false);
3344 std::vector<Func> get_outputs(
const std::string &n);
3346 void set_inputs_vector(
const std::vector<std::vector<StubInput>> &inputs);
3356 template<
typename T>
3357 std::vector<StubInput> build_input(
size_t i,
const Buffer<T> &arg) {
3358 auto *in = param_info().
inputs().at(i);
3359 check_input_is_singular(in);
3360 const auto k = in->kind();
3368 f(Halide::_) = arg(Halide::_);
3381 template<
typename T>
3382 std::vector<StubInput> build_input(
size_t i,
const GeneratorInput<Buffer<T>> &arg) {
3383 auto *in = param_info().
inputs().at(i);
3384 check_input_is_singular(in);
3385 const auto k = in->kind();
3387 StubInputBuffer<> sib = arg;
3401 std::vector<StubInput> build_input(
size_t i,
const Func &arg) {
3402 auto *in = param_info().
inputs().at(i);
3404 check_input_is_singular(in);
3411 std::vector<StubInput> build_input(
size_t i,
const std::vector<Func> &arg) {
3412 auto *in = param_info().
inputs().at(i);
3414 check_input_is_array(in);
3416 std::vector<StubInput> siv;
3417 siv.reserve(arg.size());
3418 for (
const auto &f : arg) {
3419 siv.emplace_back(f);
3425 std::vector<StubInput> build_input(
size_t i,
const Expr &arg) {
3426 auto *in = param_info().
inputs().at(i);
3428 check_input_is_singular(in);
3434 std::vector<StubInput> build_input(
size_t i,
const std::vector<Expr> &arg) {
3435 auto *in = param_info().
inputs().at(i);
3437 check_input_is_array(in);
3438 std::vector<StubInput> siv;
3439 siv.reserve(arg.size());
3440 for (
const auto &value : arg) {
3441 siv.emplace_back(value);
3448 template<
typename T,
3449 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3450 std::vector<StubInput> build_input(
size_t i,
const T &arg) {
3451 auto *in = param_info().
inputs().at(i);
3453 check_input_is_singular(in);
3461 template<
typename T,
3462 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3463 std::vector<StubInput> build_input(
size_t i,
const std::vector<T> &arg) {
3464 auto *in = param_info().
inputs().at(i);
3466 check_input_is_array(in);
3467 std::vector<StubInput> siv;
3468 siv.reserve(arg.size());
3469 for (
const auto &value : arg) {
3473 siv.emplace_back(e);
3478 template<
typename... Args,
size_t... Indices>
3479 std::vector<std::vector<StubInput>> build_inputs(
const std::tuple<const Args &...> &t, index_sequence<Indices...>) {
3480 return {build_input(Indices, std::get<Indices>(t))...};
3497 static std::unique_ptr<GeneratorBase>
create(
const std::string &name,
3501 using GeneratorFactoryMap = std::map<const std::string, GeneratorFactory>;
3503 GeneratorFactoryMap factories;
3531 auto g = std::unique_ptr<T>(
new T());
3532 g->init_from_context(context);
3538 const std::string ®istered_name,
3539 const std::string &stub_name) {
3540 auto g =
create(context);
3541 g->set_generator_names(registered_name, stub_name);
3548 template<
typename... Args>
3554 static_assert(has_generate_method<T>::value,
"apply() is not supported for old-style Generators.");
3566 struct type_sink {
typedef void type; };
3568 template<
typename T2,
typename =
void>
3569 struct has_configure_method : std::false_type {};
3571 template<
typename T2>
3572 struct has_configure_method<T2, typename type_sink<decltype(std::declval<T2>().configure())>::type> : std::true_type {};
3574 template<
typename T2,
typename =
void>
3575 struct has_generate_method : std::false_type {};
3577 template<
typename T2>
3578 struct has_generate_method<T2, typename type_sink<decltype(std::declval<T2>().generate())>::type> : std::true_type {};
3580 template<
typename T2,
typename =
void>
3581 struct has_schedule_method : std::false_type {};
3583 template<
typename T2>
3584 struct has_schedule_method<T2, typename type_sink<decltype(std::declval<T2>().
schedule())>::type> : std::true_type {};
3586 template<
typename T2 = T,
3587 typename std::enable_if<!has_generate_method<T2>::value>::type * =
nullptr>
3598 Pipeline build_pipeline_impl(
double) {
3599 static_assert(!has_configure_method<T2>::value,
"The configure() method is ignored if you define a build() method; use generate() instead.");
3600 static_assert(!has_schedule_method<T2>::value,
"The schedule() method is ignored if you define a build() method; use generate() instead.");
3607 template<
typename T2 = T,
3608 typename = decltype(std::declval<T2>().generate())>
3609 Pipeline build_pipeline_impl(
int) {
3615 ((T *)
this)->call_generate_impl(0);
3616 ((T *)
this)->call_schedule_impl(0, 0);
3623 void call_configure_impl(
double,
double) {
3630 template<
typename T2 = T,
3631 typename = decltype(std::declval<T2>().generate())>
3632 void call_configure_impl(
double,
int) {
3635 static_assert(!has_configure_method<T2>::value,
"Did not expect a configure method here.");
3639 template<
typename T2 = T,
3640 typename = decltype(std::declval<T2>().generate()),
3641 typename = decltype(std::declval<T2>().configure())>
3642 void call_configure_impl(
int,
int) {
3644 static_assert(std::is_void<decltype(t->configure())>::value,
"configure() must return void");
3653 void call_generate_impl(
double) {
3657 template<
typename T2 = T,
3658 typename = decltype(std::declval<T2>().generate())>
3659 void call_generate_impl(
int) {
3661 static_assert(std::is_void<decltype(t->generate())>::value,
"generate() must return void");
3670 void call_schedule_impl(
double,
double) {
3674 template<
typename T2 = T,
3675 typename = decltype(std::declval<T2>().generate())>
3676 void call_schedule_impl(
double,
int) {
3682 template<
typename T2 = T,
3683 typename = decltype(std::declval<T2>().generate()),
3684 typename = decltype(std::declval<T2>().
schedule())>
3685 void call_schedule_impl(
int,
int) {
3687 static_assert(std::is_void<decltype(t->schedule())>::value,
"schedule() must return void");
3695 return this->build_pipeline_impl(0);
3699 this->call_configure_impl(0, 0);
3703 this->call_generate_impl(0);
3707 this->call_schedule_impl(0, 0);
3713 friend class ::Halide::GeneratorContext;
3737 const std::vector<std::vector<Internal::StubInput>> &inputs);
3739 const std::vector<std::vector<Internal::StubInput>> &inputs);
3746 template<
typename T2>
3749 std::vector<T2> result;
3764 template<
typename T =
void>
3769 template<
typename T>
3771 std::vector<StubInput> r;
3772 std::copy(v.begin(), v.end(), std::back_inserter(r));
3792 struct halide_global_ns;
3795 #define _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
3796 namespace halide_register_generator { \
3797 struct halide_global_ns; \
3798 namespace GEN_REGISTRY_NAME##_ns { \
3799 std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext &context); \
3800 std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext &context) { \
3801 return GEN_CLASS_NAME::create(context, #GEN_REGISTRY_NAME, #FULLY_QUALIFIED_STUB_NAME); \
3804 static auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
3806 static_assert(std::is_same<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>::value, \
3807 "HALIDE_REGISTER_GENERATOR must be used at global scope");
3809 #define _HALIDE_REGISTER_GENERATOR2(GEN_CLASS_NAME, GEN_REGISTRY_NAME) \
3810 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, GEN_REGISTRY_NAME)
3812 #define _HALIDE_REGISTER_GENERATOR3(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
3813 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME)
3818 #define __HALIDE_REGISTER_ARGCOUNT_IMPL(_1, _2, _3, COUNT, ...) \
3821 #define _HALIDE_REGISTER_ARGCOUNT_IMPL(ARGS) \
3822 __HALIDE_REGISTER_ARGCOUNT_IMPL ARGS
3824 #define _HALIDE_REGISTER_ARGCOUNT(...) \
3825 _HALIDE_REGISTER_ARGCOUNT_IMPL((__VA_ARGS__, 3, 2, 1, 0))
3827 #define ___HALIDE_REGISTER_CHOOSER(COUNT) \
3828 _HALIDE_REGISTER_GENERATOR##COUNT
3830 #define __HALIDE_REGISTER_CHOOSER(COUNT) \
3831 ___HALIDE_REGISTER_CHOOSER(COUNT)
3833 #define _HALIDE_REGISTER_CHOOSER(COUNT) \
3834 __HALIDE_REGISTER_CHOOSER(COUNT)
3836 #define _HALIDE_REGISTER_GENERATOR_PASTE(A, B) \
3839 #define HALIDE_REGISTER_GENERATOR(...) \
3840 _HALIDE_REGISTER_GENERATOR_PASTE(_HALIDE_REGISTER_CHOOSER(_HALIDE_REGISTER_ARGCOUNT(__VA_ARGS__)), (__VA_ARGS__))
3856 #define HALIDE_REGISTER_GENERATOR_ALIAS(GEN_REGISTRY_NAME, ORIGINAL_REGISTRY_NAME, ...) \
3857 namespace halide_register_generator { \
3858 struct halide_global_ns; \
3859 namespace ORIGINAL_REGISTRY_NAME##_ns { \
3860 std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext &context); \
3862 namespace GEN_REGISTRY_NAME##_ns { \
3863 std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext &context); \
3864 std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext &context) { \
3865 auto g = ORIGINAL_REGISTRY_NAME##_ns::factory(context); \
3866 g->set_generator_param_values(__VA_ARGS__); \
3870 static auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
3872 static_assert(std::is_same<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>::value, \
3873 "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)
make_integer_sequence< size_t, N > make_index_sequence
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.