1#ifndef HALIDE_GENERATOR_H_
2#define HALIDE_GENERATOR_H_
270#include <type_traits>
280#if !(__cplusplus >= 201703L || _MSVC_LANG >= 201703L)
281#error "Halide requires C++17 or later; please upgrade your compiler."
286class GeneratorContext;
303 user_error <<
"Enumeration value not found.\n";
309 auto it = enum_map.find(
s);
310 user_assert(
it != enum_map.end()) <<
"Enumeration value not found: " <<
s <<
"\n";
379template<
bool B,
typename T>
385template<
typename First,
typename...
Rest>
386struct select_type : std::conditional<First::value, typename First::type, typename select_type<Rest...>::type> {};
388template<
typename First>
390 using type = std::conditional_t<First::value, typename First::type, void>;
393template<
typename...
Args>
403 const std::string &
name()
const {
415#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
416 virtual void set(const TYPE &new_value) = 0;
434#undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
475 const std::string name_;
492template<
typename FROM,
typename TO>
494 template<
typename TO2 = TO, std::enable_if_t<!std::is_same_v<TO2,
bool>> * =
nullptr>
496 return static_cast<TO2>(from);
499 template<
typename TO2 = TO, std::enable_if_t<std::is_same_v<TO2,
bool>> * =
nullptr>
520 return this->
value();
527#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
528 void set(const TYPE &new_value) override { \
529 typed_setter_impl<TYPE>(new_value, #TYPE); \
548#undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
567 template<
typename FROM, std::enable_if_t<!std::is_convertible_v<FROM, T>> * =
nullptr>
573 template<
typename FROM, std::enable_if_t<std::is_same_v<FROM, T>> * =
nullptr>
580 template<
typename FROM, std::enable_if_t<
581 !std::is_same_v<FROM, T> &&
582 std::is_convertible_v<FROM, T> &&
583 std::is_convertible_v<T, FROM>> * =
nullptr>
595 template<
typename FROM, std::enable_if_t<
596 !std::is_same_v<FROM, T> &&
597 std::is_convertible_v<FROM, T> &&
598 !std::is_convertible_v<T, FROM>> * =
nullptr>
622 return this->
value().to_string();
626 std::ostringstream
oss;
627 oss << v <<
".to_string()";
648 bool try_set(
const std::string &key,
const std::string &
value);
682 }
else if (new_value_string ==
"inlined") {
702 return "LoopLevel::inlined()";
704 return "LoopLevel::root()";
713 return std::string();
730 const T &min = std::numeric_limits<T>::lowest(),
731 const T &max = std::numeric_limits<T>::max())
748 if (
sizeof(T) ==
sizeof(
char) && !std::is_same_v<T, bool>) {
760 std::ostringstream
oss;
762 if (std::is_same_v<T, float>) {
765 if (
oss.str().find(
'.') == std::string::npos) {
774 std::ostringstream
oss;
775 oss <<
"std::to_string(" << v <<
")";
780 std::ostringstream
oss;
781 if (std::is_same_v<T, float>) {
783 }
else if (std::is_same_v<T, double>) {
785 }
else if (std::is_integral_v<T>) {
786 if (std::is_unsigned_v<T>) {
789 oss <<
"int" << (
sizeof(T) * 8) <<
"_t";
821 return this->
value() ?
"true" :
"false";
825 std::ostringstream
oss;
826 oss <<
"std::string((" << v <<
") ? \"true\" : \"false\")";
845 template<
typename T2 = T, std::enable_if_t<!std::is_same_v<T2, Type>> * =
nullptr>
857 return "Enum_" + this->
name() +
"_map().at(" + v +
")";
861 return "Enum_" + this->
name();
869 std::ostringstream
oss;
870 oss <<
"enum class Enum_" << this->
name() <<
" {\n";
879 oss <<
"inline HALIDE_NO_USER_CODE_INLINE const std::map<Enum_" << this->
name() <<
", std::string>& Enum_" << this->
name() <<
"_map() {\n";
880 oss <<
" static const std::map<Enum_" << this->
name() <<
", std::string> m = {\n";
885 oss <<
" return m;\n";
891 const std::map<std::string, T> enum_map;
902 return "Halide::Internal::halide_type_to_enum_string(" + v +
")";
925 this->
set(new_value_string);
929 return "\"" + this->
value() +
"\"";
937 return "std::string";
992 template<
typename T2 = T, std::enable_if_t<!std::is_same_v<T2, std::
string>> * =
nullptr>
994 :
Internal::GeneratorParamImplBase<T>(name, value) {
997 GeneratorParam(
const std::string &name,
const T &value,
const T &min,
const T &max)
998 :
Internal::GeneratorParamImplBase<T>(name, value, min, max) {
1001 GeneratorParam(
const std::string &name,
const T &value,
const std::map<std::string, T> &enum_map)
1002 :
Internal::GeneratorParamImplBase<T>(name, value, enum_map) {
1006 :
Internal::GeneratorParamImplBase<T>(name, value) {
1013template<
typename Other,
typename T>
1017template<
typename Other,
typename T>
1026template<
typename Other,
typename T>
1030template<
typename Other,
typename T>
1039template<
typename Other,
typename T>
1043template<
typename Other,
typename T>
1052template<
typename Other,
typename T>
1056template<
typename Other,
typename T>
1065template<
typename Other,
typename T>
1069template<
typename Other,
typename T>
1078template<
typename Other,
typename T>
1082template<
typename Other,
typename T>
1091template<
typename Other,
typename T>
1095template<
typename Other,
typename T>
1104template<
typename Other,
typename T>
1108template<
typename Other,
typename T>
1117template<
typename Other,
typename T>
1121template<
typename Other,
typename T>
1130template<
typename Other,
typename T>
1134template<
typename Other,
typename T>
1143template<
typename Other,
typename T>
1147template<
typename Other,
typename T>
1156template<
typename Other,
typename T>
1160template<
typename Other,
typename T>
1166 return (T)a && (T)b;
1173template<
typename Other,
typename T>
1177template<
typename Other,
typename T>
1183 return (T)a || (T)b;
1192namespace GeneratorMinMax {
1197template<
typename Other,
typename T>
1199 return min(a, (T)b);
1201template<
typename Other,
typename T>
1203 return min((T)a, b);
1206template<
typename Other,
typename T>
1208 return max(a, (T)b);
1210template<
typename Other,
typename T>
1212 return max((T)a, b);
1221template<
typename Other,
typename T>
1225template<
typename Other,
typename T>
1234template<
typename Other,
typename T>
1238template<
typename Other,
typename T>
1252template<
typename T2>
1253class GeneratorInput_Buffer;
1267 template<
typename T2>
1269 template<
typename T2,
int D2>
1279 Buffer<> other(
p.type(),
nullptr, std::vector<int>(
p.dimensions(), 1));
1283 template<
typename T2,
int D2>
1299 template<
typename T2,
int D2>
1301 : parameter_(parameter_from_buffer(b)) {
1304 template<
typename T2>
1306 return {t.parameter_};
1309 template<
typename T2>
1311 std::vector<Parameter> r;
1312 r.reserve(v.size());
1313 for (
const auto &
s : v) {
1314 r.push_back(
s.parameter_);
1320class AbstractGenerator;
1335 template<
typename...
Args>
1340 template<
typename Dst>
1358template<
typename T =
void>
1360 template<
typename T2>
1370 const std::shared_ptr<AbstractGenerator> &
gen) {
1371 std::vector<StubOutputBuffer<T>> result;
1372 for (
const Func &
f : v) {
1392 template<
typename T2>
1473 const std::string &
name,
1475 const std::vector<Type> &types,
1508 template<
typename ElemType>
1518 template<
typename T>
1530inline const std::vector<Expr> &GIOBase::get_values<Expr>()
const {
1535inline const std::vector<Func> &GIOBase::get_values<Func>()
const {
1542 const std::string &
name,
1544 const std::vector<Type> &t,
1581template<
typename T,
typename ValueType>
1584 using TBase = std::remove_all_extents_t<T>;
1587 return std::is_array_v<T>;
1590 template<
typename T2 = T, std::enable_if_t<
1592 !std::is_array_v<T2>> * =
nullptr>
1597 template<
typename T2 = T, std::enable_if_t<
1599 std::is_array_v<T2> && std::rank_v<T2> == 1 && (std::extent_v<T2, 0> > 0)> * =
nullptr>
1604 template<
typename T2 = T, std::enable_if_t<
1606 std::is_array_v<T2> && std::rank_v<T2> == 1 && std::extent_v<T2, 0> == 0> * =
nullptr>
1612 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
1618 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
1624 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
1625 const ValueType &
at(
size_t i)
const {
1630 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
1631 typename std::vector<ValueType>::const_iterator
begin()
const {
1636 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
1637 typename std::vector<ValueType>::const_iterator
end()
const {
1651#define HALIDE_FORWARD_METHOD(Class, Method) \
1652 template<typename... Args> \
1653 inline auto Method(Args &&...args) -> std::remove_reference_t<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))> { \
1654 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1657#define HALIDE_FORWARD_METHOD_CONST(Class, Method) \
1658 template<typename... Args> \
1659 inline auto Method(Args &&...args) const -> std::remove_reference_t<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))> { \
1660 this->check_gio_access(); \
1661 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1672 friend class ::Halide::Func;
1673 friend class ::Halide::Stage;
1676 if (TBase::has_static_halide_type) {
1677 return "Halide::Internal::StubInputBuffer<" +
1681 return "Halide::Internal::StubInputBuffer<>";
1685 template<
typename T2>
1693 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
1694 TBase::has_static_dimensions ? TBase::static_dimensions() : -1) {
1699 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Input<Buffer<T>> if T is void or omitted.");
1700 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Input<Buffer<T, D>> if D is -1 or omitted.");
1705 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Input<Buffer<T>> if T is void or omitted.");
1710 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
1712 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Input<Buffer<T, D>> if D is -1 or omitted.");
1715 template<
typename...
Args>
1718 return Func(*
this)(std::forward<Args>(args)...);
1723 return Func(*
this)(std::move(args));
1726 template<
typename T2>
1728 user_assert(!this->
is_array()) <<
"Cannot assign an array type to a non-array type for Input " << this->
name();
1734 return this->
funcs().at(0);
1756 return Func(*this).in();
1761 return Func(*this).in(other);
1766 return Func(*this).in(others);
1771 user_assert(!this->
is_array()) <<
"Cannot convert an Input<Buffer<>[]> to an ImageParam; use an explicit subscript operator: " << this->
name();
1775 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
1781 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
1787 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
1793 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
1794 std::vector<ImageParam>::const_iterator
begin()
const {
1795 user_error <<
"Input<Buffer<>>::begin() is not supported.";
1799 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
1800 std::vector<ImageParam>::const_iterator
end()
const {
1801 user_error <<
"Input<Buffer<>>::end() is not supported.";
1838 template<
typename T2>
1882 template<
typename...
Args>
1885 return this->
funcs().at(0)(std::forward<Args>(args)...);
1890 return this->
funcs().at(0)(args);
1895 return this->
funcs().at(0);
1927 return Func(*this).
in(others);
1955 static_assert(std::is_same_v<std::remove_all_extents_t<T>,
Expr>,
"GeneratorInput_DynamicScalar is only legal to use with T=Expr for now");
1965 user_assert(!std::is_array_v<T>) <<
"Input<Expr[]> is not allowed";
1972 return this->
exprs().at(0);
2019 template<
typename TBase2 = TBase, std::enable_if_t<!std::is_po
inter_v<TBase2>> * =
nullptr>
2024 template<
typename TBase2 = TBase, std::enable_if_t<std::is_po
inter_v<TBase2>> * =
nullptr>
2026 user_assert(value == 0) <<
"Zero is the only legal default value for Inputs which are pointer types.\n";
2040 const std::string &
name)
2045 const std::string &
name,
2054 return this->
exprs().at(0);
2064 template<
typename T2 = T, std::enable_if_t<std::is_po
inter_v<T2>> * =
nullptr>
2067 user_assert(value ==
nullptr) <<
"nullptr is the only valid estimate for Input<PointerType>";
2074 template<
typename T2 = T, std::enable_if_t<!std::is_array_v<T2> && !std::is_po
inter_v<T2>> * =
nullptr>
2078 if (std::is_same_v<T2, bool>) {
2086 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
2090 if (std::is_same_v<T2, bool>) {
2114 if (!std::is_same_v<TBase, bool>) {
2117 p.set_min_value(
min_);
2120 p.set_max_value(
max_);
2137 const std::string &
name)
2142 const std::string &
name,
2155 const std::string &
name,
2166template<
typename T2,
typename =
void>
2169template<
typename T2>
2172template<
typename...
Args>
2175template<
typename T,
typename TBase = std::remove_all_extents_t<T>>
2213 : Super(name, def) {
2217 : Super(array_size, name, def) {
2222 : Super(name, def, min, max) {
2227 : Super(array_size, name, def, min, max) {
2231 : Super(name, t, d) {
2244 : Super(array_size, name, t, d) {
2248 : Super(array_size, name, t) {
2254 : Super(array_size, name, d) {
2258 : Super(array_size, name) {
2266 template<
typename T2, std::enable_if_t<std::is_same_v<T2, Func>> * =
nullptr>
2268 static_assert(std::is_same_v<T2, Func>,
"Only Func allowed here");
2272 user_assert(
funcs_.size() == 1) <<
"Use [] to access individual Funcs in Output<Func[]>";
2342#undef HALIDE_OUTPUT_FORWARD
2343#undef HALIDE_OUTPUT_FORWARD_CONST
2352 const std::string &
name,
2354 const std::vector<Type> &t,
2359 const std::vector<Type> &t,
2385 using TBase = std::remove_all_extents_t<T>;
2389 return std::is_array_v<T>;
2392 template<
typename T2 = T, std::enable_if_t<
2394 !std::is_array_v<T2>> * =
nullptr>
2399 template<
typename T2 = T, std::enable_if_t<
2401 std::is_array_v<T2> && std::rank_v<T2> == 1 && (std::extent_v<T2, 0> > 0)> * =
nullptr>
2406 template<
typename T2 = T, std::enable_if_t<
2408 std::is_array_v<T2> && std::rank_v<T2> == 1 && std::extent_v<T2, 0> == 0> * =
nullptr>
2414 template<
typename...
Args,
typename T2 = T, std::enable_if_t<!std::is_array_v<T2>> * =
nullptr>
2420 template<
typename ExprOrVar,
typename T2 = T, std::enable_if_t<!std::is_array_v<T2>> * =
nullptr>
2426 template<
typename T2 = T, std::enable_if_t<!std::is_array_v<T2>> * =
nullptr>
2432 template<
typename T2 = T, std::enable_if_t<!std::is_array_v<T2>> * =
nullptr>
2438 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
2444 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
2450 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
2456 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
2457 std::vector<ValueType>::const_iterator
begin()
const {
2462 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
2463 std::vector<ValueType>::const_iterator
end()
const {
2468 template<
typename T2 = T, std::enable_if_t<
2470 std::is_array_v<T2> && std::rank_v<T2> == 1 && std::extent_v<T2, 0> == 0> * =
nullptr>
2490 <<
"Cannot assign Func \"" << f.
name()
2491 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2492 <<
"Output " << this->
name()
2493 <<
" is declared to have " <<
my_types.size() <<
" tuple elements"
2494 <<
" but Func " << f.
name()
2495 <<
" has " << f.
types().size() <<
" tuple elements.\n";
2498 <<
"Cannot assign Func \"" << f.
name()
2499 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2500 << (
my_types.size() > 1 ?
"In tuple element " + std::to_string(
i) +
", " :
"")
2501 <<
"Output " << this->
name()
2503 <<
" but Func " << f.
name()
2504 <<
" has type " << f.
types().at(
i) <<
"\n";
2509 <<
"Cannot assign Func \"" << f.
name()
2510 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2511 <<
"Output " << this->
name()
2512 <<
" has declared dimensionality " << this->
dims()
2513 <<
" but Func " << f.
name()
2514 <<
" has dimensionality " << f.
dimensions() <<
"\n";
2527 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2528 TBase::has_static_dimensions ? TBase::static_dimensions() : -1) {
2535 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2536 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2542 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2547 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2550 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2555 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2556 TBase::has_static_dimensions ? TBase::static_dimensions() : -1) {
2563 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2564 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2570 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2575 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2578 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2582 if (TBase::has_static_halide_type) {
2583 return "Halide::Internal::StubOutputBuffer<" +
2587 return "Halide::Internal::StubOutputBuffer<>";
2591 template<
typename T2, std::enable_if_t<!std::is_same_v<T2, Func>> * =
nullptr>
2603 template<
typename T2,
int D2>
2609 <<
"Cannot assign to the Output \"" << this->
name()
2610 <<
"\": the expression is not convertible to the same Buffer type and/or dimensions.\n";
2614 <<
"Output " << this->
name() <<
" should have type=" << this->
gio_type() <<
" but saw type=" <<
Type(buffer.
type()) <<
"\n";
2618 <<
"Output " << this->
name() <<
" should have dim=" << this->
dims() <<
" but saw dim=" << buffer.dimensions() <<
"\n";
2623 this->
funcs_.at(0)(_) = buffer(_);
2631 template<
typename T2>
2643 assign_from_func(f);
2649 user_assert(!this->
is_array()) <<
"Cannot convert an Output<Buffer<>[]> to an ImageParam; use an explicit subscript operator: " << this->
name();
2651 return this->
funcs_.at(0).output_buffer();
2657 user_assert(!this->
is_array()) <<
"Cannot call set_estimates() on an array Output; use an explicit subscript operator: " << this->
name();
2659 this->
funcs_.at(0).set_estimates(estimates);
2663 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
2670 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
2701 return this->funcs_.at(
i);
2729 template<
typename T2 = T, std::enable_if_t<!std::is_array_v<T2>> * =
nullptr>
2731 this->check_gio_access();
2732 this->check_value_writable();
2736 get_assignable_func_ref(0) = f;
2741 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
2743 this->check_gio_access();
2744 this->check_value_writable();
2745 return get_assignable_func_ref(
i);
2749 template<
typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * =
nullptr>
2751 this->check_gio_access();
2752 return Super::operator[](
i);
2756 this->check_gio_access();
2758 for (
Func &f : this->funcs_) {
2759 f.set_estimate(var,
min, extent);
2765 this->check_gio_access();
2767 for (
Func &f : this->funcs_) {
2768 f.set_estimates(estimates);
2791template<
typename T,
typename TBase = std::remove_all_extents_t<T>>
2821 : Super(array_size, name) {
2829 : Super(name, {t}) {
2837 : Super(name, {t}, d) {
2841 : Super(name, t, d) {
2845 : Super(array_size, name, d) {
2849 : Super(array_size, name, {t}) {
2852 explicit GeneratorOutput(
size_t array_size,
const std::string &name,
const std::vector<Type> &t)
2853 : Super(array_size, name, t) {
2857 : Super(array_size, name, {t}, d) {
2860 explicit GeneratorOutput(
size_t array_size,
const std::string &name,
const std::vector<Type> &t,
int d)
2861 : Super(array_size, name, t, d) {
2867 template<
typename T2,
int D2>
2869 Super::operator=(buffer);
2873 template<
typename T2>
2880 Super::operator=(f);
2889 std::istringstream
iss(value);
2910 if (!error_msg.empty()) {
2918 return std::string();
2923 return std::string();
2928 return std::string();
2938 static std::unique_ptr<Internal::GeneratorParamBase> make(
2940 const std::string &generator_name,
2941 const std::string &
gpname,
2945 std::string error_msg = defined ?
"Cannot set the GeneratorParam " +
gpname +
" for " + generator_name +
" because the value is explicitly specified in the C++ source." :
"";
2946 return std::unique_ptr<GeneratorParam_Synthetic<T>>(
2954 template<
typename T2 = T, std::enable_if_t<std::is_same_v<T2, ::Hal
ide::Type>> * =
nullptr>
2960 template<
typename T2 = T, std::enable_if_t<std::is_
integral_v<T2>> * =
nullptr>
2973 const std::string error_msg;
3031 return autoscheduler_params_;
3039 template<
typename T>
3041 return T::create(*
this);
3043 template<
typename T,
typename...
Args>
3079 template<
typename T>
3086 template<
typename T>
3088 template<
typename T = void,
int D = -1>
3090 template<
typename T>
3108template<
typename...>
3114template<
typename T,
typename...
Args>
3119template<
typename...
Args>
3128 std::set<std::string> names;
3131 std::vector<Internal::GeneratorParamBase *> filter_generator_params;
3134 std::vector<Internal::GeneratorInputBase *> filter_inputs;
3137 std::vector<Internal::GeneratorOutputBase *> filter_outputs;
3142 std::vector<std::unique_ptr<Internal::GeneratorParamBase>> owned_synthetic_params;
3145 std::vector<std::unique_ptr<Internal::GIOBase>> owned_extras;
3153 return filter_generator_params;
3155 const std::vector<Internal::GeneratorInputBase *> &
inputs()
const {
3156 return filter_inputs;
3158 const std::vector<Internal::GeneratorOutputBase *> &
outputs()
const {
3159 return filter_outputs;
3175 template<
typename data_t>
3190 template<
typename...
Args>
3195 <<
"Expected exactly " <<
pi.inputs().size()
3196 <<
" inputs but got " <<
sizeof...(args) <<
"\n";
3197 set_inputs_vector(build_inputs(std::forward_as_tuple<const Args &...>(args...), std::make_index_sequence<
sizeof...(Args)>{}));
3201 this->check_scheduled(
"realize");
3209 this->check_scheduled(
"realize");
3214 this->check_scheduled(
"realize");
3228 <<
". It is already taken by another input or output parameter.";
3229 param_info_ptr->names.insert(
name);
3234 template<
typename T,
3235 std::enable_if_t<std::is_same_v<T, Halide::Func>> * =
nullptr>
3240 p->generator =
this;
3241 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(
p));
3242 param_info_ptr->filter_inputs.push_back(
p);
3247 template<
typename T,
3248 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * =
nullptr>
3250 static_assert(!T::has_static_halide_type,
"You can only call this version of add_input() for a Buffer<T, D> where T is void or omitted .");
3251 static_assert(!T::has_static_dimensions,
"You can only call this version of add_input() for a Buffer<T, D> where D is -1 or omitted.");
3255 p->generator =
this;
3256 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(
p));
3257 param_info_ptr->filter_inputs.push_back(
p);
3262 template<
typename T,
3263 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * =
nullptr>
3265 static_assert(T::has_static_halide_type,
"You can only call this version of add_input() for a Buffer<T, D> where T is not void.");
3266 static_assert(!T::has_static_dimensions,
"You can only call this version of add_input() for a Buffer<T, D> where D is -1 or omitted.");
3270 p->generator =
this;
3271 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(
p));
3272 param_info_ptr->filter_inputs.push_back(
p);
3277 template<
typename T,
3278 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * =
nullptr>
3280 static_assert(T::has_static_halide_type,
"You can only call this version of add_input() for a Buffer<T, D> where T is not void.");
3281 static_assert(T::has_static_dimensions,
"You can only call this version of add_input() for a Buffer<T, D> where D is not -1.");
3285 p->generator =
this;
3286 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(
p));
3287 param_info_ptr->filter_inputs.push_back(
p);
3291 template<
typename T,
3292 std::enable_if_t<std::is_arithmetic_v<T>> * =
nullptr>
3297 p->generator =
this;
3298 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(
p));
3299 param_info_ptr->filter_inputs.push_back(
p);
3303 template<
typename T,
3304 std::enable_if_t<std::is_same_v<T, Expr>> * =
nullptr>
3309 p->generator =
this;
3311 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(
p));
3312 param_info_ptr->filter_inputs.push_back(
p);
3317 template<
typename T,
3318 std::enable_if_t<std::is_same_v<T, Halide::Func>> * =
nullptr>
3323 p->generator =
this;
3324 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(
p));
3325 param_info_ptr->filter_outputs.push_back(
p);
3329 template<
typename T,
3330 std::enable_if_t<std::is_same_v<T, Halide::Func>> * =
nullptr>
3336 template<
typename T,
3337 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * =
nullptr>
3339 static_assert(!T::has_static_halide_type,
"You can only call this version of add_output() for a Buffer<T, D> where T is void or omitted .");
3340 static_assert(!T::has_static_dimensions,
"You can only call this version of add_output() for a Buffer<T, D> where D is -1 or omitted.");
3344 p->generator =
this;
3345 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(
p));
3346 param_info_ptr->filter_outputs.push_back(
p);
3350 template<
typename T,
3351 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * =
nullptr>
3358 template<
typename T,
3359 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * =
nullptr>
3361 static_assert(!T::has_static_dimensions,
"You can only call this version of add_output() for a Buffer<T, D> where D is -1 or omitted.");
3365 p->generator =
this;
3366 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(
p));
3367 param_info_ptr->filter_outputs.push_back(
p);
3372 template<
typename T,
3373 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * =
nullptr>
3375 static_assert(!T::has_static_halide_type,
"You can only call this version of add_output() for a Buffer<T, D> where T is void or omitted.");
3376 static_assert(T::has_static_dimensions,
"You can only call this version of add_output() for a Buffer<void, D> where D is not -1.");
3380 p->generator =
this;
3381 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(
p));
3382 param_info_ptr->filter_outputs.push_back(
p);
3386 template<
typename T,
3387 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * =
nullptr>
3393 template<
typename T,
3394 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * =
nullptr>
3396 static_assert(T::has_static_halide_type,
"You can only call this version of add_output() for a Buffer<T, D> where T is not void.");
3397 static_assert(T::has_static_dimensions,
"You can only call this version of add_output() for a Buffer<T, D> where D is not -1.");
3401 p->generator =
this;
3402 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(
p));
3403 param_info_ptr->filter_outputs.push_back(
p);
3409 template<
typename...
Args,
3495 template<
typename T>
3498 template<
typename T>
3542 friend void ::Halide::Internal::generator_test();
3554 std::unique_ptr<GeneratorParamInfo> param_info_ptr;
3556 std::string generator_registered_name, generator_stub_name;
3559 struct Requirement {
3561 std::vector<Expr> error_args;
3563 std::vector<Requirement> requirements;
3568 template<
typename T>
3569 T *find_by_name(
const std::string &
name,
const std::vector<T *> &v) {
3571 if (t->name() ==
name) {
3578 Internal::GeneratorInputBase *find_input_by_name(
const std::string &
name);
3579 Internal::GeneratorOutputBase *find_output_by_name(
const std::string &
name);
3581 void check_scheduled(
const char *
m)
const;
3583 void build_params(
bool force =
false);
3588 void get_host_target();
3589 void get_jit_target_from_environment();
3590 void get_target_from_environment();
3592 void set_inputs_vector(
const std::vector<std::vector<StubInput>> &inputs);
3594 static void check_input_is_singular(Internal::GeneratorInputBase *in);
3595 static void check_input_is_array(Internal::GeneratorInputBase *in);
3602 template<
typename T,
int Dims>
3604 auto *in = param_info().
inputs().at(
i);
3605 check_input_is_singular(in);
3606 const auto k = in->kind();
3614 f(Halide::_) = arg(Halide::_);
3627 template<
typename T,
int Dims>
3628 std::vector<StubInput> build_input(
size_t i,
const GeneratorInput<
Buffer<T, Dims>> &arg) {
3629 auto *in = param_info().
inputs().at(
i);
3630 check_input_is_singular(in);
3631 const auto k = in->kind();
3647 std::vector<StubInput> build_input(
size_t i,
const Func &arg) {
3648 auto *in = param_info().
inputs().at(
i);
3650 check_input_is_singular(in);
3657 std::vector<StubInput> build_input(
size_t i,
const std::vector<Func> &arg) {
3658 auto *in = param_info().
inputs().at(
i);
3660 check_input_is_array(in);
3662 std::vector<StubInput>
siv;
3663 siv.reserve(arg.size());
3664 for (
const auto &f : arg) {
3665 siv.emplace_back(f);
3671 std::vector<StubInput> build_input(
size_t i,
const Expr &arg) {
3672 auto *in = param_info().
inputs().at(
i);
3674 check_input_is_singular(in);
3680 std::vector<StubInput> build_input(
size_t i,
const std::vector<Expr> &arg) {
3681 auto *in = param_info().
inputs().at(
i);
3683 check_input_is_array(in);
3684 std::vector<StubInput>
siv;
3685 siv.reserve(arg.size());
3686 for (
const auto &value : arg) {
3687 siv.emplace_back(value);
3694 template<
typename T,
3695 std::enable_if_t<std::is_arithmetic_v<T>> * =
nullptr>
3696 std::vector<StubInput> build_input(
size_t i,
const T &arg) {
3697 auto *in = param_info().
inputs().at(
i);
3699 check_input_is_singular(in);
3707 template<
typename T, std::enable_if_t<std::is_arithmetic_v<T>> * =
nullptr>
3708 std::vector<StubInput> build_input(
size_t i,
const std::vector<T> &arg) {
3709 auto *in = param_info().
inputs().at(
i);
3711 check_input_is_array(in);
3712 std::vector<StubInput>
siv;
3713 siv.reserve(arg.size());
3714 for (
const auto &value : arg) {
3718 siv.emplace_back(e);
3724 std::vector<std::vector<StubInput>> build_inputs(
const std::tuple<const Args &...> &t, std::index_sequence<Indices...>) {
3725 return {build_input(
Indices, std::get<Indices>(t))...};
3730 template<
typename T>
3731 static void get_arguments(std::vector<AbstractGenerator::ArgInfo> &args,
ArgInfoDirection dir,
const T &t) {
3733 args.push_back({e->name(),
3736 e->gio_types_defined() ? e->gio_types() : std::vector<
Type>{},
3737 e->dims_defined() ? e->dims() : 0});
3781 using GeneratorFactoryMap = std::map<const std::string, GeneratorFactory>;
3783 GeneratorFactoryMap factories;
3810 auto g = std::make_unique<T>();
3811 g->init_from_context(
context);
3824 template<
typename...
Args>
3832 template<
typename T2>
3837 template<
typename T2,
typename...
Args>
3848 using type_sink_t = void;
3850 template<
typename T2,
typename =
void>
3851 struct has_configure_method : std::false_type {};
3853 template<
typename T2>
3856 template<
typename T2>
3857 static constexpr bool has_configure_method_v = has_configure_method<T2>::value;
3859 template<
typename T2,
typename =
void>
3860 struct has_generate_method : std::false_type {};
3862 template<
typename T2>
3865 template<
typename T2>
3866 static constexpr bool has_generate_method_v = has_generate_method<T2>::value;
3868 template<
typename T2,
typename =
void>
3869 struct has_schedule_method : std::false_type {};
3871 template<
typename T2>
3874 template<
typename T2>
3875 static constexpr bool has_schedule_method_v = has_schedule_method<T2>::value;
3884 t->call_generate_impl();
3885 t->call_schedule_impl();
3889 void call_configure_impl() {
3893 static_assert(std::is_void_v<
decltype(t->configure())>,
"configure() must return void");
3899 void call_generate_impl() {
3903 static_assert(std::is_void_v<
decltype(t->generate())>,
"generate() must return void");
3908 void call_schedule_impl() {
3912 static_assert(std::is_void_v<
decltype(t->schedule())>,
"schedule() must return void");
3921 return this->build_pipeline_impl();
3925 this->call_configure_impl();
3929 this->call_generate_impl();
3933 this->call_schedule_impl();
3937 friend void ::Halide::Internal::generator_test();
3938 friend void ::Halide::Internal::generator_test();
3939 friend class ::Halide::GeneratorContext;
4042 const std::string &name,
4045 const std::string &name,
4055struct halide_global_ns;
4058#define _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
4059 namespace halide_register_generator { \
4060 struct halide_global_ns; \
4061 namespace GEN_REGISTRY_NAME##_ns { \
4062 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
4063 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context) { \
4064 using GenType = std::remove_pointer_t<decltype(new GEN_CLASS_NAME)>; \
4065 return GenType::create(context, #GEN_REGISTRY_NAME, #FULLY_QUALIFIED_STUB_NAME); \
4069 auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
4072 static_assert(std::is_same_v<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>, \
4073 "HALIDE_REGISTER_GENERATOR must be used at global scope");
4075#define _HALIDE_REGISTER_GENERATOR2(GEN_CLASS_NAME, GEN_REGISTRY_NAME) \
4076 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, GEN_REGISTRY_NAME)
4078#define _HALIDE_REGISTER_GENERATOR3(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
4079 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME)
4084#define __HALIDE_REGISTER_ARGCOUNT_IMPL(_1, _2, _3, COUNT, ...) \
4087#define _HALIDE_REGISTER_ARGCOUNT_IMPL(ARGS) \
4088 __HALIDE_REGISTER_ARGCOUNT_IMPL ARGS
4090#define _HALIDE_REGISTER_ARGCOUNT(...) \
4091 _HALIDE_REGISTER_ARGCOUNT_IMPL((__VA_ARGS__, 3, 2, 1, 0))
4093#define ___HALIDE_REGISTER_CHOOSER(COUNT) \
4094 _HALIDE_REGISTER_GENERATOR##COUNT
4096#define __HALIDE_REGISTER_CHOOSER(COUNT) \
4097 ___HALIDE_REGISTER_CHOOSER(COUNT)
4099#define _HALIDE_REGISTER_CHOOSER(COUNT) \
4100 __HALIDE_REGISTER_CHOOSER(COUNT)
4102#define _HALIDE_REGISTER_GENERATOR_PASTE(A, B) \
4105#define HALIDE_REGISTER_GENERATOR(...) \
4106 _HALIDE_REGISTER_GENERATOR_PASTE(_HALIDE_REGISTER_CHOOSER(_HALIDE_REGISTER_ARGCOUNT(__VA_ARGS__)), (__VA_ARGS__))
4122#define HALIDE_REGISTER_GENERATOR_ALIAS(GEN_REGISTRY_NAME, ORIGINAL_REGISTRY_NAME, ...) \
4123 namespace halide_register_generator { \
4124 struct halide_global_ns; \
4125 namespace ORIGINAL_REGISTRY_NAME##_ns { \
4126 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
4128 namespace GEN_REGISTRY_NAME##_ns { \
4129 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context) { \
4130 auto g = ORIGINAL_REGISTRY_NAME##_ns::factory(context); \
4131 const Halide::GeneratorParamsMap m = __VA_ARGS__; \
4132 g->set_generatorparam_values(m); \
4137 auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
4140 static_assert(std::is_same_v<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>, \
4141 "HALIDE_REGISTER_GENERATOR_ALIAS must be used at global scope");
4146#define HALIDE_GENERATOR_PYSTUB(GEN_REGISTRY_NAME, MODULE_NAME) \
4147 static_assert(PY_MAJOR_VERSION >= 3, "Python bindings for Halide require Python 3+"); \
4148 extern "C" PyObject *_halide_pystub_impl(const char *module_name, const Halide::Internal::GeneratorFactory &factory); \
4149 namespace halide_register_generator::GEN_REGISTRY_NAME##_ns { \
4150 extern std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
4152 extern "C" HALIDE_EXPORT_SYMBOL PyObject *PyInit_##MODULE_NAME() { \
4153 const auto factory = halide_register_generator::GEN_REGISTRY_NAME##_ns::factory; \
4154 return _halide_pystub_impl(#MODULE_NAME, factory); \
#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.
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
bool defined() const
Check if this Buffer refers to an existing Buffer.
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.
const std::vector< Type > & types() const
Realization realize(std::vector< int32_t > sizes={}, const Target &target=Target())
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.
Func in(const Func &f)
Creates and returns a new identity Func that wraps this Func.
A fragment of front-end syntax of the form f(x, y, z), where x, y, z are Vars or Exprs.
GeneratorContext is a class that is used when using Generators (or Stubs) directly; it is used to all...
GeneratorContext with_target(const Target &t) const
GeneratorContext(const Target &t)
std::unique_ptr< T > apply(const Args &...args) const
std::unique_ptr< T > create() const
GeneratorContext & operator=(GeneratorContext &&)=default
GeneratorContext & operator=(const GeneratorContext &)=default
const Target & target() const
GeneratorContext(const Target &t, const AutoschedulerParams &autoscheduler_params)
GeneratorContext()=default
GeneratorContext(const GeneratorContext &)=default
const AutoschedulerParams & autoscheduler_params() const
GeneratorContext(GeneratorContext &&)=default
void call_generate() override
Generator(Generator &&that)=delete
static std::unique_ptr< T > create(const Halide::GeneratorContext &context, const std::string ®istered_name, const std::string &stub_name)
void call_schedule() override
std::unique_ptr< T2 > apply(const Args &...args) const
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)
void call_configure() override
std::unique_ptr< T2 > create() const
Pipeline build_pipeline() override
Build and return the Pipeline for this AbstractGenerator.
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< T > & operator=(const Internal::StubOutputBuffer< T2 > &stub_output_buffer)
GeneratorOutput(const char *name)
GeneratorOutput(const std::string &name, const std::vector< Type > &t)
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=(Buffer< T2, D2 > &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(const std::string &name, const Type &t)
GeneratorOutput(size_t array_size, const std::string &name, const std::vector< Type > &t)
GeneratorOutput(size_t array_size, const std::string &name, const Type &t)
GeneratorOutput< T > & operator=(const Func &f)
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.
AbstractGenerator is an ABC that defines the API a Generator must provide to work with the existing G...
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...
const std::string & name() const
GIOBase & operator=(const GIOBase &)=delete
size_t array_size() const
virtual const char * input_or_output() const =0
GIOBase(size_t array_size, const std::string &name, ArgInfoKind kind, const std::vector< Type > &types, int dims)
void check_matching_dims(int d) const
bool array_size_defined() const
const std::vector< Type > & gio_types() const
bool dims_defined() const
GIOBase & operator=(GIOBase &&)=delete
const std::vector< Func > & funcs() const
std::vector< Type > types_
void check_matching_types(const std::vector< Type > &t) 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
friend class GeneratorStub
GIOBase(GIOBase &&)=delete
void check_gio_access() const
void set_dimensions(int dims)
void set_array_size(int size)
std::vector< Func > funcs_
virtual bool is_array() const
virtual void verify_internals()
virtual ~GIOBase()=default
std::vector< Expr > exprs_
void set_type(const Type &type)
bool gio_types_defined() const
GeneratorBase * generator
const std::vector< Expr > & exprs() const
const std::vector< ElemType > & get_values() const
GeneratorContext context() const override
Return the Target and autoscheduler info that this Generator was created with.
void ensure_configure_has_been_called()
std::string name() override
Return the name of this Generator.
friend class StubOutputBufferBase
virtual void call_schedule()=0
bool allow_out_of_order_inputs_and_outputs() const override
By default, a Generator must declare all Inputs before all Outputs.
GeneratorParam< Target > target
void bind_input(const std::string &name, const std::vector< Parameter > &v) override
Rebind a specified Input to refer to the given piece of IR, replacing the default ImageParam / Param ...
GeneratorInput< T > * add_input(const std::string &name)
std::vector< Func > output_func(const std::string &name) override
Given the name of an output, return the Func(s) for that output.
void claim_name(const std::string &name, const char *param_type)
std::vector< Parameter > input_parameter(const std::string &name) override
Given the name of an input, return the Parameter(s) for that input.
void bind_input(const std::string &name, const std::vector< Func > &v) override
void bind_input(const std::string &name, const std::vector< Expr > &v) override
bool emit_hlpipe(const std::string &hlpipe_file_path) override
Emit a Serialized Halide Pipeline (.hlpipe) file to the given path.
Realization realize(Args &&...args)
GeneratorBase(const GeneratorBase &)=delete
virtual void call_generate()=0
GeneratorOutput< T > * add_output(const std::string &name)
GeneratorBase(size_t size)
int natural_vector_size() const
Given a data type, return an estimate of the "natural" vector size for that data type when compiling ...
friend class GeneratorInputBase
Target get_target() const
~GeneratorBase() override
virtual void init_from_context(const Halide::GeneratorContext &context)
GeneratorOutput< T > * add_output(const std::string &name, const Type &t)
void check_exact_phase(Phase expected_phase) const
void set_generatorparam_value(const std::string &name, const LoopLevel &loop_level) override
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)
GeneratorInput< T > * add_input(const std::string &name, int dimensions)
std::vector< ArgInfo > arginfos() override
Return a list of all the ArgInfos for this generator.
virtual void call_configure()=0
GeneratorInput< T > * add_input(const std::string &name, const Type &type)
void set_generatorparam_value(const std::string &name, const std::string &value) override
Set the value for a specific GeneratorParam for an AbstractGenerator instance.
GeneratorBase(GeneratorBase &&that)=delete
GeneratorOutput< T > * add_output(const std::string &name, int dimensions)
bool using_autoscheduler() const
friend class GeneratorParamBase
bool emit_cpp_stub(const std::string &stub_file_path) override
Emit a Generator Stub (.stub.h) file to the given path.
friend class GeneratorParamInfo
GeneratorOutput< T > * add_output(const std::string &name, const std::vector< Type > &t, int dimensions)
GeneratorOutput< T > * add_output(const std::string &name, const std::vector< Type > &t)
GeneratorBase & operator=(const GeneratorBase &)=delete
GeneratorBase & operator=(GeneratorBase &&that)=delete
void set_inputs(const Args &...args)
set_inputs is a variadic wrapper around set_inputs_vector, which makes usage much simpler in many cas...
GeneratorParam_AutoSchedulerParams autoscheduler_
HALIDE_NO_USER_CODE_INLINE void add_requirement(const Expr &condition, Args &&...error_args)
GeneratorInput< T > * add_input(const std::string &name, const Type &t, int dimensions)
void add_requirement(const Expr &condition, const std::vector< Expr > &error_args)
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 advance_phase(Phase new_phase)
GeneratorOutput< T > * add_output(const std::string &name, const Type &t, int dimensions)
friend class GeneratorOutputBase
GeneratorFactoryProvider provides a way to customize the Generators that are visible to generate_filt...
virtual AbstractGeneratorPtr create(const std::string &name, const Halide::GeneratorContext &context) const =0
Create an instance of the Generator that is registered under the given name.
GeneratorFactoryProvider(const GeneratorFactoryProvider &)=delete
GeneratorFactoryProvider()=default
GeneratorFactoryProvider & operator=(GeneratorFactoryProvider &&)=delete
GeneratorFactoryProvider(GeneratorFactoryProvider &&)=delete
GeneratorFactoryProvider & operator=(const GeneratorFactoryProvider &)=delete
virtual std::vector< std::string > enumerate() const =0
Return a list of all registered Generators that are available for use with the create() method.
virtual ~GeneratorFactoryProvider()=default
GeneratorOutput_Arithmetic(const std::string &name)
GeneratorOutput_Arithmetic(size_t array_size, const std::string &name)
typename Super::TBase TBase
GeneratorOutput_Buffer(const std::string &name, int d)
GeneratorOutput_Buffer(size_t array_size, const std::string &name)
typename Super::TBase TBase
GeneratorOutput_Buffer(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
GeneratorOutput_Buffer< T > & operator=(const StubOutputBuffer< T2 > &stub_output_buffer)
GeneratorOutput_Buffer(const std::string &name)
HALIDE_NO_USER_CODE_INLINE std::string get_c_type() const override
GeneratorOutput_Buffer< T > & set_estimates(const Region &estimates)
HALIDE_NO_USER_CODE_INLINE T2 as() const
GeneratorOutput_Buffer(const std::string &name, const std::vector< Type > &t)
GeneratorOutput_Buffer(size_t array_size, const std::string &name, int d)
GeneratorOutput_Buffer< T > & operator=(const Func &f)
HALIDE_NO_USER_CODE_INLINE GeneratorOutput_Buffer< T > & operator=(Buffer< T2, D2 > &buffer)
const Func & operator[](size_t i) const
GeneratorOutput_Buffer(size_t array_size, const std::string &name, const std::vector< Type > &t)
GeneratorOutput_Buffer(const std::string &name, const std::vector< Type > &t, int d)
Func operator[](size_t i)
const Func & operator[](size_t i) const
GeneratorOutput_Func(const std::string &name)
typename Super::TBase TBase
GeneratorOutput_Func< T > & operator=(const Func &f)
GeneratorOutput_Func(const std::string &name, const std::vector< Type > &t, int d)
GeneratorOutput_Func(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
GeneratorOutput_Func(const std::string &name, int d)
GeneratorOutput_Func< T > & set_estimate(const Var &var, const Expr &min, const Expr &extent)
Func & operator[](size_t i)
GeneratorOutput_Func(const std::string &name, const std::vector< Type > &t)
GeneratorOutput_Func< T > & set_estimates(const Region &estimates)
void set_type(const std::vector< Type > &types)
Set types dynamically for tuple outputs.
const char * input_or_output() const override
~GeneratorOutputBase() override
GeneratorOutputBase(const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
virtual std::string get_c_type() const
HALIDE_NO_USER_CODE_INLINE T2 as() const
void check_value_writable() const override
GeneratorOutputBase(size_t array_size, const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
std::vector< ValueType >::const_iterator end() const
const ValueType & operator[](size_t i) const
GeneratorOutputImpl(const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
const ValueType & at(size_t i) const
std::vector< ValueType >::const_iterator begin() const
bool is_array() const override
std::remove_all_extents_t< T > TBase
FuncRef operator()(std::vector< ExprOrVar > args) const
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
GeneratorParam_AutoSchedulerParams()
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
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_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)
void check_value_readable() const
virtual bool is_synthetic_param() const
GeneratorParamBase(GeneratorParamBase &&)=delete
virtual std::string call_to_string(const std::string &v) const =0
void fail_wrong_type(const char *type)
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
GeneratorParamBase & operator=(GeneratorParamBase &&)=delete
const std::string & name() const
GeneratorParamBase & operator=(const GeneratorParamBase &)=delete
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::GeneratorInputBase * > & inputs() const
const std::vector< Internal::GeneratorParamBase * > & generator_params() const
GeneratorParamInfo(GeneratorBase *generator, size_t size)
const std::vector< Internal::GeneratorOutputBase * > & outputs() const
GeneratorRegistry(const GeneratorRegistry &)=delete
static AbstractGeneratorPtr create(const std::string &name, const Halide::GeneratorContext &context)
GeneratorRegistry & operator=(GeneratorRegistry &&that)=delete
GeneratorRegistry(GeneratorRegistry &&that)=delete
GeneratorRegistry & operator=(const GeneratorRegistry &)=delete
static void register_factory(const std::string &name, GeneratorFactory generator_factory)
static std::vector< std::string > enumerate()
static void unregister_factory(const std::string &name)
RegisterGenerator(const char *registered_name, GeneratorFactory generator_factory)
Target get_target() const
std::shared_ptr< AbstractGenerator > generator
Realization realize(Args &&...args)
StubOutputBufferBase(const Func &f, const std::shared_ptr< AbstractGenerator > &generator)
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
static std::vector< StubOutputBuffer< T > > to_output_buffers(const std::vector< Func > &v, const std::shared_ptr< AbstractGenerator > &gen)
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 reference-counted handle to a parameter to a halide pipeline.
void set_default_value(const Expr &e)
Get and set the default values for scalar parameters.
void set_estimate(Expr e)
A class representing a Halide pipeline.
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())
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))
std::function< AbstractGeneratorPtr(const GeneratorContext &context)> GeneratorFactory
int generate_filter_main(int argc, char **argv)
generate_filter_main() is a convenient wrapper for GeneratorRegistry::create() + compile_to_files(); ...
std::string halide_type_to_enum_string(const Type &t)
constexpr bool has_static_halide_type_method_v
ConstantInterval min(const ConstantInterval &a, const ConstantInterval &b)
std::vector< Expr > parameter_constraints(const Parameter &p)
typename select_type< Args... >::type select_type_t
constexpr bool no_realizations_v
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)
select_type_t< cond< has_static_halide_type_method_v< TBase >, GeneratorOutput_Buffer< T > >, cond< std::is_same_v< TBase, Func >, GeneratorOutput_Func< T > >, cond< std::is_arithmetic_v< TBase >, GeneratorOutput_Arithmetic< T > > > GeneratorOutputImplBase
ConstantInterval max(const ConstantInterval &a, const ConstantInterval &b)
select_type_t< cond< has_static_halide_type_method_v< TBase >, GeneratorInput_Buffer< T > >, cond< std::is_same_v< TBase, Func >, GeneratorInput_Func< T > >, cond< std::is_arithmetic_v< TBase >, GeneratorInput_Arithmetic< T > >, cond< std::is_scalar_v< TBase >, GeneratorInput_Scalar< T > >, cond< std::is_same_v< TBase, Expr >, GeneratorInput_DynamicScalar< T > > > GeneratorInputImplBase
select_type_t< cond< std::is_same_v< T, Target >, GeneratorParam_Target< T > >, cond< std::is_same_v< T, LoopLevel >, GeneratorParam_LoopLevel >, cond< std::is_same_v< T, std::string >, GeneratorParam_String< T > >, cond< std::is_same_v< T, Type >, GeneratorParam_Type< T > >, cond< std::is_same_v< T, bool >, GeneratorParam_Bool< T > >, cond< std::is_arithmetic_v< T >, GeneratorParam_Arithmetic< T > >, cond< std::is_enum_v< T >, GeneratorParam_Enum< T > > > GeneratorParamImplBase
HALIDE_NO_USER_CODE_INLINE std::string enum_to_string(const std::map< std::string, T > &enum_map, const T &t)
std::vector< Type > parse_halide_type_list(const std::string &types)
std::string halide_type_to_c_type(const Type &t)
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...
constexpr bool all_are_printable_args_v
std::unique_ptr< AbstractGenerator > AbstractGeneratorPtr
void execute_generator(const ExecuteGeneratorArgs &args)
Execute a Generator for AOT compilation – this provides the implementation of the command-line Genera...
HALIDE_NO_USER_CODE_INLINE void collect_print_args(std::vector< Expr > &args)
const GeneratorFactoryProvider & get_registered_generators()
Return a GeneratorFactoryProvider that knows about all the currently-registered C++ Generators.
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...
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.
@ 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.
std::map< std::string, std::string > GeneratorParamsMap
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 operator-(const Other &a, const GeneratorParam< T > &b) -> decltype(a -(T) b)
Subtraction between GeneratorParam<T> and any type that supports operator- with 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.
std::function< std::unique_ptr< Internal::CompilerLogger >(const std::string &fn_name, const Target &target)> CompilerLoggerFactory
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.
Callable create_callable_from_generator(const GeneratorContext &context, const std::string &name, const GeneratorParamsMap &generator_params={})
Create a Generator from the currently-registered Generators, use it to create a Callable.
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.
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.
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!...
Internal::ConstantInterval cast(Type t, const Internal::ConstantInterval &a)
Cast operators for ConstantIntervals.
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.
MemoryType
An enum describing different address spaces to be used with Func::store_in.
Partition
Different ways to handle loops with a potentially optimizable boundary conditions.
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
Special the Autoscheduler to be used (if any), along with arbitrary additional arguments specific to ...
A fragment of Halide syntax.
HALIDE_ALWAYS_INLINE Type type() const
Get the type of this expression node.
An argument to an extern-defined Func.
static TO2 value(const FROM &from)
The Dim struct represents one loop in the schedule's representation of a loop nest.
ExecuteGeneratorArgs is the set of arguments to execute_generator().
CompilerLoggerFactory compiler_logger_factory
std::string function_name
enum Halide::Internal::ExecuteGeneratorArgs::BuildMode build_mode
std::string file_base_name
CreateGeneratorFn create_generator
std::string generator_name
std::set< OutputFileType > output_types
std::vector< std::string > suffixes
std::vector< Target > targets
GeneratorParamsMap generator_params
std::function< AbstractGeneratorPtr(const std::string &name, const GeneratorContext &context)> CreateGeneratorFn
HALIDE_ALWAYS_INLINE bool defined() const
static constexpr bool value
std::conditional_t< First::value, typename First::type, void > type
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.