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;
298 for (
const auto &key_value : enum_map) {
299 if (t == key_value.second) {
300 return key_value.first;
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 =
typename std::conditional<First::value, typename First::type, void>::type;
400 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_;
489template<
typename FROM,
typename TO>
491 template<typename TO2 = TO, typename std::enable_if<!std::is_same<TO2, bool>::value>::type * =
nullptr>
492 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 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 bool try_set(
const std::string &key,
const std::string &
value);
679 if (new_value_string ==
"root") {
681 }
else if (new_value_string ==
"inlined") {
684 user_error <<
"Unable to parse " << this->
name() <<
": " << new_value_string;
701 return "LoopLevel::inlined()";
703 return "LoopLevel::root()";
712 return std::string();
729 const T &min = std::numeric_limits<T>::lowest(),
730 const T &max = std::numeric_limits<T>::max())
737 user_assert(new_value >= min && new_value <= max) <<
"Value out of range: " << new_value;
742 std::istringstream iss(new_value_string);
747 if (
sizeof(T) ==
sizeof(
char) && !std::is_same<T, bool>::value) {
754 user_assert(!iss.fail() && iss.get() == EOF) <<
"Unable to parse: " << new_value_string;
759 std::ostringstream oss;
760 oss << this->
value();
761 if (std::is_same<T, float>::value) {
764 if (oss.str().find(
'.') == std::string::npos) {
773 std::ostringstream oss;
774 oss <<
"std::to_string(" << v <<
")";
779 std::ostringstream oss;
780 if (std::is_same<T, float>::value) {
782 }
else if (std::is_same<T, double>::value) {
784 }
else if (std::is_integral<T>::value) {
785 if (std::is_unsigned<T>::value) {
788 oss <<
"int" << (
sizeof(T) * 8) <<
"_t";
809 if (new_value_string ==
"true" || new_value_string ==
"True") {
811 }
else if (new_value_string ==
"false" || new_value_string ==
"False") {
814 user_assert(
false) <<
"Unable to parse bool: " << new_value_string;
820 return this->
value() ?
"true" :
"false";
824 std::ostringstream oss;
825 oss <<
"std::string((" << v <<
") ? \"true\" : \"false\")";
844 template<typename T2 = T, typename std::enable_if<!std::is_same<T2, Type>::value>
::type * =
nullptr>
850 auto it = enum_map.find(new_value_string);
851 user_assert(it != enum_map.end()) <<
"Enumeration value not found: " << new_value_string;
856 return "Enum_" + this->
name() +
"_map().at(" + v +
")";
860 return "Enum_" + this->
name();
868 std::ostringstream oss;
869 oss <<
"enum class Enum_" << this->
name() <<
" {\n";
870 for (
auto key_value : enum_map) {
871 oss <<
" " << key_value.first <<
",\n";
878 oss <<
"inline HALIDE_NO_USER_CODE_INLINE const std::map<Enum_" << this->
name() <<
", std::string>& Enum_" << this->
name() <<
"_map() {\n";
879 oss <<
" static const std::map<Enum_" << this->
name() <<
", std::string> m = {\n";
880 for (
auto key_value : enum_map) {
881 oss <<
" { Enum_" << this->
name() <<
"::" << key_value.first <<
", \"" << key_value.first <<
"\"},\n";
884 oss <<
" return m;\n";
890 const std::map<std::string, T> enum_map;
901 return "Halide::Internal::halide_type_to_enum_string(" + v +
")";
924 this->
set(new_value_string);
928 return "\"" + this->
value() +
"\"";
936 return "std::string";
991 template<typename T2 = T, typename std::enable_if<!std::is_same<T2, std::string>::value>::type * =
nullptr>
993 :
Internal::GeneratorParamImplBase<T>(name, value) {
996 GeneratorParam(
const std::string &name,
const T &value,
const T &min,
const T &max)
997 :
Internal::GeneratorParamImplBase<T>(name, value, min, max) {
1000 GeneratorParam(
const std::string &name,
const T &value,
const std::map<std::string, T> &enum_map)
1001 :
Internal::GeneratorParamImplBase<T>(name, value, enum_map) {
1005 :
Internal::GeneratorParamImplBase<T>(name, value) {
1012template<
typename Other,
typename T>
1016template<
typename Other,
typename T>
1025template<
typename Other,
typename T>
1029template<
typename Other,
typename T>
1038template<
typename Other,
typename T>
1042template<
typename Other,
typename T>
1051template<
typename Other,
typename T>
1055template<
typename Other,
typename T>
1064template<
typename Other,
typename T>
1068template<
typename Other,
typename T>
1077template<
typename Other,
typename T>
1081template<
typename Other,
typename T>
1090template<
typename Other,
typename T>
1094template<
typename Other,
typename T>
1103template<
typename Other,
typename T>
1107template<
typename Other,
typename T>
1116template<
typename Other,
typename T>
1120template<
typename Other,
typename T>
1129template<
typename Other,
typename T>
1133template<
typename Other,
typename T>
1142template<
typename Other,
typename T>
1146template<
typename Other,
typename T>
1155template<
typename Other,
typename T>
1159template<
typename Other,
typename T>
1165 return (T)a && (T)b;
1172template<
typename Other,
typename T>
1176template<
typename Other,
typename T>
1182 return (T)a || (T)b;
1191namespace GeneratorMinMax {
1196template<
typename Other,
typename T>
1198 return min(a, (T)b);
1200template<
typename Other,
typename T>
1202 return min((T)a, b);
1205template<
typename Other,
typename T>
1207 return max(a, (T)b);
1209template<
typename Other,
typename T>
1211 return max((T)a, b);
1220template<
typename Other,
typename T>
1224template<
typename Other,
typename T>
1233template<
typename Other,
typename T>
1237template<
typename Other,
typename T>
1251template<
typename T2>
1252class GeneratorInput_Buffer;
1263template<typename T = void, int Dims = Buffer<>::AnyDims>
1266 template<
typename T2>
1268 template<
typename T2,
int D2>
1282 template<
typename T2,
int D2>
1298 template<
typename T2,
int D2>
1300 : parameter_(parameter_from_buffer(b)) {
1303 template<
typename T2>
1305 return {t.parameter_};
1308 template<
typename T2>
1310 std::vector<Parameter> r;
1311 r.reserve(v.size());
1312 for (
const auto &s : v) {
1313 r.push_back(s.parameter_);
1319class AbstractGenerator;
1334 template<
typename... Args>
1339 template<
typename Dst>
1357template<
typename T =
void>
1359 template<
typename T2>
1369 const std::shared_ptr<AbstractGenerator> &gen) {
1370 std::vector<StubOutputBuffer<T>> result;
1371 for (
const Func &
f : v) {
1391 template<
typename T2>
1472 const std::string &
name,
1474 const std::vector<Type> &types,
1507 template<
typename ElemType>
1517 template<
typename T>
1541 const std::string &
name,
1543 const std::vector<Type> &t,
1580template<
typename T,
typename ValueType>
1583 using TBase =
typename std::remove_all_extents<T>::type;
1586 return std::is_array<T>::value;
1589 template<
typename T2 = T,
typename std::enable_if<
1591 !std::is_array<T2>::value>::type * =
nullptr>
1596 template<
typename T2 = T,
typename std::enable_if<
1598 std::is_array<T2>::value && std::rank<T2>::value == 1 && (std::extent<T2, 0>::value > 0)>::type * =
nullptr>
1603 template<
typename T2 = T,
typename std::enable_if<
1605 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>::type * =
nullptr>
1611 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1617 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1623 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1624 const ValueType &
at(
size_t i)
const {
1629 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1630 typename std::vector<ValueType>::const_iterator
begin()
const {
1635 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1636 typename std::vector<ValueType>::const_iterator
end()
const {
1650#define HALIDE_FORWARD_METHOD(Class, Method) \
1651 template<typename... Args> \
1652 inline auto Method(Args &&...args) -> typename std::remove_reference<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))>::type { \
1653 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1656#define HALIDE_FORWARD_METHOD_CONST(Class, Method) \
1657 template<typename... Args> \
1658 inline auto Method(Args &&...args) const -> \
1659 typename std::remove_reference<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))>::type { \
1660 this->check_gio_access(); \
1661 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1665class GeneratorInput_Buffer :
public GeneratorInputImpl<T, Func> {
1667 using Super = GeneratorInputImpl<T, Func>;
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>
1717 this->check_gio_access();
1718 return Func(*
this)(std::forward<Args>(args)...);
1722 this->check_gio_access();
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();
1733 this->check_gio_access();
1734 return this->funcs().at(0);
1738 this->check_gio_access();
1743 this->check_gio_access();
1744 this->set_estimate_impl(var, min, extent);
1749 this->check_gio_access();
1750 this->set_estimates_impl(estimates);
1755 this->check_gio_access();
1760 this->check_gio_access();
1761 return Func(*this).
in(other);
1765 this->check_gio_access();
1766 return Func(*this).
in(others);
1770 this->check_gio_access();
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, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1777 this->check_gio_access();
1778 return this->parameters_.size();
1781 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1783 this->check_gio_access();
1784 return ImageParam(this->parameters_.at(i), this->funcs().at(i));
1787 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1789 this->check_gio_access();
1790 return ImageParam(this->parameters_.at(i), this->funcs().at(i));
1793 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1794 typename std::vector<ImageParam>::const_iterator
begin()
const {
1795 user_error <<
"Input<Buffer<>>::begin() is not supported.";
1799 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1800 typename std::vector<ImageParam>::const_iterator
end()
const {
1801 user_error <<
"Input<Buffer<>>::end() is not supported.";
1838 template<
typename T2>
1882 template<
typename... Args>
1884 this->check_gio_access();
1885 return this->funcs().at(0)(std::forward<Args>(args)...);
1889 this->check_gio_access();
1890 return this->funcs().at(0)(args);
1894 this->check_gio_access();
1895 return this->funcs().at(0);
1899 this->check_gio_access();
1904 this->check_gio_access();
1905 this->set_estimate_impl(var, min, extent);
1910 this->check_gio_access();
1911 this->set_estimates_impl(estimates);
1916 this->check_gio_access();
1921 this->check_gio_access();
1922 return Func(*this).
in(other);
1926 this->check_gio_access();
1927 return Func(*this).
in(others);
1955 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");
1965 user_assert(!std::is_array<T>::value) <<
"Input<Expr[]> is not allowed";
1971 this->check_gio_access();
1972 return this->exprs().at(0);
1978 this->check_gio_access();
1983 this->check_gio_access();
1984 for (
Parameter &p : this->parameters_) {
2006 for (
Parameter &p : this->parameters_) {
2019 template<typename TBase2 = TBase, typename std::enable_if<!std::is_pointer<TBase2>::value>::type * =
nullptr>
2021 return cast<TBase>(
Expr(value));
2024 template<typename TBase2 = TBase, typename std::enable_if<std::is_pointer<TBase2>::value>::type * =
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,
2047 :
Super(array_size, name,
ArgInfoKind::
Scalar, {type_of<TBase>()}, 0), def_(def), def_expr_(TBaseToExpr(def)) {
2053 this->check_gio_access();
2054 return this->exprs().at(0);
2060 this->check_gio_access();
2064 template<typename T2 = T, typename std::enable_if<std::is_pointer<T2>::value>::type * =
nullptr>
2066 this->check_gio_access();
2067 user_assert(value ==
nullptr) <<
"nullptr is the only valid estimate for Input<PointerType>";
2069 for (
Parameter &p : this->parameters_) {
2074 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value && !std::is_pointer<T2>::value>::type * =
nullptr>
2076 this->check_gio_access();
2078 if (std::is_same<T2, bool>::value) {
2081 for (
Parameter &p : this->parameters_) {
2086 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2088 this->check_gio_access();
2090 if (std::is_same<T2, bool>::value) {
2093 this->parameters_.at(index).set_estimate(e);
2112 Super::set_def_min_max();
2114 if (!std::is_same<TBase, bool>::value) {
2115 for (
Parameter &p : this->parameters_) {
2137 const std::string &name)
2142 const std::string &name,
2144 :
Super(array_size, name, def), min_(
Expr()), max_(
Expr()) {
2151 :
Super(name, def), min_(min), max_(max) {
2155 const std::string &name,
2159 :
Super(array_size, name, def), min_(min), max_(max) {
2168template<
typename T2,
typename =
void>
2171template<
typename T2>
2174template<typename T, typename TBase = typename std::remove_all_extents<T>::type>
2212 : Super(name, def) {
2216 : Super(array_size, name, def) {
2221 : Super(name, def, min, max) {
2226 : Super(array_size, name, def, min, max) {
2230 : Super(name, t, d) {
2243 : Super(array_size, name, t, d) {
2247 : Super(array_size, name, t) {
2253 : Super(array_size, name, d) {
2257 : Super(array_size, name) {
2265 template<typename T2, typename std::enable_if<std::is_same<T2, Func>::value>::type * =
nullptr>
2267 static_assert(std::is_same<T2, Func>::value,
"Only Func allowed here");
2270 user_assert(!funcs_.empty()) <<
"No funcs_ are defined yet";
2271 user_assert(funcs_.size() == 1) <<
"Use [] to access individual Funcs in Output<Func[]>";
2341#undef HALIDE_OUTPUT_FORWARD
2342#undef HALIDE_OUTPUT_FORWARD_CONST
2346 const std::string &name,
2348 const std::vector<Type> &t,
2353 const std::vector<Type> &t,
2357 friend class StubEmitter;
2379 using TBase =
typename std::remove_all_extents<T>::type;
2383 return std::is_array<T>::value;
2386 template<
typename T2 = T,
typename std::enable_if<
2388 !std::is_array<T2>::value>::type * =
nullptr>
2393 template<
typename T2 = T,
typename std::enable_if<
2395 std::is_array<T2>::value && std::rank<T2>::value == 1 && (std::extent<T2, 0>::value > 0)>::type * =
nullptr>
2400 template<
typename T2 = T,
typename std::enable_if<
2402 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>::type * =
nullptr>
2408 template<
typename... Args,
typename T2 = T,
typename std::enable_if<!std::is_array<T2>::value>::type * =
nullptr>
2410 this->check_gio_access();
2411 return get_values<ValueType>().at(0)(std::forward<Args>(args)...);
2414 template<typename ExprOrVar, typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * =
nullptr>
2416 this->check_gio_access();
2417 return get_values<ValueType>().at(0)(args);
2420 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * =
nullptr>
2422 this->check_gio_access();
2423 return get_values<ValueType>().at(0);
2426 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * =
nullptr>
2428 this->check_gio_access();
2429 return get_values<ValueType>().at(0);
2432 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2434 this->check_gio_access();
2435 return get_values<ValueType>().size();
2438 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2440 this->check_gio_access();
2441 return get_values<ValueType>()[i];
2444 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2446 this->check_gio_access();
2447 return get_values<ValueType>().at(i);
2450 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2451 typename std::vector<ValueType>::const_iterator
begin()
const {
2452 this->check_gio_access();
2453 return get_values<ValueType>().begin();
2456 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2457 typename std::vector<ValueType>::const_iterator
end()
const {
2458 this->check_gio_access();
2459 return get_values<ValueType>().end();
2462 template<
typename T2 = T,
typename std::enable_if<
2464 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>::type * =
nullptr>
2466 this->check_gio_access();
2467 GeneratorOutputBase::resize(size);
2477 this->check_value_writable();
2481 if (this->gio_types_defined()) {
2482 const auto &my_types = this->gio_types();
2484 <<
"Cannot assign Func \"" << f.
name()
2485 <<
"\" to Output \"" << this->name() <<
"\"\n"
2486 <<
"Output " << this->name()
2487 <<
" is declared to have " << my_types.size() <<
" tuple elements"
2488 <<
" but Func " << f.
name()
2489 <<
" has " << f.
types().size() <<
" tuple elements.\n";
2490 for (
size_t i = 0; i < my_types.size(); i++) {
2492 <<
"Cannot assign Func \"" << f.
name()
2493 <<
"\" to Output \"" << this->name() <<
"\"\n"
2494 << (my_types.size() > 1 ?
"In tuple element " + std::to_string(i) +
", " :
"")
2495 <<
"Output " << this->name()
2496 <<
" has declared type " << my_types[i]
2497 <<
" but Func " << f.
name()
2498 <<
" has type " << f.
types().at(i) <<
"\n";
2501 if (this->dims_defined()) {
2503 <<
"Cannot assign Func \"" << f.
name()
2504 <<
"\" to Output \"" << this->name() <<
"\"\n"
2505 <<
"Output " << this->name()
2506 <<
" has declared dimensionality " << this->dims()
2507 <<
" but Func " << f.
name()
2508 <<
" has dimensionality " << f.
dimensions() <<
"\n";
2513 this->funcs_[0] = f;
2521 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2522 TBase::has_static_dimensions ? TBase::static_dimensions() : -1) {
2529 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.");
2530 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2536 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.");
2541 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2544 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2549 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2550 TBase::has_static_dimensions ? TBase::static_dimensions() : -1) {
2557 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.");
2558 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2564 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.");
2569 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2572 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2576 if (TBase::has_static_halide_type) {
2577 return "Halide::Internal::StubOutputBuffer<" +
2581 return "Halide::Internal::StubOutputBuffer<>";
2585 template<typename T2, typename std::enable_if<!std::is_same<T2, Func>::value>::type * =
nullptr>
2597 template<
typename T2,
int D2>
2599 this->check_gio_access();
2600 this->check_value_writable();
2603 <<
"Cannot assign to the Output \"" << this->name()
2604 <<
"\": the expression is not convertible to the same Buffer type and/or dimensions.\n";
2606 if (this->gio_types_defined()) {
2608 <<
"Output " << this->name() <<
" should have type=" << this->gio_type() <<
" but saw type=" <<
Type(buffer.
type()) <<
"\n";
2610 if (this->dims_defined()) {
2612 <<
"Output " << this->name() <<
" should have dim=" << this->dims() <<
" but saw dim=" << buffer.dimensions() <<
"\n";
2617 this->funcs_.at(0)(_) = buffer(_);
2625 template<
typename T2>
2627 this->check_gio_access();
2628 assign_from_func(stub_output_buffer.
f);
2636 this->check_gio_access();
2637 assign_from_func(f);
2642 this->check_gio_access();
2643 user_assert(!this->is_array()) <<
"Cannot convert an Output<Buffer<>[]> to an ImageParam; use an explicit subscript operator: " << this->name();
2645 return this->funcs_.at(0).output_buffer();
2651 user_assert(!this->is_array()) <<
"Cannot call set_estimates() on an array Output; use an explicit subscript operator: " << this->name();
2653 this->funcs_.at(0).set_estimates(estimates);
2657 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2659 this->check_gio_access();
2660 return this->
template get_values<Func>()[i];
2664 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2666 this->check_gio_access();
2667 return this->
template get_values<Func>()[i];
2695 return this->funcs_.at(i);
2723 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * =
nullptr>
2725 this->check_gio_access();
2726 this->check_value_writable();
2730 get_assignable_func_ref(0) = f;
2735 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2737 this->check_gio_access();
2738 this->check_value_writable();
2739 return get_assignable_func_ref(i);
2743 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2745 this->check_gio_access();
2746 return Super::operator[](i);
2750 this->check_gio_access();
2752 for (
Func &f : this->funcs_) {
2753 f.set_estimate(var, min, extent);
2759 this->check_gio_access();
2761 for (
Func &f : this->funcs_) {
2762 f.set_estimates(estimates);
2785template<typename T, typename TBase = typename std::remove_all_extents<T>::type>
2815 : Super(array_size, name) {
2823 : Super(name, {t}) {
2831 : Super(name, {t}, d) {
2835 : Super(name, t, d) {
2839 : Super(array_size, name, d) {
2843 : Super(array_size, name, {t}) {
2846 explicit GeneratorOutput(
size_t array_size,
const std::string &name,
const std::vector<Type> &t)
2847 : Super(array_size, name, t) {
2851 : Super(array_size, name, {t}, d) {
2854 explicit GeneratorOutput(
size_t array_size,
const std::string &name,
const std::vector<Type> &t,
int d)
2855 : Super(array_size, name, t, d) {
2861 template<
typename T2,
int D2>
2863 Super::operator=(buffer);
2867 template<
typename T2>
2869 Super::operator=(stub_output_buffer);
2874 Super::operator=(f);
2883 std::istringstream iss(value);
2886 user_assert(!iss.fail() && iss.get() == EOF) <<
"Unable to parse: " << value;
2904 if (!error_msg.empty()) {
2907 set_from_string_impl<T>(new_value_string);
2912 return std::string();
2917 return std::string();
2922 return std::string();
2932 static std::unique_ptr<Internal::GeneratorParamBase> make(
2934 const std::string &generator_name,
2935 const std::string &gpname,
2939 std::string error_msg = defined ?
"Cannot set the GeneratorParam " + gpname +
" for " + generator_name +
" because the value is explicitly specified in the C++ source." :
"";
2940 return std::unique_ptr<GeneratorParam_Synthetic<T>>(
2948 template<typename T2 = T, typename std::enable_if<std::is_same<T2, ::Halide::Type>::value>::type * =
nullptr>
2949 void set_from_string_impl(
const std::string &new_value_string) {
2951 gio.types_ = parse_halide_type_list(new_value_string);
2954 template<typename T2 = T, typename std::enable_if<std::is_integral<T2>::value>::type * =
nullptr>
2955 void set_from_string_impl(
const std::string &new_value_string) {
2956 if (which == SyntheticParamType::Dim) {
2957 gio.dims_ = parse_scalar<T2>(new_value_string);
2958 }
else if (which == SyntheticParamType::ArraySize) {
2959 gio.array_size_ = parse_scalar<T2>(new_value_string);
2967 const std::string error_msg;
3025 return autoscheduler_params_;
3033 template<
typename T>
3035 return T::create(*
this);
3037 template<
typename T,
typename... Args>
3038 std::unique_ptr<T>
apply(
const Args &...args)
const {
3039 auto t = this->create<T>();
3073 template<
typename T>
3080 template<
typename T>
3082 template<
typename T = void,
int D = -1>
3084 template<
typename T>
3102template<
typename... Args>
3108template<
typename T,
typename... Args>
3110 static const bool value = !std::is_convertible<T, Realization>::value &&
NoRealizations<Args...>::value;
3119 std::set<std::string> names;
3122 std::vector<Internal::GeneratorParamBase *> filter_generator_params;
3125 std::vector<Internal::GeneratorInputBase *> filter_inputs;
3128 std::vector<Internal::GeneratorOutputBase *> filter_outputs;
3133 std::vector<std::unique_ptr<Internal::GeneratorParamBase>> owned_synthetic_params;
3136 std::vector<std::unique_ptr<Internal::GIOBase>> owned_extras;
3144 return filter_generator_params;
3146 const std::vector<Internal::GeneratorInputBase *> &
inputs()
const {
3147 return filter_inputs;
3149 const std::vector<Internal::GeneratorOutputBase *> &
outputs()
const {
3150 return filter_outputs;
3161 return get_target().natural_vector_size(t);
3166 template<
typename data_t>
3168 return get_target().natural_vector_size<data_t>();
3181 template<
typename... Args>
3186 <<
"Expected exactly " << pi.
inputs().size()
3187 <<
" inputs but got " <<
sizeof...(args) <<
"\n";
3188 set_inputs_vector(build_inputs(std::forward_as_tuple<const Args &...>(args...), std::make_index_sequence<
sizeof...(Args)>{}));
3192 this->check_scheduled(
"realize");
3193 return get_pipeline().realize(std::move(sizes), get_target());
3198 template<
typename... Args,
typename std::enable_if<
NoRealizations<Args...>::value>::type * =
nullptr>
3200 this->check_scheduled(
"realize");
3201 return get_pipeline().realize(std::forward<Args>(args)..., get_target());
3205 this->check_scheduled(
"realize");
3206 get_pipeline().realize(r, get_target());
3216 template<
typename T,
3217 typename std::enable_if<std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3219 check_exact_phase(GeneratorBase::ConfigureCalled);
3221 p->generator =
this;
3222 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3223 param_info_ptr->filter_inputs.push_back(p);
3228 template<
typename T,
3229 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3231 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 .");
3232 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.");
3233 check_exact_phase(GeneratorBase::ConfigureCalled);
3235 p->generator =
this;
3236 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3237 param_info_ptr->filter_inputs.push_back(p);
3242 template<
typename T,
3243 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3245 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.");
3246 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.");
3247 check_exact_phase(GeneratorBase::ConfigureCalled);
3249 p->generator =
this;
3250 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3251 param_info_ptr->filter_inputs.push_back(p);
3256 template<
typename T,
3257 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3259 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.");
3260 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.");
3261 check_exact_phase(GeneratorBase::ConfigureCalled);
3263 p->generator =
this;
3264 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3265 param_info_ptr->filter_inputs.push_back(p);
3269 template<
typename T,
3270 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3272 check_exact_phase(GeneratorBase::ConfigureCalled);
3274 p->generator =
this;
3275 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3276 param_info_ptr->filter_inputs.push_back(p);
3280 template<
typename T,
3281 typename std::enable_if<std::is_same<T, Expr>::value>::type * =
nullptr>
3283 check_exact_phase(GeneratorBase::ConfigureCalled);
3285 p->generator =
this;
3287 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3288 param_info_ptr->filter_inputs.push_back(p);
3293 template<
typename T,
3294 typename std::enable_if<std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3296 check_exact_phase(GeneratorBase::ConfigureCalled);
3298 p->generator =
this;
3299 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3300 param_info_ptr->filter_outputs.push_back(p);
3305 template<
typename T,
3306 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3308 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 .");
3309 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.");
3310 check_exact_phase(GeneratorBase::ConfigureCalled);
3312 p->generator =
this;
3313 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3314 param_info_ptr->filter_outputs.push_back(p);
3319 template<
typename T,
3320 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3322 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.");
3323 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.");
3324 check_exact_phase(GeneratorBase::ConfigureCalled);
3326 p->generator =
this;
3327 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3328 param_info_ptr->filter_outputs.push_back(p);
3333 template<
typename T,
3334 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3336 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.");
3337 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.");
3338 check_exact_phase(GeneratorBase::ConfigureCalled);
3340 p->generator =
this;
3341 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3342 param_info_ptr->filter_outputs.push_back(p);
3348 template<
typename... Args,
3351 std::vector<Expr> collected_args;
3352 Internal::collect_print_args(collected_args, std::forward<Args>(error_args)...);
3353 add_requirement(condition, collected_args);
3357 get_pipeline().trace_pipeline();
3434 template<
typename T>
3437 template<
typename T>
3473 return !autoscheduler_.value().name.empty();
3481 friend void ::Halide::Internal::generator_test();
3493 std::unique_ptr<GeneratorParamInfo> param_info_ptr;
3495 std::string generator_registered_name, generator_stub_name;
3498 struct Requirement {
3500 std::vector<Expr> error_args;
3502 std::vector<Requirement> requirements;
3507 template<
typename T>
3508 T *find_by_name(
const std::string &name,
const std::vector<T *> &v) {
3510 if (t->name() == name) {
3517 Internal::GeneratorInputBase *find_input_by_name(
const std::string &name);
3518 Internal::GeneratorOutputBase *find_output_by_name(
const std::string &name);
3520 void check_scheduled(
const char *m)
const;
3522 void build_params(
bool force =
false);
3531 void set_inputs_vector(
const std::vector<std::vector<StubInput>> &inputs);
3533 static void check_input_is_singular(Internal::GeneratorInputBase *in);
3534 static void check_input_is_array(Internal::GeneratorInputBase *in);
3535 static void check_input_kind(Internal::GeneratorInputBase *in, Internal::ArgInfoKind kind);
3541 template<
typename T,
int Dims>
3542 std::vector<StubInput> build_input(
size_t i,
const Buffer<T, Dims> &arg) {
3543 auto *in = param_info().inputs().at(i);
3544 check_input_is_singular(in);
3545 const auto k = in->kind();
3546 if (k == Internal::ArgInfoKind::Buffer) {
3548 StubInputBuffer<> sib(b);
3551 }
else if (k == Internal::ArgInfoKind::Function) {
3553 f(Halide::_) = arg(Halide::_);
3557 check_input_kind(in, Internal::ArgInfoKind::Buffer);
3566 template<
typename T,
int Dims>
3567 std::vector<StubInput> build_input(
size_t i,
const GeneratorInput<Buffer<T, Dims>> &arg) {
3568 auto *in = param_info().inputs().at(i);
3569 check_input_is_singular(in);
3570 const auto k = in->kind();
3571 if (k == Internal::ArgInfoKind::Buffer) {
3572 StubInputBuffer<> sib = arg;
3575 }
else if (k == Internal::ArgInfoKind::Function) {
3580 check_input_kind(in, Internal::ArgInfoKind::Buffer);
3586 std::vector<StubInput> build_input(
size_t i,
const Func &arg) {
3587 auto *in = param_info().inputs().at(i);
3588 check_input_kind(in, Internal::ArgInfoKind::Function);
3589 check_input_is_singular(in);
3596 std::vector<StubInput> build_input(
size_t i,
const std::vector<Func> &arg) {
3597 auto *in = param_info().inputs().at(i);
3598 check_input_kind(in, Internal::ArgInfoKind::Function);
3599 check_input_is_array(in);
3601 std::vector<StubInput> siv;
3602 siv.reserve(arg.size());
3603 for (
const auto &f : arg) {
3604 siv.emplace_back(f);
3610 std::vector<StubInput> build_input(
size_t i,
const Expr &arg) {
3611 auto *in = param_info().inputs().at(i);
3612 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3613 check_input_is_singular(in);
3619 std::vector<StubInput> build_input(
size_t i,
const std::vector<Expr> &arg) {
3620 auto *in = param_info().inputs().at(i);
3621 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3622 check_input_is_array(in);
3623 std::vector<StubInput> siv;
3624 siv.reserve(arg.size());
3625 for (
const auto &value : arg) {
3626 siv.emplace_back(value);
3633 template<
typename T,
3634 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3635 std::vector<StubInput> build_input(
size_t i,
const T &arg) {
3636 auto *in = param_info().inputs().at(i);
3637 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3638 check_input_is_singular(in);
3646 template<
typename T,
3647 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3648 std::vector<StubInput> build_input(
size_t i,
const std::vector<T> &arg) {
3649 auto *in = param_info().inputs().at(i);
3650 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3651 check_input_is_array(in);
3652 std::vector<StubInput> siv;
3653 siv.reserve(arg.size());
3654 for (
const auto &value : arg) {
3658 siv.emplace_back(e);
3663 template<
typename... Args,
size_t... Indices>
3664 std::vector<std::vector<StubInput>> build_inputs(
const std::tuple<const Args &...> &t, std::index_sequence<Indices...>) {
3665 return {build_input(Indices, std::get<Indices>(t))...};
3670 template<
typename T>
3671 static void get_arguments(std::vector<AbstractGenerator::ArgInfo> &args, ArgInfoDirection dir,
const T &t) {
3673 args.push_back({e->name(),
3676 e->gio_types_defined() ? e->gio_types() : std::vector<Type>{},
3677 e->dims_defined() ? e->dims() : 0});
3697 void bind_input(
const std::string &name,
const std::vector<Parameter> &v)
override;
3698 void bind_input(
const std::string &name,
const std::vector<Func> &v)
override;
3699 void bind_input(
const std::string &name,
const std::vector<Expr> &v)
override;
3721 using GeneratorFactoryMap = std::map<const std::string, GeneratorFactory>;
3723 GeneratorFactoryMap factories;
3743 :
Internal::GeneratorBase(sizeof(T)) {
3750 auto g = std::make_unique<T>();
3751 g->init_from_context(context);
3757 const std::string ®istered_name,
3758 const std::string &stub_name) {
3759 auto g = create(context);
3760 g->set_generator_names(registered_name, stub_name);
3764 template<
typename... Args>
3767 set_inputs(args...);
3772 template<
typename T2>
3774 return T2::create(context());
3777 template<
typename T2,
typename... Args>
3778 std::unique_ptr<T2>
apply(
const Args &...args)
const {
3779 auto t = this->create<T2>();
3792 template<
typename T2,
typename =
void>
3793 struct has_configure_method : std::false_type {};
3795 template<
typename T2>
3796 struct has_configure_method<T2, typename type_sink<decltype(std::declval<T2>().configure())>::type> : std::true_type {};
3798 template<
typename T2,
typename =
void>
3799 struct has_generate_method : std::false_type {};
3801 template<
typename T2>
3802 struct has_generate_method<T2, typename type_sink<decltype(std::declval<T2>().generate())>::type> : std::true_type {};
3804 template<
typename T2,
typename =
void>
3805 struct has_schedule_method : std::false_type {};
3807 template<
typename T2>
3808 struct has_schedule_method<T2, typename type_sink<decltype(std::declval<T2>().
schedule())>::type> : std::true_type {};
3810 Pipeline build_pipeline_impl() {
3817 t->call_generate_impl();
3818 t->call_schedule_impl();
3819 return get_pipeline();
3822 void call_configure_impl() {
3824 if constexpr (has_configure_method<T>::value) {
3826 static_assert(std::is_void<
decltype(t->configure())>::value,
"configure() must return void");
3832 void call_generate_impl() {
3834 static_assert(has_generate_method<T>::value,
"Expected a generate() method here.");
3836 static_assert(std::is_void<
decltype(t->generate())>::value,
"generate() must return void");
3841 void call_schedule_impl() {
3843 if constexpr (has_schedule_method<T>::value) {
3845 static_assert(std::is_void<
decltype(t->schedule())>::value,
"schedule() must return void");
3853 ensure_configure_has_been_called();
3854 return this->build_pipeline_impl();
3858 this->call_configure_impl();
3862 this->call_generate_impl();
3866 this->call_schedule_impl();
3870 friend void ::Halide::Internal::generator_test();
3871 friend void ::Halide::Internal::generator_test();
3872 friend class ::Halide::GeneratorContext;
3956 bool log_outputs =
false;
3975 const std::string &name,
3978 const std::string &name,
3988struct halide_global_ns;
3991#define _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
3992 namespace halide_register_generator { \
3993 struct halide_global_ns; \
3994 namespace GEN_REGISTRY_NAME##_ns { \
3995 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
3996 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context) { \
3997 using GenType = std::remove_pointer<decltype(new GEN_CLASS_NAME)>::type; \
3998 return GenType::create(context, #GEN_REGISTRY_NAME, #FULLY_QUALIFIED_STUB_NAME); \
4002 auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
4005 static_assert(std::is_same<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>::value, \
4006 "HALIDE_REGISTER_GENERATOR must be used at global scope");
4008#define _HALIDE_REGISTER_GENERATOR2(GEN_CLASS_NAME, GEN_REGISTRY_NAME) \
4009 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, GEN_REGISTRY_NAME)
4011#define _HALIDE_REGISTER_GENERATOR3(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
4012 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME)
4017#define __HALIDE_REGISTER_ARGCOUNT_IMPL(_1, _2, _3, COUNT, ...) \
4020#define _HALIDE_REGISTER_ARGCOUNT_IMPL(ARGS) \
4021 __HALIDE_REGISTER_ARGCOUNT_IMPL ARGS
4023#define _HALIDE_REGISTER_ARGCOUNT(...) \
4024 _HALIDE_REGISTER_ARGCOUNT_IMPL((__VA_ARGS__, 3, 2, 1, 0))
4026#define ___HALIDE_REGISTER_CHOOSER(COUNT) \
4027 _HALIDE_REGISTER_GENERATOR##COUNT
4029#define __HALIDE_REGISTER_CHOOSER(COUNT) \
4030 ___HALIDE_REGISTER_CHOOSER(COUNT)
4032#define _HALIDE_REGISTER_CHOOSER(COUNT) \
4033 __HALIDE_REGISTER_CHOOSER(COUNT)
4035#define _HALIDE_REGISTER_GENERATOR_PASTE(A, B) \
4038#define HALIDE_REGISTER_GENERATOR(...) \
4039 _HALIDE_REGISTER_GENERATOR_PASTE(_HALIDE_REGISTER_CHOOSER(_HALIDE_REGISTER_ARGCOUNT(__VA_ARGS__)), (__VA_ARGS__))
4055#define HALIDE_REGISTER_GENERATOR_ALIAS(GEN_REGISTRY_NAME, ORIGINAL_REGISTRY_NAME, ...) \
4056 namespace halide_register_generator { \
4057 struct halide_global_ns; \
4058 namespace ORIGINAL_REGISTRY_NAME##_ns { \
4059 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
4061 namespace GEN_REGISTRY_NAME##_ns { \
4062 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context) { \
4063 auto g = ORIGINAL_REGISTRY_NAME##_ns::factory(context); \
4064 const Halide::GeneratorParamsMap m = __VA_ARGS__; \
4065 g->set_generatorparam_values(m); \
4070 auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
4073 static_assert(std::is_same<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>::value, \
4074 "HALIDE_REGISTER_GENERATOR_ALIAS must be used at global scope");
4079#define HALIDE_GENERATOR_PYSTUB(GEN_REGISTRY_NAME, MODULE_NAME) \
4080 static_assert(PY_MAJOR_VERSION >= 3, "Python bindings for Halide require Python 3+"); \
4081 extern "C" PyObject *_halide_pystub_impl(const char *module_name, const Halide::Internal::GeneratorFactory &factory); \
4082 namespace halide_register_generator::GEN_REGISTRY_NAME##_ns { \
4083 extern std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
4085 extern "C" HALIDE_EXPORT_SYMBOL PyObject *PyInit_##MODULE_NAME() { \
4086 const auto factory = halide_register_generator::GEN_REGISTRY_NAME##_ns::factory; \
4087 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.
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.
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)
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)
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
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)
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)
Forward schedule-related methods to the underlying Func.
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
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
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)
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.
int dimensions() const
Get the dimensionality of this parameter.
void set_max_value(const Expr &e)
void set_buffer(const Buffer< void > &b)
If the parameter is a buffer parameter, set its current value.
void set_min_value(const Expr &e)
Get and set constraints for scalar parameters.
void set_estimate(Expr e)
Type type() const
Get the type of this parameter.
A class representing a Halide pipeline.
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))
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)
generate_filter_main() is a convenient wrapper for GeneratorRegistry::create() + compile_to_files(); ...
std::string halide_type_to_enum_string(const Type &t)
ConstantInterval min(const ConstantInterval &a, const ConstantInterval &b)
std::vector< Expr > parameter_constraints(const Parameter &p)
Expr make_const(Type t, int64_t val)
Construct an immediate of the given type from any numeric C++ type.
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
std::string halide_type_to_c_source(const Type &t)
std::function< AbstractGeneratorPtr(const GeneratorContext &context)> GeneratorFactory
ConstantInterval max(const ConstantInterval &a, const ConstantInterval &b)
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)
void execute_generator(const ExecuteGeneratorArgs &args)
Execute a Generator for AOT compilation – this provides the implementation of the command-line Genera...
std::unique_ptr< AbstractGenerator > AbstractGeneratorPtr
const GeneratorFactoryProvider & get_registered_generators()
Return a GeneratorFactoryProvider that knows about all the currently-registered C++ Generators.
typename select_type< cond< std::is_same< T, Target >::value, GeneratorParam_Target< 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
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.
std::function< std::unique_ptr< Internal::CompilerLogger >(const std::string &fn_name, const Target &target)> CompilerLoggerFactory
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.
Type type_of()
Construct the halide equivalent of a C type.
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.
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.
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.
@ Default
Match whatever is specified in the Target.
Target get_jit_target_from_environment()
Return the target that Halide will use for jit-compilation.
std::map< std::string, std::string > GeneratorParamsMap
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!...
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.
Expr max(const FuncRef &a, const FuncRef &b)
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().
std::string function_name
std::string file_base_name
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
typename std::conditional< First::value, typename First::type, void >::type type
A struct representing a target machine and os to generate code for.
Types in the halide type system.