From 970328fadd27a7cec1ae0dfe59e49255e514d9d9 Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Wed, 4 Mar 2026 14:09:28 -0800 Subject: [PATCH 1/2] Remove stubs entirely stubs never really moved beyond proof-of-concept. E.g. there is no cmake support for them, and the one app that uses them has no build. This PR removes them entirely. Opened for discussion. Co-authored-by: Claude Code --- Makefile | 39 +- apps/CMakeLists.txt | 1 - apps/linear_blur/linear_blur_generator.cpp | 32 - apps/linear_blur/linear_to_srgb_generator.cpp | 43 -- apps/linear_blur/run_linear_blur.cpp | 39 -- apps/linear_blur/simple_blur_generator.cpp | 51 -- apps/linear_blur/srgb_to_linear_generator.cpp | 43 -- cmake/HalideGeneratorHelpers.cmake | 2 - .../src/halide/halide_/PyEnums.cpp | 1 - .../src/halide/halide_/PyGenerator.cpp | 6 - python_bindings/stub/PyStubImpl.cpp | 2 - src/AbstractGenerator.h | 15 - src/Generator.cpp | 547 +----------------- src/Generator.h | 285 ++------- src/Module.cpp | 1 - src/Module.h | 1 - test/correctness/compile_to_multitarget.cpp | 3 - test/generator/CMakeLists.txt | 9 - .../abstractgeneratortest_generator.cpp | 5 - test/generator/configure_jittest.cpp | 39 +- test/generator/example_jittest.cpp | 51 +- test/generator/stubtest_aottest.cpp | 103 ---- test/generator/stubtest_generator.cpp | 109 ---- test/generator/stubtest_jittest.cpp | 290 ---------- test/generator/stubuser_aottest.cpp | 87 --- test/generator/stubuser_generator.cpp | 114 ---- 26 files changed, 63 insertions(+), 1855 deletions(-) delete mode 100644 apps/linear_blur/linear_blur_generator.cpp delete mode 100644 apps/linear_blur/linear_to_srgb_generator.cpp delete mode 100644 apps/linear_blur/run_linear_blur.cpp delete mode 100644 apps/linear_blur/simple_blur_generator.cpp delete mode 100644 apps/linear_blur/srgb_to_linear_generator.cpp delete mode 100644 test/generator/stubtest_aottest.cpp delete mode 100644 test/generator/stubtest_generator.cpp delete mode 100644 test/generator/stubtest_jittest.cpp delete mode 100644 test/generator/stubuser_aottest.cpp delete mode 100644 test/generator/stubuser_generator.cpp diff --git a/Makefile b/Makefile index 9e775869e1d3..38f73afaeb09 100644 --- a/Makefile +++ b/Makefile @@ -1326,10 +1326,6 @@ GENERATOR_AOTCPP_TESTS := $(filter-out generator_aotcpp_msan,$(GENERATOR_AOTCPP_ # https://github.com/halide/Halide/issues/7272 GENERATOR_AOTCPP_TESTS := $(filter-out generator_aotcpp_memory_profiler_mandelbrot,$(GENERATOR_AOTCPP_TESTS)) -# https://github.com/halide/Halide/issues/4916 -GENERATOR_AOTCPP_TESTS := $(filter-out generator_aotcpp_stubtest,$(GENERATOR_AOTCPP_TESTS)) -GENERATOR_AOTCPP_TESTS := $(filter-out generator_aotcpp_stubuser,$(GENERATOR_AOTCPP_TESTS)) - # Build requirements are finicky, testing non-C++ backend is good enough here GENERATOR_AOTCPP_TESTS := $(filter-out generator_aotcpp_gpu_multi_context_threaded,$(GENERATOR_AOTCPP_TESTS)) @@ -1535,10 +1531,6 @@ $(FILTERS_DIR)/%.halide_generated.cpp: $(FILTERS_DIR)/%.a $(FILTERS_DIR)/%.registration.cpp: $(FILTERS_DIR)/%.a @echo $@ produced implicitly by $^ -$(FILTERS_DIR)/%.stub.h: $(BIN_DIR)/%.generator - @mkdir -p $(@D) - $(CURDIR)/$< -g $* -n $* -o $(CURDIR)/$(FILTERS_DIR) -e cpp_stub - $(FILTERS_DIR)/cxx_mangling_externs.o: $(ROOT_DIR)/test/generator/cxx_mangling_externs.cpp @mkdir -p $(@D) $(CXX) $(GEN_AOT_CXX_FLAGS) -c $(filter-out %.h,$^) $(GEN_AOT_INCLUDES) -o $@ @@ -1700,28 +1692,6 @@ endif $(BIN_DIR)/$(TARGET)/generator_aotcpp_cxx_mangling: $(FILTERS_DIR)/cxx_mangling_externs.o $(BIN_DIR)/$(TARGET)/generator_aotcpp_cxx_mangling_define_extern: $(FILTERS_DIR)/cxx_mangling.halide_generated.cpp $(FILTERS_DIR)/cxx_mangling_externs.o $(FILTERS_DIR)/cxx_mangling_define_extern_externs.o -$(BUILD_DIR)/stubuser_generator.o: $(FILTERS_DIR)/stubtest.stub.h $(FILTERS_DIR)/configure.stub.h -$(BIN_DIR)/stubuser.generator: $(BUILD_DIR)/stubtest_generator.o $(BUILD_DIR)/configure_generator.o - -# stubtest has input and output funcs with undefined types and array sizes; this is fine for stub -# usage (the types can be inferred), but for AOT compilation, we must make the types -# concrete via generator args. -STUBTEST_GENERATOR_ARGS=\ - untyped_buffer_input.type=uint8 untyped_buffer_input.dim=3 \ - simple_input.type=float32 \ - array_input.type=float32 array_input.size=2 \ - int_arg.size=2 \ - tuple_output.type=float32,float32 \ - vectorize=true - -$(FILTERS_DIR)/stubtest.a: $(BIN_DIR)/stubtest.generator - @mkdir -p $(@D) - $(CURDIR)/$< -g stubtest -f stubtest $(GEN_AOT_OUTPUTS) -o $(CURDIR)/$(FILTERS_DIR) target=$(TARGET)-no_runtime $(STUBTEST_GENERATOR_ARGS) - -$(FILTERS_DIR)/stubuser_auto.a: $(BIN_DIR)/stubuser.generator $(BIN_MULLAPUDI2016) - @mkdir -p $(@D) - $(CURDIR)/$< -g stubuser $(GEN_AOT_OUTPUTS) -o $(CURDIR)/$(FILTERS_DIR) -f stubuser_auto target=$(TARGET)-no_runtime autoscheduler=Mullapudi2016 -p $(BIN_MULLAPUDI2016) - $(FILTERS_DIR)/autograd_grad.a: $(BIN_DIR)/autograd.generator $(BIN_MULLAPUDI2016) @mkdir -p $(@D) $(CURDIR)/$< -g autograd $(GEN_AOT_OUTPUTS) -o $(CURDIR)/$(FILTERS_DIR) -f autograd_grad target=$(TARGET)-no_runtime autoscheduler=Mullapudi2016 -d 1 -p $(BIN_MULLAPUDI2016) @@ -1827,16 +1797,11 @@ $(BIN_DIR)/$(TARGET)/generator_aotcpp_define_extern_opencl: $(ROOT_DIR)/test/gen @mkdir -p $(@D) $(CXX) $(GEN_AOT_CXX_FLAGS) $(filter %.cpp %.o %.a,$^) $(GEN_AOT_INCLUDES) $(GEN_AOT_LD_FLAGS) $(OPENCL_LD_FLAGS) -o $@ -# By default, %_jittest.cpp depends on libHalide, plus the stubs for the Generator. These are external tests that use the JIT. -$(BIN_DIR)/generator_jit_%: $(ROOT_DIR)/test/generator/%_jittest.cpp $(TEST_DEPS) $(FILTERS_DIR)/%.stub.h $(BUILD_DIR)/%_generator.o +# By default, %_jittest.cpp depends on libHalide. These are external tests that use the JIT. +$(BIN_DIR)/generator_jit_%: $(ROOT_DIR)/test/generator/%_jittest.cpp $(TEST_DEPS) $(BUILD_DIR)/%_generator.o @mkdir -p $(@D) $(CXX) -g $(TEST_CXX_FLAGS) $(filter %.cpp %.o %.a,$^) -I$(INCLUDE_DIR) -I$(FILTERS_DIR) -I $(ROOT_DIR)/apps/support $(TEST_LD_FLAGS) -o $@ -# stubuser is run with autoscheduling too -$(BIN_DIR)/$(TARGET)/generator_aot_stubuser: $(ROOT_DIR)/test/generator/stubuser_aottest.cpp $(FILTERS_DIR)/stubuser.a $(FILTERS_DIR)/stubuser.h $(FILTERS_DIR)/stubuser_auto.a $(FILTERS_DIR)/stubuser_auto.h $(RUNTIME_EXPORTED_INCLUDES) $(BIN_DIR)/$(TARGET)/runtime.a - @mkdir -p $(@D) - $(CXX) $(GEN_AOT_CXX_FLAGS) $(filter %.cpp %.o %.a,$^) $(GEN_AOT_INCLUDES) $(GEN_AOT_LD_FLAGS) -o $@ - # generator_aot_multitarget is run multiple times, with different env vars. generator_aot_multitarget: $(BIN_DIR)/$(TARGET)/generator_aot_multitarget @mkdir -p $(@D) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 6ffd7966a991..9a54fc620786 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -52,7 +52,6 @@ add_app(iir_blur) add_app(interpolate) add_app(lens_blur) add_app(linear_algebra) -# add_app(linear_blur) # TODO(#5374): missing CMake build add_app(local_laplacian) add_app(max_filter) add_app(nl_means) diff --git a/apps/linear_blur/linear_blur_generator.cpp b/apps/linear_blur/linear_blur_generator.cpp deleted file mode 100644 index ec9db2e8097b..000000000000 --- a/apps/linear_blur/linear_blur_generator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "Halide.h" -#include "linear_to_srgb.stub.h" -#include "simple_blur.stub.h" -#include "srgb_to_linear.stub.h" - -namespace { - -struct LinearBlur : public Halide::Generator { - Input> input{"input"}; - Output> output{"output"}; - - void generate() { - Var x("x"), y("y"), c("c"); - - Func linear = srgb_to_linear::generate(this, {input}); - Func blurred = simple_blur::generate(this, {linear, input.width(), input.height()}); - Func srgb = linear_to_srgb::generate(this, {blurred}); - output(x, y, c) = srgb(x, y, c); - - if (using_autoscheduler()) { - input.set_estimates({{0, 1536}, {0, 2560}, {0, 4}}); - output.set_estimates({{0, 1536}, {0, 2560}, {0, 4}}); - } else { - assert(false && "non-auto_schedule not supported."); - abort(); - } - } -}; - -} // namespace - -HALIDE_REGISTER_GENERATOR(LinearBlur, linear_blur) diff --git a/apps/linear_blur/linear_to_srgb_generator.cpp b/apps/linear_blur/linear_to_srgb_generator.cpp deleted file mode 100644 index a45285e3b5a8..000000000000 --- a/apps/linear_blur/linear_to_srgb_generator.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "Halide.h" - -namespace { - -struct LinearTosRGB : public Halide::Generator { - Input linear{"linear"}; - Output srgb{"srgb"}; - - Var x{"x"}, y{"y"}; - - void generate() { - using Halide::_; - - srgb(x, y, _) = select(linear(x, y, _) <= .0031308f, - linear(x, y, _) * 12.92f, - (1 + .055f) * pow(linear(x, y, _), 1.0f / 2.4f) - .055f); - } - - void schedule() { - if (using_autoscheduler()) { - const int W = 1536, H = 2560, C = 4; - // Wart: Input are defined with Vars we don't know. - // Might be x,y but might be _0,_1. Use the args() to work around. - linear.set_estimate(linear.args()[0], 0, W) - .set_estimate(linear.args()[1], 0, H); - for (size_t i = 2; i < linear.args().size(); ++i) { - linear.set_estimate(linear.args()[i], 0, C); - } - srgb.set_estimate(x, 0, W) - .set_estimate(y, 0, H); - for (size_t i = 2; i < srgb.args().size(); ++i) { - srgb.set_estimate(srgb.args()[i], 0, C); - } - } else { - Var yi("yi"); - srgb.split(y, y, yi, 8).parallel(y).vectorize(x, 8); - } - } -}; - -} // namespace - -HALIDE_REGISTER_GENERATOR(LinearTosRGB, linear_to_srgb) diff --git a/apps/linear_blur/run_linear_blur.cpp b/apps/linear_blur/run_linear_blur.cpp deleted file mode 100644 index 8f44ffd542bf..000000000000 --- a/apps/linear_blur/run_linear_blur.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include - -#include "linear_blur.h" -#include "simple_blur.h" - -#include "HalideBuffer.h" -#include "halide_image_io.h" - -using namespace Halide::Tools; -using namespace Halide::Runtime; - -int main(int argc, char **argv) { - if (argc != 4) { - printf("Usage: ./linear_blur use_linear input.png output.png\n"); - return 0; - } - - int use_linear = atoi(argv[1]); - - Buffer input = load_and_convert_image(argv[2]); - Buffer output = Buffer::make_with_shape_of(input); - - // Call either the simple or linear-corrected blur at runtime, - // mainly to demonstrate how simple_blur can be used either standalone - // or fused into another Generator. - if (use_linear) { - printf("Using linear blur...\n"); - linear_blur(input, output); - } else { - printf("Using simple blur...\n"); - simple_blur(input, input.width(), input.height(), output); - } - - convert_and_save_image(output, argv[3]); - - return 0; -} diff --git a/apps/linear_blur/simple_blur_generator.cpp b/apps/linear_blur/simple_blur_generator.cpp deleted file mode 100644 index 78d23ae253cd..000000000000 --- a/apps/linear_blur/simple_blur_generator.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "Halide.h" - -namespace { - -struct SimpleBlur : public Halide::Generator { - Input input{"input"}; - Input width{"width"}; - Input height{"height"}; - Output output{"output"}; - - Var x{"x"}, y{"y"}; - Func blur_x{"blur_x"}; - - void generate() { - using Halide::_; - - // Since Input has no extent limits, we must specify explicit min-extent pairs - Func in = Halide::BoundaryConditions::repeat_edge(input, {{0, width}, {0, height}}); - - blur_x(x, y, _) = (in(x, y, _) + in(x + 1, y, _) + in(x + 2, y, _)) / 3; - output(x, y, _) = (blur_x(x, y, _) + blur_x(x, y + 1, _) + blur_x(x, y + 2, _)) / 3; - } - - void schedule() { - if (using_autoscheduler()) { - const int W = 1536, H = 2560, C = 4; - // Wart: Input are defined with Vars we don't know. - // Might be x,y but might be _0,_1. Use the args() to work around. - input.set_estimate(input.args()[0], 0, W) - .set_estimate(input.args()[1], 0, H); - for (size_t i = 2; i < input.args().size(); ++i) { - input.set_estimate(input.args()[i], 0, C); - } - width.set_estimate(W); - height.set_estimate(H); - output.set_estimate(x, 0, W) - .set_estimate(y, 0, H); - for (size_t i = 2; i < output.args().size(); ++i) { - output.set_estimate(output.args()[i], 0, C); - } - } else { - Var xi("xi"), yi("yi"); - output.split(y, y, yi, 8).parallel(y).vectorize(x, 8); - blur_x.store_at(output, y).compute_at(output, yi).vectorize(x, 8); - } - } -}; - -} // namespace - -HALIDE_REGISTER_GENERATOR(SimpleBlur, simple_blur) diff --git a/apps/linear_blur/srgb_to_linear_generator.cpp b/apps/linear_blur/srgb_to_linear_generator.cpp deleted file mode 100644 index 95cf203ada85..000000000000 --- a/apps/linear_blur/srgb_to_linear_generator.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "Halide.h" - -namespace { - -struct sRGBToLinear : public Halide::Generator { - Input srgb{"srgb"}; - Output linear{"linear"}; - - Var x{"x"}, y{"y"}; - - void generate() { - using Halide::_; - - linear(x, y, _) = select(srgb(x, y, _) <= 0.04045f, - srgb(x, y, _) / 12.92f, - pow(((srgb(x, y, _) + .055f) / (1.0f + .055f)), 2.4f)); - } - - void schedule() { - if (using_autoscheduler()) { - const int W = 1536, H = 2560, C = 4; - // Wart: Input are defined with Vars we don't know. - // Might be x,y but might be _0,_1. Use the args() to work around. - srgb.set_estimate(srgb.args()[0], 0, W) - .set_estimate(srgb.args()[1], 0, H); - for (size_t i = 2; i < srgb.args().size(); ++i) { - srgb.set_estimate(srgb.args()[i], 0, C); - } - linear.set_estimate(x, 0, W) - .set_estimate(y, 0, H); - for (size_t i = 2; i < linear.args().size(); ++i) { - linear.set_estimate(linear.args()[i], 0, C); - } - } else { - Var yi("yi"); - linear.split(y, y, yi, 8).parallel(y).vectorize(x, 8); - } - } -}; - -} // namespace - -HALIDE_REGISTER_GENERATOR(sRGBToLinear, srgb_to_linear) diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index 324f44a31985..319629e631dc 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -181,7 +181,6 @@ function(_Halide_library_from_generator TARGET) set(compiler_log_extension ".halide_compiler_log") set(conceptual_stmt_extension ".conceptual.stmt") set(conceptual_stmt_html_extension ".conceptual.stmt.html") - # set(cpp_stub_extension ".stub.h") # not implemented set(device_code_extension ".device_code") set(featurization_extension ".featurization") set(function_info_header_extension ".function_info.h") @@ -448,7 +447,6 @@ function(add_halide_library TARGET) # See Module.cpp for list of extra outputs. The following outputs intentionally do not appear: # - `c_header` is always generated - # - `cpp_stub` is not available # - `object` is selected for CMake-target-compile # - `static_library` is selected for cross-compile set(extra_output_names diff --git a/python_bindings/src/halide/halide_/PyEnums.cpp b/python_bindings/src/halide/halide_/PyEnums.cpp index af5519896b9e..9d507a87f4ad 100644 --- a/python_bindings/src/halide/halide_/PyEnums.cpp +++ b/python_bindings/src/halide/halide_/PyEnums.cpp @@ -230,7 +230,6 @@ void define_enums(py::module &m) { .value("c_header", OutputFileType::c_header) .value("c_source", OutputFileType::c_source) .value("compiler_log", OutputFileType::compiler_log) - .value("cpp_stub", OutputFileType::cpp_stub) .value("featurization", OutputFileType::featurization) .value("function_info_header", OutputFileType::function_info_header) .value("hlpipe", OutputFileType::hlpipe) diff --git a/python_bindings/src/halide/halide_/PyGenerator.cpp b/python_bindings/src/halide/halide_/PyGenerator.cpp index 5be07944eb86..6a0af65c3204 100644 --- a/python_bindings/src/halide/halide_/PyGenerator.cpp +++ b/python_bindings/src/halide/halide_/PyGenerator.cpp @@ -87,12 +87,6 @@ class PyGeneratorBase : public AbstractGenerator { generator_.attr("_bind_input")(v); } - bool emit_cpp_stub(const std::string & /*stub_file_path*/) override { - // Python Generators don't support this (and *never* will, so don't ask), - // but don't throw an error, just return false. - return false; - } - bool emit_hlpipe(const std::string & /*hlpipe_file_path*/) override { // Python Generators don't support this yet ... // but don't throw an error, just return false. diff --git a/python_bindings/stub/PyStubImpl.cpp b/python_bindings/stub/PyStubImpl.cpp index 223935a8d3e1..dd63dcd7bfdc 100644 --- a/python_bindings/stub/PyStubImpl.cpp +++ b/python_bindings/stub/PyStubImpl.cpp @@ -25,8 +25,6 @@ namespace PythonBindings { using ArgInfoKind = Internal::ArgInfoKind; using ArgInfo = Internal::AbstractGenerator::ArgInfo; using GeneratorFactory = Internal::GeneratorFactory; -using StubInput = Internal::StubInput; -using StubInputBuffer = Internal::StubInputBuffer; namespace { diff --git a/src/AbstractGenerator.h b/src/AbstractGenerator.h index 39c50c1d08f4..4ef1b7759d34 100644 --- a/src/AbstractGenerator.h +++ b/src/AbstractGenerator.h @@ -162,21 +162,6 @@ class AbstractGenerator { virtual void bind_input(const std::string &name, const std::vector &v) = 0; // @} - /** Emit a Generator Stub (.stub.h) file to the given path. Not all Generators support this. - * - * If you call this method, you should not call any other AbstractGenerator methods - * on this instance, before or after this call. - * - * If the Generator is capable of emitting a Stub, do so and return true. (Errors - * during stub emission should assert-fail rather than returning false.) - * - * If the Generator is not capable of emitting a Stub, do nothing and return false. - * - * CALL-AFTER: none - * CALL-BEFORE: none - */ - virtual bool emit_cpp_stub(const std::string &stub_file_path) = 0; - /** Emit a Serialized Halide Pipeline (.hlpipe) file to the given path. Not all Generators support this. * * If you call this method, you should not call any other AbstractGenerator methods diff --git a/src/Generator.cpp b/src/Generator.cpp index 7c96226e0bec..8780b67fbddd 100644 --- a/src/Generator.cpp +++ b/src/Generator.cpp @@ -123,475 +123,7 @@ std::vector parse_halide_type_list(const std::string &types) { return result; } -class StubEmitter { -public: - StubEmitter(std::ostream &dest, - const std::string &generator_registered_name, - const std::string &generator_stub_name, - const std::vector &generator_params, - const std::vector &inputs, - const std::vector &outputs) - : stream(dest), - generator_registered_name(generator_registered_name), - generator_stub_name(generator_stub_name), - generator_params(select_generator_params(generator_params)), - inputs(inputs), - outputs(outputs) { - namespaces = split_string(generator_stub_name, "::"); - internal_assert(!namespaces.empty()); - if (namespaces[0].empty()) { - // We have a name like ::foo::bar::baz; omit the first empty ns. - namespaces.erase(namespaces.begin()); - internal_assert(namespaces.size() >= 2); - } - class_name = namespaces.back(); - namespaces.pop_back(); - } - void emit(); - -private: - std::ostream &stream; - const std::string generator_registered_name; - const std::string generator_stub_name; - std::string class_name; - std::vector namespaces; - const std::vector generator_params; - const std::vector inputs; - const std::vector outputs; - int indent_level{0}; - - std::vector select_generator_params(const std::vector &in) { - std::vector out; - for (auto *p : in) { - // These are always propagated specially. - if (p->name() == "target" || - p->name() == "autoscheduler") { - continue; - } - if (p->is_synthetic_param()) { - continue; - } - out.push_back(p); - } - return out; - } - - /** Emit spaces according to the current indentation level */ - Indentation get_indent() const { - return Indentation{indent_level}; - } - - void emit_inputs_struct(); - void emit_generator_params_struct(); -}; - -void StubEmitter::emit_generator_params_struct() { - const auto &v = generator_params; - std::string name = "GeneratorParams"; - stream << get_indent() << "struct " << name << " final {\n"; - indent_level++; - if (!v.empty()) { - for (auto *p : v) { - stream << get_indent() << p->get_c_type() << " " << p->name() << "{ " << p->get_default_value() << " };\n"; - } - stream << "\n"; - } - - stream << get_indent() << name << "() {}\n"; - stream << "\n"; - - if (!v.empty()) { - stream << get_indent() << name << "(\n"; - indent_level++; - std::string comma = ""; - for (auto *p : v) { - std::string c_type = p->get_c_type(); - if (c_type == "AutoschedulerParams") { - c_type = "const AutoschedulerParams&"; - } - stream << get_indent() << comma << c_type << " " << p->name() << "\n"; - comma = ", "; - } - indent_level--; - stream << get_indent() << ") : \n"; - indent_level++; - comma = ""; - for (auto *p : v) { - stream << get_indent() << comma << p->name() << "(" << p->name() << ")\n"; - comma = ", "; - } - indent_level--; - stream << get_indent() << "{\n"; - stream << get_indent() << "}\n"; - stream << "\n"; - } - - indent_level--; - stream << get_indent() << "};\n"; - stream << "\n"; -} - -void StubEmitter::emit_inputs_struct() { - struct InInfo { - std::string c_type; - std::string name; - }; - std::vector in_info; - for (auto *input : inputs) { - std::stringstream c_type; - if (input->is_array()) { - c_type << "std::vector<"; - } - c_type << input->get_c_type(); - if (input->is_array()) { - c_type << ">"; - } - in_info.push_back({c_type.str(), input->name()}); - } - - const std::string name = "Inputs"; - stream << get_indent() << "struct " << name << " final {\n"; - indent_level++; - for (const auto &in : in_info) { - stream << get_indent() << in.c_type << " " << in.name << ";\n"; - } - stream << "\n"; - - stream << get_indent() << name << "() {}\n"; - stream << "\n"; - if (!in_info.empty()) { - stream << get_indent() << name << "(\n"; - indent_level++; - std::string comma = ""; - for (const auto &in : in_info) { - stream << get_indent() << comma << "const " << in.c_type << "& " << in.name << "\n"; - comma = ", "; - } - indent_level--; - stream << get_indent() << ") : \n"; - indent_level++; - comma = ""; - for (const auto &in : in_info) { - stream << get_indent() << comma << in.name << "(" << in.name << ")\n"; - comma = ", "; - } - indent_level--; - stream << get_indent() << "{\n"; - stream << get_indent() << "}\n"; - - indent_level--; - } - stream << get_indent() << "};\n"; - stream << "\n"; -} - -void StubEmitter::emit() { - if (outputs.empty()) { - // The generator can't support a real stub. Instead, generate an (essentially) - // empty .stub.h file, so that build systems like Bazel will still get the output file - // they expected. Note that we deliberately don't emit an ifndef header guard, - // since we can't reliably assume that the generator_name will be globally unique; - // on the other hand, since this file is just a couple of comments, it's - // really not an issue if it's included multiple times. - stream << "/* MACHINE-GENERATED - DO NOT EDIT */\n"; - stream << "/* The Generator named " << generator_registered_name << " uses ImageParam or Param, thus cannot have a Stub generated. */\n"; - return; - } - - struct OutputInfo { - std::string name; - std::string ctype; - std::string getter; - }; - bool all_outputs_are_func = true; - std::vector out_info; - for (auto *output : outputs) { - std::string c_type = output->get_c_type(); - const bool is_func = (c_type == "Func"); - std::stringstream getter; - - if (!is_func) { - getter << c_type << "::to_output_buffers("; - } - getter << "generator->output_func(\"" << output->name() << "\")"; - if (!is_func) { - getter << ", generator)"; - } - if (!output->is_array()) { - getter << ".at(0)"; - } - - out_info.push_back({output->name(), - output->is_array() ? "std::vector<" + c_type + ">" : c_type, - getter.str()}); - if (c_type != "Func") { - all_outputs_are_func = false; - } - } - - std::ostringstream guard; - guard << "HALIDE_STUB"; - for (const auto &ns : namespaces) { - guard << "_" << ns; - } - guard << "_" << class_name; - - stream << get_indent() << "#ifndef " << guard.str() << "\n"; - stream << get_indent() << "#define " << guard.str() << "\n"; - stream << "\n"; - - stream << get_indent() << "/* MACHINE-GENERATED - DO NOT EDIT */\n"; - stream << "\n"; - - stream << get_indent() << "#include \n"; - stream << get_indent() << "#include \n"; - stream << get_indent() << "#include \n"; - stream << get_indent() << "#include \n"; - stream << get_indent() << "#include \n"; - stream << get_indent() << "#include \n"; - stream << get_indent() << "#include \n"; - stream << "\n"; - stream << get_indent() << "#include \"Halide.h\"\n"; - stream << "\n"; - - stream << "namespace halide_register_generator {\n"; - stream << "namespace " << generator_registered_name << "_ns {\n"; - stream << "extern std::unique_ptr factory(const Halide::GeneratorContext& context);\n"; - stream << "} // namespace halide_register_generator\n"; - stream << "} // namespace " << generator_registered_name << "\n"; - stream << "\n"; - - for (const auto &ns : namespaces) { - stream << get_indent() << "namespace " << ns << " {\n"; - } - stream << "\n"; - - for (auto *p : generator_params) { - std::string decl = p->get_type_decls(); - if (decl.empty()) { - continue; - } - stream << decl << "\n"; - } - - stream << get_indent() << "class " << class_name << " final : public Halide::NamesInterface {\n"; - stream << get_indent() << "public:\n"; - indent_level++; - - emit_inputs_struct(); - emit_generator_params_struct(); - - stream << get_indent() << "struct Outputs final {\n"; - indent_level++; - stream << get_indent() << "// Outputs\n"; - for (const auto &out : out_info) { - stream << get_indent() << out.ctype << " " << out.name << ";\n"; - } - - stream << "\n"; - stream << get_indent() << "// The Target used\n"; - stream << get_indent() << "Target target;\n"; - - if (out_info.size() == 1) { - stream << "\n"; - if (all_outputs_are_func) { - std::string name = out_info.at(0).name; - auto *output = outputs[0]; - if (output->is_array()) { - stream << get_indent() << "operator std::vector() const {\n"; - indent_level++; - stream << get_indent() << "return " << name << ";\n"; - indent_level--; - stream << get_indent() << "}\n"; - - stream << get_indent() << "Halide::Func operator[](size_t i) const {\n"; - indent_level++; - stream << get_indent() << "return " << name << "[i];\n"; - indent_level--; - stream << get_indent() << "}\n"; - - stream << get_indent() << "Halide::Func at(size_t i) const {\n"; - indent_level++; - stream << get_indent() << "return " << name << ".at(i);\n"; - indent_level--; - stream << get_indent() << "}\n"; - - stream << get_indent() << "// operator operator()() overloads omitted because the sole Output is array-of-Func.\n"; - } else { - // If there is exactly one output, add overloads - // for operator Func and operator(). - stream << get_indent() << "operator Halide::Func() const {\n"; - indent_level++; - stream << get_indent() << "return " << name << ";\n"; - indent_level--; - stream << get_indent() << "}\n"; - - stream << "\n"; - stream << get_indent() << "template \n"; - stream << get_indent() << "Halide::FuncRef operator()(Args&&... args) const {\n"; - indent_level++; - stream << get_indent() << "return " << name << "(std::forward(args)...);\n"; - indent_level--; - stream << get_indent() << "}\n"; - - stream << "\n"; - stream << get_indent() << "template \n"; - stream << get_indent() << "Halide::FuncRef operator()(std::vector args) const {\n"; - indent_level++; - stream << get_indent() << "return " << name << "()(args);\n"; - indent_level--; - stream << get_indent() << "}\n"; - } - } else { - stream << get_indent() << "// operator Func() and operator()() overloads omitted because the sole Output is not Func.\n"; - } - } - - stream << "\n"; - if (all_outputs_are_func) { - stream << get_indent() << "Halide::Pipeline get_pipeline() const {\n"; - indent_level++; - stream << get_indent() << "return Halide::Pipeline(std::vector{\n"; - indent_level++; - int commas = (int)out_info.size() - 1; - for (const auto &out : out_info) { - stream << get_indent() << out.name << (commas-- ? "," : "") << "\n"; - } - indent_level--; - stream << get_indent() << "});\n"; - indent_level--; - stream << get_indent() << "}\n"; - - stream << "\n"; - stream << get_indent() << "Halide::Realization realize(std::vector sizes) {\n"; - indent_level++; - stream << get_indent() << "return get_pipeline().realize(sizes, target);\n"; - indent_level--; - stream << get_indent() << "}\n"; - - stream << "\n"; - stream << get_indent() << "template ::value>::type * = nullptr>\n"; - stream << get_indent() << "Halide::Realization realize(Args&&... args) {\n"; - indent_level++; - stream << get_indent() << "return get_pipeline().realize(std::forward(args)..., target);\n"; - indent_level--; - stream << get_indent() << "}\n"; - - stream << "\n"; - stream << get_indent() << "void realize(Halide::Realization r) {\n"; - indent_level++; - stream << get_indent() << "get_pipeline().realize(r, target);\n"; - indent_level--; - stream << get_indent() << "}\n"; - } else { - stream << get_indent() << "// get_pipeline() and realize() overloads omitted because some Outputs are not Func.\n"; - } - - indent_level--; - stream << get_indent() << "};\n"; - stream << "\n"; - - stream << get_indent() << "HALIDE_NO_USER_CODE_INLINE static Outputs generate(\n"; - indent_level++; - stream << get_indent() << "const GeneratorContext& context,\n"; - stream << get_indent() << "const Inputs& inputs,\n"; - stream << get_indent() << "const GeneratorParams& generator_params = GeneratorParams()\n"; - indent_level--; - stream << get_indent() << ")\n"; - stream << get_indent() << "{\n"; - indent_level++; - stream << get_indent() << "std::shared_ptr generator = halide_register_generator::" << generator_registered_name << "_ns::factory(context);\n"; - for (auto *p : generator_params) { - stream << get_indent(); - if (p->is_looplevel_param()) { - stream << "generator->set_generatorparam_value("; - } else { - stream << "generator->set_generatorparam_value("; - } - stream << "\"" << p->name() << "\", "; - if (p->is_looplevel_param()) { - stream << "generator_params." << p->name(); - } else { - stream << p->call_to_string("generator_params." + p->name()); - } - stream << ");\n"; - } - - for (auto *p : inputs) { - stream << get_indent() << "generator->bind_input(" - << "\"" << p->name() << "\", "; - if (p->kind() == ArgInfoKind::Buffer) { - stream << "Halide::Internal::StubInputBuffer<>::to_parameter_vector(inputs." << p->name() << ")"; - } else { - // Func or Expr - if (!p->is_array()) { - stream << "{"; - } - stream << "inputs." << p->name(); - if (!p->is_array()) { - stream << "}"; - } - } - stream << ");\n"; - } - - stream << get_indent() << "generator->build_pipeline();\n"; - stream << get_indent() << "return {\n"; - indent_level++; - for (const auto &out : out_info) { - stream << get_indent() << out.getter << ",\n"; - } - stream << get_indent() << "generator->context().target()\n"; - indent_level--; - stream << get_indent() << "};\n"; - indent_level--; - stream << get_indent() << "}\n"; - stream << "\n"; - - stream << get_indent() << "// overload to allow GeneratorBase-pointer\n"; - stream << get_indent() << "inline static Outputs generate(\n"; - indent_level++; - stream << get_indent() << "const Halide::Internal::GeneratorBase* generator,\n"; - stream << get_indent() << "const Inputs& inputs,\n"; - stream << get_indent() << "const GeneratorParams& generator_params = GeneratorParams()\n"; - indent_level--; - stream << get_indent() << ")\n"; - stream << get_indent() << "{\n"; - indent_level++; - stream << get_indent() << "return generate(generator->context(), inputs, generator_params);\n"; - indent_level--; - stream << get_indent() << "}\n"; - stream << "\n"; - - stream << get_indent() << "// overload to allow Target instead of GeneratorContext.\n"; - stream << get_indent() << "inline static Outputs generate(\n"; - indent_level++; - stream << get_indent() << "const Target& target,\n"; - stream << get_indent() << "const Inputs& inputs,\n"; - stream << get_indent() << "const GeneratorParams& generator_params = GeneratorParams()\n"; - indent_level--; - stream << get_indent() << ")\n"; - stream << get_indent() << "{\n"; - indent_level++; - stream << get_indent() << "return generate(Halide::GeneratorContext(target), inputs, generator_params);\n"; - indent_level--; - stream << get_indent() << "}\n"; - stream << "\n"; - - stream << get_indent() << class_name << "() = delete;\n"; - - indent_level--; - stream << get_indent() << "};\n"; - stream << "\n"; - - for (const auto &ns : reverse_view(namespaces)) { - stream << get_indent() << "} // namespace " << ns << "\n"; - } - stream << "\n"; - - stream << get_indent() << "#endif // " << guard.str() << "\n"; -} const std::map &get_halide_type_enum_map() { static const std::map halide_type_enum_map{ @@ -662,7 +194,7 @@ gengen documentation. -e A comma separated list of files to emit. Accepted values are: - [assembly, bitcode, c_header, c_source, cpp_stub, featurization, + [assembly, bitcode, c_header, c_source, featurization, llvm_assembly, object, python_extension, pytorch_wrapper, registration, schedule, static_library, stmt, stmt_html, conceptual_stmt, conceptual_stmt_html, compiler_log, hlpipe, device_code]. @@ -1014,13 +546,7 @@ void execute_generator(const ExecuteGeneratorArgs &args_in) { // -------------- Do some sanity checking. internal_assert(!args.output_dir.empty()); - const bool cpp_stub_only = args.output_types.size() == 1 && - args.output_types.count(OutputFileType::cpp_stub) == 1; - - if (!cpp_stub_only) { - // It's ok to leave targets unspecified if we are generating *only* a cpp_stub - internal_assert(!args.targets.empty()); - } + internal_assert(!args.targets.empty()); const auto ensure_valid_name = [](const std::string &s) { internal_assert(s.empty() || is_valid_name(s)) << "string '" << s << "' is not a valid Generator name."; @@ -1080,15 +606,6 @@ void execute_generator(const ExecuteGeneratorArgs &args_in) { return gen; }; - if (args.output_types.count(OutputFileType::cpp_stub)) { - // When generating cpp_stub we ignore all generator args passed in, and supply a fake Target. - // (CompilerLogger is never enabled for cpp_stub, for now anyway.) - const Target fake_target = Target(); - auto gen = args.create_generator(args.generator_name, GeneratorContext(fake_target)); - auto output_files = compute_output_files(fake_target, base_path, args.output_types); - gen->emit_cpp_stub(output_files[OutputFileType::cpp_stub]); - } - #ifdef WITH_SERIALIZATION if (args.output_types.count(OutputFileType::hlpipe)) { // When serializing a halide pipeline, target is required (since the schedule may be target dependent). @@ -1104,8 +621,7 @@ void execute_generator(const ExecuteGeneratorArgs &args_in) { } #endif - // Don't bother with this if we're just emitting a cpp_stub. - if (!cpp_stub_only) { + { auto output_files = compute_output_files(args.targets[0], base_path, args.output_types); auto module_factory = [&](const std::string &function_name, const Target &target) -> Module { auto gen = generator_factory(function_name, target); @@ -1374,15 +890,14 @@ void GeneratorBase::init_from_context(const Halide::GeneratorContext &context) { param_info_ptr = std::make_unique(this, size); } -void GeneratorBase::set_generator_names(const std::string ®istered_name, const std::string &stub_name) { +void GeneratorBase::set_generator_names(const std::string ®istered_name) { user_assert(is_valid_name(registered_name)) << "Invalid Generator name: " << registered_name; - internal_assert(!registered_name.empty() && !stub_name.empty()); - internal_assert(generator_registered_name.empty() && generator_stub_name.empty()); + internal_assert(!registered_name.empty()); + internal_assert(generator_registered_name.empty()); generator_registered_name = registered_name; - generator_stub_name = stub_name; } -void GeneratorBase::set_inputs_vector(const std::vector> &inputs) { +void GeneratorBase::set_inputs_vector(const std::vector> &inputs) { ensure_configure_has_been_called(); advance_phase(InputsSet); GeneratorParamInfo &pi = param_info(); @@ -1614,7 +1129,7 @@ std::vector GeneratorBase::output_func(const std::string &n) { void GeneratorBase::bind_input(const std::string &name, const std::vector &v) { ensure_configure_has_been_called(); advance_phase(InputsSet); - std::vector si; + std::vector si; std::copy(v.begin(), v.end(), std::back_inserter(si)); find_input_by_name(name)->set_inputs(si); } @@ -1622,7 +1137,7 @@ void GeneratorBase::bind_input(const std::string &name, const std::vector &v) { ensure_configure_has_been_called(); advance_phase(InputsSet); - std::vector si; + std::vector si; std::copy(v.begin(), v.end(), std::back_inserter(si)); find_input_by_name(name)->set_inputs(si); } @@ -1630,28 +1145,14 @@ void GeneratorBase::bind_input(const std::string &name, const std::vector void GeneratorBase::bind_input(const std::string &name, const std::vector &v) { ensure_configure_has_been_called(); advance_phase(InputsSet); - std::vector si; + std::vector si; std::copy(v.begin(), v.end(), std::back_inserter(si)); find_input_by_name(name)->set_inputs(si); } -bool GeneratorBase::emit_cpp_stub(const std::string &stub_file_path) { - user_assert(!generator_registered_name.empty() && !generator_stub_name.empty()) << "Generator has no name.\n"; - // Make sure we call configure() so that extra inputs/outputs are added as necessary. - ensure_configure_has_been_called(); - // StubEmitter will want to access the GP/SP values, so advance the phase to avoid assert-fails. - advance_phase(GenerateCalled); - advance_phase(ScheduleCalled); - GeneratorParamInfo &pi = param_info(); - std::ofstream file(stub_file_path); - StubEmitter emit(file, generator_registered_name, generator_stub_name, pi.generator_params(), pi.inputs(), pi.outputs()); - emit.emit(); - return true; -} - bool GeneratorBase::emit_hlpipe(const std::string &hlpipe_file_path) { #ifdef WITH_SERIALIZATION - user_assert(!generator_registered_name.empty() && !generator_stub_name.empty()) << "Generator has no name.\n"; + user_assert(!generator_registered_name.empty()) << "Generator has no name.\n"; Pipeline pipeline = build_pipeline(); AutoSchedulerResults auto_schedule_results; const auto context = this->context(); @@ -1934,14 +1435,14 @@ void GeneratorInputBase::init_internals() { verify_internals(); } -void GeneratorInputBase::set_inputs(const std::vector &inputs) { +void GeneratorInputBase::set_inputs(const std::vector &inputs) { generator->check_exact_phase(GeneratorBase::InputsSet); parameters_.clear(); exprs_.clear(); funcs_.clear(); check_matching_array_size(inputs.size()); for (size_t i = 0; i < inputs.size(); ++i) { - const StubInput &in = inputs.at(i); + const BoundInput &in = inputs.at(i); user_assert(in.kind() == kind()) << "An input for " << name() << " is not of the expected kind.\n"; if (kind() == ArgInfoKind::Function) { auto f = in.func(); @@ -2050,20 +1551,6 @@ void GeneratorOutputBase::resize(size_t size) { init_internals(); } -StubOutputBufferBase::StubOutputBufferBase() = default; - -StubOutputBufferBase::StubOutputBufferBase(const Func &f, const std::shared_ptr &generator) - : f(f), generator(generator) { -} - -Realization StubOutputBufferBase::realize(std::vector sizes) { - return f.realize(std::move(sizes), get_target()); -} - -Target StubOutputBufferBase::get_target() const { - return generator->context().target(); -} - RegisterGenerator::RegisterGenerator(const char *registered_name, GeneratorFactory generator_factory) { Internal::GeneratorRegistry::register_factory(registered_name, std::move(generator_factory)); } @@ -2102,10 +1589,10 @@ void generator_test() { // Verify that calling GeneratorParam::set() works. tester.gp0.set(1); - tester.set_inputs_vector({{StubInput(42)}}); + tester.set_inputs_vector({{BoundInput(42)}}); internal_assert(tester.phase == GeneratorBase::InputsSet); - // tester.set_inputs_vector({{StubInput(43)}}); // This will assert-fail. + // tester.set_inputs_vector({{BoundInput(43)}}); // This will assert-fail. // Also ok to call in this phase. tester.gp1.set(2.f); @@ -2113,13 +1600,13 @@ void generator_test() { tester.call_generate(); internal_assert(tester.phase == GeneratorBase::GenerateCalled); - // tester.set_inputs_vector({{StubInput(44)}}); // This will assert-fail. + // tester.set_inputs_vector({{BoundInput(44)}}); // This will assert-fail. // tester.gp2.set(2); // This will assert-fail. tester.call_schedule(); internal_assert(tester.phase == GeneratorBase::ScheduleCalled); - // tester.set_inputs_vector({{StubInput(45)}}); // This will assert-fail. + // tester.set_inputs_vector({{BoundInput(45)}}); // This will assert-fail. // tester.gp2.set(2); // This will assert-fail. // tester.sp2.set(202); // This will assert-fail. } diff --git a/src/Generator.h b/src/Generator.h index 591d7bd86cbc..8ea43af8ca52 100644 --- a/src/Generator.h +++ b/src/Generator.h @@ -240,14 +240,6 @@ * The registered name of the Generator is provided must match the same rules as * Input names, above. * - * Note that the class name of the generated Stub class will match the registered - * name by default; if you want to vary it (typically, to include namespaces), - * you can add it as an optional third argument: - * - * \code - * HALIDE_REGISTER_GENERATOR(ExampleGen, jit_example, SomeNamespace::JitExampleStub) - * \endcode - * * Note that a Generator is always executed with a specific Target assigned to it, * that you can access via the get_target() method. (You should *not* use the * global get_target_from_environment(), etc. methods provided in Target.h) @@ -444,7 +436,6 @@ class GeneratorParamBase { protected: friend class GeneratorBase; friend class GeneratorParamInfo; - friend class StubEmitter; void check_value_readable() const; void check_value_writable() const; @@ -1252,135 +1243,11 @@ namespace Internal { template class GeneratorInput_Buffer; -/** - * StubInputBuffer is the placeholder that a Stub uses when it requires - * a Buffer for an input (rather than merely a Func or Expr). It is constructed - * to allow only two possible sorts of input: - * -- Assignment of an Input>, with compatible type and dimensions, - * essentially allowing us to pipe a parameter from an enclosing Generator to an internal Stub. - * -- Assignment of a Buffer<>, with compatible type and dimensions, - * causing the Input> to become a precompiled buffer in the generated code. - */ -template::AnyDims> -class StubInputBuffer { - friend class StubInput; - template - friend class GeneratorInput_Buffer; - template - friend class StubInputBuffer; - - Parameter parameter_; - - HALIDE_NO_USER_CODE_INLINE explicit StubInputBuffer(const Parameter &p) - : parameter_(p) { - // Create an empty 1-element buffer with the right runtime typing and dimensions, - // which we'll use only to pass to can_convert_from() to verify this - // Parameter is compatible with our constraints. - Buffer<> other(p.type(), nullptr, std::vector(p.dimensions(), 1)); - internal_assert((Buffer::can_convert_from(other))); - } - - template - HALIDE_NO_USER_CODE_INLINE static Parameter parameter_from_buffer(const Buffer &b) { - internal_assert(b.defined()); - user_assert((Buffer::can_convert_from(b))); - Parameter p(b.type(), true, b.dimensions()); - p.set_buffer(b); - return p; - } - -public: - StubInputBuffer() = default; - - // *not* explicit -- this ctor should only be used when you want - // to pass a literal Buffer<> for a Stub Input; this Buffer<> will be - // compiled into the Generator's product, rather than becoming - // a runtime Parameter. - template - StubInputBuffer(const Buffer &b) - : parameter_(parameter_from_buffer(b)) { - } - - template - static std::vector to_parameter_vector(const StubInputBuffer &t) { - return {t.parameter_}; - } - - template - static std::vector to_parameter_vector(const std::vector> &v) { - std::vector r; - r.reserve(v.size()); - for (const auto &s : v) { - r.push_back(s.parameter_); - } - return r; - } -}; - -class AbstractGenerator; - -class StubOutputBufferBase { -protected: - Func f; - std::shared_ptr generator; - - Target get_target() const; - - StubOutputBufferBase(); - explicit StubOutputBufferBase(const Func &f, const std::shared_ptr &generator); - -public: - Realization realize(std::vector sizes); - - template - Realization realize(Args &&...args) { - return f.realize(std::forward(args)..., get_target()); - } - - template - void realize(Dst dst) { - f.realize(dst, get_target()); - } -}; - -/** - * StubOutputBuffer is the placeholder that a Stub uses when it requires - * a Buffer for an output (rather than merely a Func). It is constructed - * to allow only two possible sorts of things: - * -- Assignment to an Output>, with compatible type and dimensions, - * essentially allowing us to pipe a parameter from the result of a Stub to an - * enclosing Generator - * -- Realization into a Buffer<>; this is useful only in JIT compilation modes - * (and shouldn't be usable otherwise) - * - * It is deliberate that StubOutputBuffer is not (easily) convertible to Func. - */ -template -class StubOutputBuffer : public StubOutputBufferBase { - template - friend class GeneratorOutput_Buffer; - explicit StubOutputBuffer(const Func &fn, const std::shared_ptr &gen) - : StubOutputBufferBase(fn, gen) { - } - -public: - StubOutputBuffer() = default; - - static std::vector> to_output_buffers(const std::vector &v, - const std::shared_ptr &gen) { - std::vector> result; - for (const Func &f : v) { - result.push_back(StubOutputBuffer(f, gen)); - } - return result; - } -}; - -// This is a union-like class that allows for convenient initialization of Stub Inputs -// via initializer-list syntax; it is only used in situations where the -// downstream consumer will be able to explicitly check that each value is -// of the expected/required kind. -class StubInput { +// This is a union-like class that allows for convenient initialization of +// bound inputs via initializer-list syntax; it is only used in situations +// where the downstream consumer will be able to explicitly check that each +// value is of the expected/required kind. +class BoundInput { const ArgInfoKind kind_; // Exactly one of the following fields should be defined: const Parameter parameter_; @@ -1389,17 +1256,13 @@ class StubInput { public: // *not* explicit. - template - StubInput(const StubInputBuffer &b) - : kind_(ArgInfoKind::Buffer), parameter_(b.parameter_), func_(), expr_() { - } - StubInput(const Parameter &p) + BoundInput(const Parameter &p) : kind_(ArgInfoKind::Buffer), parameter_(p), func_(), expr_() { } - StubInput(const Func &f) + BoundInput(const Func &f) : kind_(ArgInfoKind::Function), parameter_(), func_(f), expr_() { } - StubInput(const Expr &e) + BoundInput(const Expr &e) : kind_(ArgInfoKind::Scalar), parameter_(), func_(), expr_(e) { } @@ -1554,14 +1417,13 @@ class GeneratorInputBase : public GIOBase { Parameter parameter() const; void init_internals(); - void set_inputs(const std::vector &inputs); + void set_inputs(const std::vector &inputs); bool inputs_set = false; virtual void set_def_min_max(); void verify_internals() override; - friend class StubEmitter; virtual std::string get_c_type() const = 0; @@ -1674,11 +1536,11 @@ class GeneratorInput_Buffer : public GeneratorInputImpl { std::string get_c_type() const override { if (TBase::has_static_halide_type) { - return "Halide::Internal::StubInputBuffer<" + + return "Halide::Buffer<" + halide_type_to_c_type(TBase::static_halide_type()) + ">"; } else { - return "Halide::Internal::StubInputBuffer<>"; + return "Halide::Buffer<>"; } } @@ -1723,12 +1585,6 @@ class GeneratorInput_Buffer : public GeneratorInputImpl { return Func(*this)(std::move(args)); } - template - operator StubInputBuffer() const { - user_assert(!this->is_array()) << "Cannot assign an array type to a non-array type for Input " << this->name(); - return StubInputBuffer(this->parameters_.at(0)); - } - operator Func() const { this->check_gio_access(); return this->funcs().at(0); @@ -2360,7 +2216,6 @@ class GeneratorOutputBase : public GIOBase { int d); friend class GeneratorBase; - friend class StubEmitter; void init_internals(); void resize(size_t size); @@ -2580,11 +2435,11 @@ class GeneratorOutput_Buffer : public GeneratorOutputImpl { HALIDE_NO_USER_CODE_INLINE std::string get_c_type() const override { if (TBase::has_static_halide_type) { - return "Halide::Internal::StubOutputBuffer<" + + return "Halide::Buffer<" + halide_type_to_c_type(TBase::static_halide_type()) + ">"; } else { - return "Halide::Internal::StubOutputBuffer<>"; + return "Halide::Buffer<>"; } } @@ -2625,16 +2480,6 @@ class GeneratorOutput_Buffer : public GeneratorOutputImpl { return *this; } - // Allow assignment from a StubOutputBuffer to an Output; - // this allows us to pipeline the results of a Stub to the results - // of the enclosing Generator. - template - GeneratorOutput_Buffer &operator=(const StubOutputBuffer &stub_output_buffer) { - this->check_gio_access(); - assign_from_func(stub_output_buffer.f); - return *this; - } - // Allow assignment from a Func to an Output; // this allows us to use helper functions that return a plain Func // to simply set the output(s) without needing a wrapper Func. @@ -2870,12 +2715,6 @@ class GeneratorOutput : public Internal::GeneratorOutputImplBase { return *this; } - template - GeneratorOutput &operator=(const Internal::StubOutputBuffer &stub_output_buffer) { - Super::operator=(stub_output_buffer); - return *this; - } - GeneratorOutput &operator=(const Func &f) { Super::operator=(f); return *this; @@ -3420,7 +3259,7 @@ class GeneratorBase : public NamesInterface, public AbstractGenerator { protected: GeneratorBase(size_t size); - void set_generator_names(const std::string ®istered_name, const std::string &stub_name); + void set_generator_names(const std::string ®istered_name); // Note that it is explicitly legal to override init_from_context(), so that you can (say) // create a modified context with a different Target (eg with features enabled or disabled), but... @@ -3545,15 +3384,13 @@ class GeneratorBase : public NamesInterface, public AbstractGenerator { friend class GeneratorInputBase; friend class GeneratorOutputBase; friend class GeneratorParamInfo; - friend class StubOutputBufferBase; - const size_t size; // Lazily-allocated-and-inited struct with info about our various Params. // Do not access directly: use the param_info() getter. std::unique_ptr param_info_ptr; - std::string generator_registered_name, generator_stub_name; + std::string generator_registered_name; Pipeline pipeline; struct Requirement { @@ -3589,7 +3426,7 @@ class GeneratorBase : public NamesInterface, public AbstractGenerator { void get_jit_target_from_environment(); void get_target_from_environment(); - void set_inputs_vector(const std::vector> &inputs); + void set_inputs_vector(const std::vector> &inputs); static void check_input_is_singular(Internal::GeneratorInputBase *in); static void check_input_is_array(Internal::GeneratorInputBase *in); @@ -3600,20 +3437,19 @@ class GeneratorBase : public NamesInterface, public AbstractGenerator { // causing the Input> to become a precompiled buffer in the generated code. // -- we are assigningit to an Input, in which case we just Func-wrap the Buffer<>. template - std::vector build_input(size_t i, const Buffer &arg) { + std::vector build_input(size_t i, const Buffer &arg) { auto *in = param_info().inputs().at(i); check_input_is_singular(in); const auto k = in->kind(); if (k == Internal::ArgInfoKind::Buffer) { Halide::Buffer<> b = arg; - StubInputBuffer<> sib(b); - StubInput si(sib); - return {si}; + Parameter p(b.type(), true, b.dimensions()); + p.set_buffer(b); + return {BoundInput(p)}; } else if (k == Internal::ArgInfoKind::Function) { Halide::Func f(arg.name() + "_im"); f(Halide::_) = arg(Halide::_); - StubInput si(f); - return {si}; + return {BoundInput(f)}; } else { check_input_kind(in, Internal::ArgInfoKind::Buffer); // just to trigger assertion return {}; @@ -3623,19 +3459,17 @@ class GeneratorBase : public NamesInterface, public AbstractGenerator { // Allow Input> if: // -- we are assigning it to another Input> (with compatible type and dimensions), // allowing us to simply pipe a parameter from an enclosing Generator to the Invoker. - // -- we are assigningit to an Input, in which case we just Func-wrap the Input>. + // -- we are assigning it to an Input, in which case we just Func-wrap the Input>. template - std::vector build_input(size_t i, const GeneratorInput> &arg) { + std::vector build_input(size_t i, const GeneratorInput> &arg) { auto *in = param_info().inputs().at(i); check_input_is_singular(in); const auto k = in->kind(); if (k == Internal::ArgInfoKind::Buffer) { - StubInputBuffer<> sib = arg; - StubInput si(sib); - return {si}; + return {BoundInput(arg.parameters_.at(0))}; } else if (k == Internal::ArgInfoKind::Function) { Halide::Func f = arg.funcs().at(0); - StubInput si(f); + BoundInput si(f); return {si}; } else { check_input_kind(in, Internal::ArgInfoKind::Buffer); // just to trigger assertion @@ -3644,22 +3478,22 @@ class GeneratorBase : public NamesInterface, public AbstractGenerator { } // Allow Func iff we are assigning it to an Input (with compatible type and dimensions). - std::vector build_input(size_t i, const Func &arg) { + std::vector build_input(size_t i, const Func &arg) { auto *in = param_info().inputs().at(i); check_input_kind(in, Internal::ArgInfoKind::Function); check_input_is_singular(in); const Halide::Func &f = arg; - StubInput si(f); + BoundInput si(f); return {si}; } // Allow vector iff we are assigning it to an Input (with compatible type and dimensions). - std::vector build_input(size_t i, const std::vector &arg) { + std::vector build_input(size_t i, const std::vector &arg) { auto *in = param_info().inputs().at(i); check_input_kind(in, Internal::ArgInfoKind::Function); check_input_is_array(in); // My kingdom for a list comprehension... - std::vector siv; + std::vector siv; siv.reserve(arg.size()); for (const auto &f : arg) { siv.emplace_back(f); @@ -3668,20 +3502,20 @@ class GeneratorBase : public NamesInterface, public AbstractGenerator { } // Expr must be Input. - std::vector build_input(size_t i, const Expr &arg) { + std::vector build_input(size_t i, const Expr &arg) { auto *in = param_info().inputs().at(i); check_input_kind(in, Internal::ArgInfoKind::Scalar); check_input_is_singular(in); - StubInput si(arg); + BoundInput si(arg); return {si}; } // (Array form) - std::vector build_input(size_t i, const std::vector &arg) { + std::vector build_input(size_t i, const std::vector &arg) { auto *in = param_info().inputs().at(i); check_input_kind(in, Internal::ArgInfoKind::Scalar); check_input_is_array(in); - std::vector siv; + std::vector siv; siv.reserve(arg.size()); for (const auto &value : arg) { siv.emplace_back(value); @@ -3693,23 +3527,23 @@ class GeneratorBase : public NamesInterface, public AbstractGenerator { // Use is_arithmetic since some Expr conversions are explicit. template> * = nullptr> - std::vector build_input(size_t i, const T &arg) { + std::vector build_input(size_t i, const T &arg) { auto *in = param_info().inputs().at(i); check_input_kind(in, Internal::ArgInfoKind::Scalar); check_input_is_singular(in); // We must use an explicit Expr() ctor to preserve the type Expr e(arg); - StubInput si(e); + BoundInput si(e); return {si}; } // (Array form) template> * = nullptr> - std::vector build_input(size_t i, const std::vector &arg) { + std::vector build_input(size_t i, const std::vector &arg) { auto *in = param_info().inputs().at(i); check_input_kind(in, Internal::ArgInfoKind::Scalar); check_input_is_array(in); - std::vector siv; + std::vector siv; siv.reserve(arg.size()); for (const auto &value : arg) { // We must use an explicit Expr() ctor to preserve the type; @@ -3721,7 +3555,7 @@ class GeneratorBase : public NamesInterface, public AbstractGenerator { } template - std::vector> build_inputs(const std::tuple &t, std::index_sequence) { + std::vector> build_inputs(const std::tuple &t, std::index_sequence) { return {build_input(Indices, std::get(t))...}; } @@ -3758,7 +3592,6 @@ class GeneratorBase : public NamesInterface, public AbstractGenerator { void bind_input(const std::string &name, const std::vector &v) override; void bind_input(const std::string &name, const std::vector &v) override; - bool emit_cpp_stub(const std::string &stub_file_path) override; bool emit_hlpipe(const std::string &hlpipe_file_path) override; GeneratorBase(const GeneratorBase &) = delete; @@ -3814,10 +3647,9 @@ class Generator : public Internal::GeneratorBase { // This is public but intended only for use by the HALIDE_REGISTER_GENERATOR() macro. static std::unique_ptr create(const Halide::GeneratorContext &context, - const std::string ®istered_name, - const std::string &stub_name) { + const std::string ®istered_name) { auto g = create(context); - g->set_generator_names(registered_name, stub_name); + g->set_generator_names(registered_name); return g; } @@ -4055,14 +3887,14 @@ namespace halide_register_generator { struct halide_global_ns; }; -#define _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \ +#define HALIDE_REGISTER_GENERATOR(GEN_CLASS_NAME, GEN_REGISTRY_NAME) \ namespace halide_register_generator { \ struct halide_global_ns; \ namespace GEN_REGISTRY_NAME##_ns { \ std::unique_ptr factory(const Halide::GeneratorContext &context); \ std::unique_ptr factory(const Halide::GeneratorContext &context) { \ using GenType = std::remove_pointer_t; /* NOLINT(bugprone-macro-parentheses) */ \ - return GenType::create(context, #GEN_REGISTRY_NAME, #FULLY_QUALIFIED_STUB_NAME); \ + return GenType::create(context, #GEN_REGISTRY_NAME); \ } \ } \ namespace { \ @@ -4072,39 +3904,6 @@ struct halide_global_ns; static_assert(std::is_same_v<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>, \ "HALIDE_REGISTER_GENERATOR must be used at global scope"); -#define _HALIDE_REGISTER_GENERATOR2(GEN_CLASS_NAME, GEN_REGISTRY_NAME) \ - _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, GEN_REGISTRY_NAME) - -#define _HALIDE_REGISTER_GENERATOR3(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \ - _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) - -// MSVC has a broken implementation of variadic macros: it expands __VA_ARGS__ -// as a single token in argument lists (rather than multiple tokens). -// Jump through some hoops to work around this. -#define __HALIDE_REGISTER_ARGCOUNT_IMPL(_1, _2, _3, COUNT, ...) \ - COUNT - -#define _HALIDE_REGISTER_ARGCOUNT_IMPL(ARGS) \ - __HALIDE_REGISTER_ARGCOUNT_IMPL ARGS - -#define _HALIDE_REGISTER_ARGCOUNT(...) \ - _HALIDE_REGISTER_ARGCOUNT_IMPL((__VA_ARGS__, 3, 2, 1, 0)) - -#define ___HALIDE_REGISTER_CHOOSER(COUNT) \ - _HALIDE_REGISTER_GENERATOR##COUNT - -#define __HALIDE_REGISTER_CHOOSER(COUNT) \ - ___HALIDE_REGISTER_CHOOSER(COUNT) - -#define _HALIDE_REGISTER_CHOOSER(COUNT) \ - __HALIDE_REGISTER_CHOOSER(COUNT) - -#define _HALIDE_REGISTER_GENERATOR_PASTE(A, B) \ - A B - -#define HALIDE_REGISTER_GENERATOR(...) \ - _HALIDE_REGISTER_GENERATOR_PASTE(_HALIDE_REGISTER_CHOOSER(_HALIDE_REGISTER_ARGCOUNT(__VA_ARGS__)), (__VA_ARGS__)) - // HALIDE_REGISTER_GENERATOR_ALIAS() can be used to create an an alias-with-a-particular-set-of-param-values // for a given Generator in the build system. Normally, you wouldn't want to do this; // however, some existing Halide clients have build systems that make it challenging to diff --git a/src/Module.cpp b/src/Module.cpp index 372669ec6e57..38d601086331 100644 --- a/src/Module.cpp +++ b/src/Module.cpp @@ -38,7 +38,6 @@ std::map get_output_info(const Target &target) {OutputFileType::c_header, {"c_header", ".h", IsSingle}}, {OutputFileType::c_source, {"c_source", ".halide_generated.cpp", IsSingle}}, {OutputFileType::compiler_log, {"compiler_log", ".halide_compiler_log", IsSingle}}, - {OutputFileType::cpp_stub, {"cpp_stub", ".stub.h", IsSingle}}, {OutputFileType::featurization, {"featurization", ".featurization", IsMulti}}, {OutputFileType::function_info_header, {"function_info_header", ".function_info.h", IsSingle}}, {OutputFileType::hlpipe, {"hlpipe", ".hlpipe", IsSingle}}, diff --git a/src/Module.h b/src/Module.h index efb984529458..1d6cb8d9637a 100644 --- a/src/Module.h +++ b/src/Module.h @@ -29,7 +29,6 @@ enum class OutputFileType { c_header, c_source, compiler_log, - cpp_stub, featurization, function_info_header, hlpipe, diff --git a/test/correctness/compile_to_multitarget.cpp b/test/correctness/compile_to_multitarget.cpp index e27ef22e99d0..a00425142357 100644 --- a/test/correctness/compile_to_multitarget.cpp +++ b/test/correctness/compile_to_multitarget.cpp @@ -187,9 +187,6 @@ void test_compile_to_everything(Func j, bool do_object) { {OutputFileType::c_header, filename_prefix + ".h"}, // IsSingle {OutputFileType::c_source, filename_prefix + ".halide_generated.cpp"}, // IsSingle {OutputFileType::compiler_log, filename_prefix + ".halide_compiler_log"}, // IsSingle - // Note: compile_multitarget() doesn't produce cpp_stub output, - // even if you pass this in. - // {OutputFileType::cpp_stub, filename_prefix + ".stub.h"}, // IsSingle {OutputFileType::featurization, filename_prefix + ".featurization"}, // IsMulti {OutputFileType::function_info_header, filename_prefix + ".function_info.h"}, // IsSingle // Note: compile_multitarget() doesn't produce hlpipe output, diff --git a/test/generator/CMakeLists.txt b/test/generator/CMakeLists.txt index 35731923f148..c66f14955908 100644 --- a/test/generator/CMakeLists.txt +++ b/test/generator/CMakeLists.txt @@ -701,15 +701,6 @@ _add_halide_aot_tests(rdom_input) _add_halide_libraries(string_param PARAMS "rpn_expr=5 y * x +") _add_halide_aot_tests(string_param) -# stubtest_aottest.cpp -# stubtest_generator.cpp -# stubtest_jittest.cpp -# TODO: stubs not supported in CMake - -# stubuser_aottest.cpp -# stubuser_generator.cpp -# TODO: stubs not supported in CMake - # shuffler_aottest.cpp # shuffler_generator.cpp _add_halide_libraries(shuffler) diff --git a/test/generator/abstractgeneratortest_generator.cpp b/test/generator/abstractgeneratortest_generator.cpp index 563a2348f8d9..f0c5cb483155 100644 --- a/test/generator/abstractgeneratortest_generator.cpp +++ b/test/generator/abstractgeneratortest_generator.cpp @@ -131,11 +131,6 @@ class AbstractGeneratorTest : public AbstractGenerator { _halide_user_assert(false) << "OOPS"; } - bool emit_cpp_stub(const std::string & /*stub_file_path*/) override { - // not supported - return false; - } - bool emit_hlpipe(const std::string & /*hlpipe_file_path*/) override { // not supported return false; diff --git a/test/generator/configure_jittest.cpp b/test/generator/configure_jittest.cpp index 1049f5769217..7f18382eb08a 100644 --- a/test/generator/configure_jittest.cpp +++ b/test/generator/configure_jittest.cpp @@ -1,8 +1,5 @@ #include "Halide.h" -// Include the machine-generated .stub.h header file. -#include "configure.stub.h" - using namespace Halide; const int kSize = 32; @@ -43,41 +40,7 @@ int main(int argc, char **argv) { extra_value += extra_scalar + extra_dynamic_scalar + extra_func_value + typed_extra_value + bias; - // Use a Generator Stub to create the Halide IR, - // then call realize() to JIT and execute it. - { - // When calling a Stub, Func inputs must be actual Halide::Func. - Var x, y, c; - Func func_extra; - func_extra(x, y, c) = cast(extra_func_value); - - auto result = configure::generate(context, configure::Inputs{ - input, - bias, - extras[0], extras[1], extras[2], - typed_extra, - func_extra, - extra_scalar, - cast(extra_dynamic_scalar)}); - - Buffer output = result.output.realize({kSize, kSize, 3}); - Buffer extra_buffer_output = result.extra_buffer_output.realize({kSize, kSize, 3}); - Buffer extra_func_output = result.extra_func_output.realize({kSize, kSize}); - - output.for_each_element([&](int x, int y, int c) { - assert(output(x, y, c) == input(x, y, c) + extra_value); - }); - - extra_buffer_output.for_each_element([&](int x, int y, int c) { - assert(extra_buffer_output(x, y, c) == output(x, y, c)); - }); - - extra_func_output.for_each_element([&](int x, int y) { - assert(extra_func_output(x, y) == output(x, y, 0)); - }); - } - - // Alternately, instead of using Generator Stubs, we can just use the Callable interface. + // Use the Callable interface to invoke a Generator. // We can call this on any Generator that is registered in the current process. { Callable configure = create_callable_from_generator(context, "configure"); diff --git a/test/generator/example_jittest.cpp b/test/generator/example_jittest.cpp index 7596c4c27b68..96d8abb00364 100644 --- a/test/generator/example_jittest.cpp +++ b/test/generator/example_jittest.cpp @@ -1,8 +1,5 @@ #include "Halide.h" -// Include the machine-generated .stub.h header file. -#include "example.stub.h" - using namespace Halide; const int kSize = 32; @@ -19,54 +16,8 @@ int main(int argc, char **argv) { GeneratorContext context(get_jit_target_from_environment()); const float runtime_factor = 4.5f; - // Demonstrate (and test) various ways to use a Stub to invoke a Generator with the JIT. - { - // The simplest way is to just use the Stub's static "generate" method. - // - // The Generator's Input<>s are specified via a struct that is initialized - // via an {initializer-list}, in the order the Input<>s are declared in the Generator. - Func f = example::generate(context, {runtime_factor}); - Buffer img = f.realize({kSize, kSize, 3}); - verify(img, 1.f, runtime_factor, 3); - } - - { - // Of course, we can fill in the Inputs struct by name if we prefer. - example::Inputs inputs; - inputs.runtime_factor = runtime_factor; - - Func f = example::generate(context, inputs); - Buffer img = f.realize({kSize, kSize, 3}); - verify(img, 1.f, runtime_factor, 3); - } - - { - // We can also (optionally) specify non-default values for the Generator's GeneratorParam<> fields. - // Note that we could use an {initializer-list} for this struct, but usually do not: - // the example::GeneratorParams struct is initialized to the correct default values, - // so we usually prefer to set just the fields we want to change. - example::GeneratorParams gp; - gp.compiletime_factor = 2.5f; - - Func f = example::generate(context, {runtime_factor}, gp); - Buffer img = f.realize({kSize, kSize, 3}); - verify(img, gp.compiletime_factor, runtime_factor, 3); - } - - { - // generate() actually returns an Outputs struct, which contains all of the Generator's - // Output<> fields. If there is just a single Output<>, - // you can assign a Func to it directly (as we did in previous examples). - // - // In this case, we'll save it to a temporary to make the typing explicit. - example::Outputs result = example::generate(context, {runtime_factor}); - - Buffer img = result.realize({kSize, kSize, 3}); - verify(img, 1.f, runtime_factor, 3); - } - { - // Alternately, instead of using Generator Stubs, we can just use the Callable interface. + // Use the Callable interface to invoke a Generator. // We can call this on any Generator that is registered in the current process. Callable example = create_callable_from_generator(context, "example"); diff --git a/test/generator/stubtest_aottest.cpp b/test/generator/stubtest_aottest.cpp deleted file mode 100644 index 7687c2bdaf1f..000000000000 --- a/test/generator/stubtest_aottest.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include - -#include "HalideBuffer.h" -#include "HalideRuntime.h" -#include "stubtest.h" - -using Halide::Runtime::Buffer; - -const int kSize = 32; - -template -Buffer make_image(int extra) { - Buffer im(kSize, kSize, 3); - for (int x = 0; x < kSize; x++) { - for (int y = 0; y < kSize; y++) { - for (int c = 0; c < 3; c++) { - im(x, y, c) = static_cast(x + y + c + extra); - } - } - } - return im; -} - -template -void verify(const Buffer &input, float float_arg, int int_arg, const Buffer &output) { - if (input.width() != output.width() || - input.height() != output.height()) { - fprintf(stderr, "size mismatch: %dx%d vs %dx%d\n", input.width(), input.height(), output.width(), output.height()); - exit(1); - } - int channels = std::max(1, std::min(input.channels(), output.channels())); - for (int x = 0; x < output.width(); x++) { - for (int y = 0; y < output.height(); y++) { - for (int c = 0; c < channels; c++) { - const OutputType expected = static_cast(input(x, y, c) * float_arg + int_arg); - const OutputType actual = output(x, y, c); - if (expected != actual) { - fprintf(stderr, "img[%d, %d, %d] = %f, expected %f (input = %f)\n", x, y, c, (double)actual, (double)expected, (double)input(x, y, c)); - exit(1); - } - } - } - } -} - -int main(int argc, char **argv) { - Buffer buffer_input = make_image(0); - Buffer simple_input = make_image(0); - Buffer array_input0 = make_image(0); - Buffer array_input1 = make_image(1); - Buffer typed_buffer_output(kSize, kSize, 3); - Buffer untyped_buffer_output(kSize, kSize, 3); - Buffer tupled_output0(kSize, kSize, 3); - Buffer tupled_output1(kSize, kSize, 3); - Buffer array_buffer_input0 = make_image(0); - Buffer array_buffer_input1 = make_image(1); - Buffer simple_output(kSize, kSize, 3); - // TODO: see Issues #3709, #3967 - Buffer float16_output(halide_type_t(halide_type_float, 16), kSize, kSize, 3); - Buffer bfloat16_output(halide_type_t(halide_type_bfloat, 16), kSize, kSize, 3); - Buffer tuple_output0(kSize, kSize, 3), tuple_output1(kSize, kSize, 3); - Buffer array_output0(kSize, kSize, 3), array_output1(kSize, kSize, 3); - Buffer static_compiled_buffer_output(kSize, kSize, 3); - Buffer array_buffer_output0(kSize, kSize, 3), array_buffer_output1(kSize, kSize, 3); - - stubtest( - buffer_input, - buffer_input, - array_buffer_input0, array_buffer_input1, - simple_input, - array_input0, array_input1, - 1.25f, - 33, - 66, - simple_output, - tuple_output0, tuple_output1, - array_output0, array_output1, - typed_buffer_output, - untyped_buffer_output, - tupled_output0, tupled_output1, - static_compiled_buffer_output, - array_buffer_output0, array_buffer_output1, - float16_output, - bfloat16_output); - - verify(buffer_input, 1.f, 0, typed_buffer_output); - verify(buffer_input, 1.f, 0, untyped_buffer_output); - verify(simple_input, 1.f, 0, simple_output); - verify(simple_input, 1.f, 0, tupled_output0); - verify(simple_input, 1.f, 1, tupled_output1); - verify(array_input0, 1.f, 0, simple_output); - verify(array_input0, 1.25f, 0, tuple_output0); - verify(array_input0, 1.25f, 33, tuple_output1); - verify(array_input0, 1.0f, 33, array_output0); - verify(array_input1, 1.0f, 66, array_output1); - verify(buffer_input, 1.0f, 42, static_compiled_buffer_output); - verify(array_buffer_input0, 1.f, 1, array_buffer_output0); - verify(array_buffer_input1, 1.f, 2, array_buffer_output1); - - printf("Success!\n"); - return 0; -} diff --git a/test/generator/stubtest_generator.cpp b/test/generator/stubtest_generator.cpp deleted file mode 100644 index de0a03f1c797..000000000000 --- a/test/generator/stubtest_generator.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "Halide.h" - -namespace { - -enum class BagType { Paper, - Plastic }; - -template -Halide::Buffer make_image(int extra) { - Halide::Buffer im(size, size, dim); - for (int x = 0; x < size; x++) { - for (int y = 0; y < size; y++) { - for (int c = 0; c < dim; c++) { - im(x, y, c) = static_cast(x + y + c + extra); - } - } - } - return im; -} - -class StubTest : public Halide::Generator { -public: - GeneratorParam untyped_buffer_output_type{"untyped_buffer_output_type", Float(32)}; - GeneratorParam float_param{"float_param", 3.1415926535f}; - GeneratorParam str_param{"str_param", ""}; - GeneratorParam bag_type{"bag_type", - BagType::Paper, - {{"paper", BagType::Paper}, - {"plastic", BagType::Plastic}}}; - GeneratorParam vectorize{"vectorize", true}; - GeneratorParam intermediate_level{"intermediate_level", LoopLevel::root()}; - - Input> typed_buffer_input{"typed_buffer_input"}; - Input> untyped_buffer_input{"untyped_buffer_input"}; - Input[2]> array_buffer_input{"array_buffer_input"}; - Input simple_input{"simple_input", 3}; // require a 3-dimensional Func but leave Type unspecified - Input array_input{"array_input", 3}; // require a 3-dimensional Func but leave Type and ArraySize unspecified - // Note that Input does not (yet) support Tuples - Input float_arg{"float_arg", 1.0f, 0.0f, 100.0f}; - Input int_arg{"int_arg", 1}; // leave ArraySize unspecified - - Output simple_output{"simple_output", Float(32), 3}; - Output tuple_output{"tuple_output", 3}; // require a 3-dimensional Func but leave Type(s) unspecified - Output array_output{"array_output", Int(16), 3}; // leave ArraySize unspecified - Output> typed_buffer_output{"typed_buffer_output"}; - Output> untyped_buffer_output{"untyped_buffer_output"}; - Output> tupled_output{"tupled_output", {Float(32), Int(32)}}; - Output> static_compiled_buffer_output{"static_compiled_buffer_output"}; - Output[2]> array_buffer_output{"array_buffer_output"}; - Output> float16_output{"float16_output"}; - Output> bfloat16_output{"bfloat16_output"}; - - void generate() { - simple_output(x, y, c) = cast(simple_input(x, y, c)); - float16_output(x, y, c) = cast(simple_input(x, y, c)); - bfloat16_output(x, y, c) = cast(simple_input(x, y, c)); - - typed_buffer_output(x, y, c) = cast(typed_buffer_input(x, y, c)); - // Note that if we are being invoked via a Stub, "untyped_buffer_output.type()" will - // assert-fail, because there is no type constraint set: the type - // will end up as whatever we infer from the values put into it. We'll use an - // explicit GeneratorParam to allow us to set it. - untyped_buffer_output(x, y, c) = cast(untyped_buffer_output_type, untyped_buffer_input(x, y, c)); - - tupled_output(x, y, c) = Tuple(simple_output(x, y, c), cast(simple_output(x, y, c)) + 1); - - for (int i = 0; i < 2; ++i) { - array_buffer_output[i](x, y, c) = array_buffer_input[i](x, y, c) + 1 + i; - } - - // Gratuitous intermediate for the purpose of exercising - // GeneratorParam - intermediate(x, y, c) = simple_input(x, y, c) * float_arg; - - tuple_output(x, y, c) = Tuple( - intermediate(x, y, c), - intermediate(x, y, c) + int_arg[0]); - // Verify that Output::type() and ::dims() are well-defined after we define the Func - assert(tuple_output.types()[0] == Float(32)); - assert(tuple_output.types()[1] == Float(32)); - assert(tuple_output.dimensions() == 3); - - array_output.resize(array_input.size()); - for (size_t i = 0; i < array_input.size(); ++i) { - array_output[i](x, y, c) = cast(array_input[i](x, y, c) + int_arg[i]); - } - - // This should be compiled into the Generator product itself, - // and not produce another input for the Stub or AOT filter. - Buffer static_compiled_buffer = make_image(42); - static_compiled_buffer_output = static_compiled_buffer; - } - - void schedule() { - if (!using_autoscheduler()) { - intermediate.compute_at(intermediate_level); - intermediate.specialize(vectorize).vectorize(x, natural_vector_size()); - } - } - -private: - Var x{"x"}, y{"y"}, c{"c"}; - - Func intermediate{"intermediate"}; -}; - -} // namespace - -HALIDE_REGISTER_GENERATOR(StubTest, stubtest, StubNS1::StubNS2::StubTest) diff --git a/test/generator/stubtest_jittest.cpp b/test/generator/stubtest_jittest.cpp deleted file mode 100644 index 685b717a2914..000000000000 --- a/test/generator/stubtest_jittest.cpp +++ /dev/null @@ -1,290 +0,0 @@ -#include "Halide.h" - -#include "stubtest.stub.h" - -using namespace Halide; - -using StubNS1::StubNS2::StubTest; - -const int kSize = 32; - -Var x, y, c; - -template -Buffer make_image(int extra) { - Buffer im(kSize, kSize, 3); - for (int x = 0; x < kSize; x++) { - for (int y = 0; y < kSize; y++) { - for (int c = 0; c < 3; c++) { - im(x, y, c) = static_cast(x + y + c + extra); - } - } - } - return im; -} - -template -void verify(const Buffer &input, float float_arg, int int_arg, const Buffer &output) { - if (input.width() != output.width() || - input.height() != output.height()) { - fprintf(stderr, "size mismatch: %dx%d vs %dx%d\n", input.width(), input.height(), output.width(), output.height()); - exit(1); - } - int channels = std::max(1, std::min(input.channels(), output.channels())); - for (int x = 0; x < output.width(); x++) { - for (int y = 0; y < output.height(); y++) { - for (int c = 0; c < channels; c++) { - const OutputType expected = static_cast(input(x, y, c) * float_arg + int_arg); - const OutputType actual = output(x, y, c); - if (expected != actual) { - fprintf(stderr, "img[%d, %d, %d] = %f, expected %f (input = %f)\n", x, y, c, (double)actual, (double)expected, (double)input(x, y, c)); - exit(1); - } - } - } - } -} - -int main(int argc, char **argv) { - constexpr int kArrayCount = 2; - - Buffer buffer_input = make_image(0); - Buffer simple_input = make_image(0); - Buffer array_input[kArrayCount] = { - make_image(0), - make_image(1)}; - - std::vector int_args = {33, 66}; - - // the Stub wants Expr, so make a conversion in place - std::vector int_args_expr(int_args.begin(), int_args.end()); - - GeneratorContext context(get_jit_target_from_environment()); - - { - // Pass in a set of GeneratorParams: even though we aren't customizing - // the values, we can set the LoopLevel values after-the-fact. - StubTest::GeneratorParams gp; - auto gen = StubTest::generate( - context, - // Use aggregate-initialization syntax to fill in an Inputs struct. - { - buffer_input, // typed_buffer_input - buffer_input, // untyped_buffer_input - {buffer_input, buffer_input}, - Func(simple_input), - {Func(array_input[0]), Func(array_input[1])}, - 1.25f, - int_args_expr}, - gp); - - gp.intermediate_level.set(LoopLevel(gen.tuple_output, gen.tuple_output.args().at(1))); - - Realization simple_output_realized = gen.simple_output.realize({kSize, kSize, 3}); - Buffer s0 = simple_output_realized; - verify(array_input[0], 1.f, 0, s0); - - Realization tuple_output_realized = gen.tuple_output.realize({kSize, kSize, 3}); - Buffer f0 = tuple_output_realized[0]; - Buffer f1 = tuple_output_realized[1]; - verify(array_input[0], 1.25f, 0, f0); - verify(array_input[0], 1.25f, 33, f1); - - for (int i = 0; i < kArrayCount; ++i) { - Realization array_output_realized = gen.array_output[i].realize({kSize, kSize, 3}, gen.target); - Buffer g0 = array_output_realized; - verify(array_input[i], 1.0f, int_args[i], g0); - } - - Realization typed_buffer_output_realized = gen.typed_buffer_output.realize({kSize, kSize, 3}); - Buffer b0 = typed_buffer_output_realized; - verify(buffer_input, 1.f, 0, b0); - - Realization untyped_buffer_output_realized = gen.untyped_buffer_output.realize({kSize, kSize, 3}); - Buffer b1 = untyped_buffer_output_realized; - verify(buffer_input, 1.f, 0, b1); - - Realization static_compiled_buffer_output_realized = gen.static_compiled_buffer_output.realize({kSize, kSize, 3}); - Buffer b2 = static_compiled_buffer_output_realized; - verify(buffer_input, 1.f, 42, b2); - - for (int i = 0; i < 2; ++i) { - Realization array_buffer_output_realized = gen.array_buffer_output[i].realize({kSize, kSize, 3}); - Buffer b2 = array_buffer_output_realized; - verify(buffer_input, 1.f, 1 + i, b2); - } - } - - // Alternately, instead of using Generator Stubs, we can just use the Callable interface. - // We can call this on any Generator that is registered in the current process. - { - Buffer buffer_input = make_image(0); - Buffer simple_input = make_image(0); - Buffer array_input0 = make_image(0); - Buffer array_input1 = make_image(1); - Buffer typed_buffer_output(kSize, kSize, 3); - Buffer untyped_buffer_output(kSize, kSize, 3); - Buffer tupled_output0(kSize, kSize, 3); - Buffer tupled_output1(kSize, kSize, 3); - Buffer array_buffer_input0 = make_image(0); - Buffer array_buffer_input1 = make_image(1); - Buffer simple_output(kSize, kSize, 3); - // TODO: see Issues #3709, #3967 - Buffer float16_output(halide_type_t(halide_type_float, 16), kSize, kSize, 3); - Buffer bfloat16_output(halide_type_t(halide_type_bfloat, 16), kSize, kSize, 3); - Buffer tuple_output0(kSize, kSize, 3), tuple_output1(kSize, kSize, 3); - Buffer array_output0(kSize, kSize, 3), array_output1(kSize, kSize, 3); - Buffer static_compiled_buffer_output(kSize, kSize, 3); - Buffer array_buffer_output0(kSize, kSize, 3), array_buffer_output1(kSize, kSize, 3); - - // Note that this Generator has several GeneratorParams that need to be set correctly - // before compilation -- in the Stub case above, the values end up being inferred - // from the specific inputs we provide, but for the JIT (and AOT) cases, there are - // no such inputs available, so we must be explicit. (Note that these are the same - // values specified in our Make/CMake files.) - const GeneratorParamsMap gp = { - {"untyped_buffer_input.type", "uint8"}, - {"untyped_buffer_input.dim", "3"}, - {"simple_input.type", "float32"}, - {"array_input.type", "float32"}, - {"array_input.size", "2"}, - {"int_arg.size", "2"}, - {"tuple_output.type", "float32,float32"}, - {"vectorize", "true"}, - }; - - Callable stubtest = create_callable_from_generator(context, "stubtest", gp); - - int r = stubtest( - buffer_input, - buffer_input, - array_buffer_input0, array_buffer_input1, - simple_input, - array_input0, array_input1, - 1.25f, - 33, - 66, - simple_output, - tuple_output0, tuple_output1, - array_output0, array_output1, - typed_buffer_output, - untyped_buffer_output, - tupled_output0, tupled_output1, - static_compiled_buffer_output, - array_buffer_output0, array_buffer_output1, - float16_output, - bfloat16_output); - assert(r == 0); - - verify(buffer_input, 1.f, 0, typed_buffer_output); - verify(buffer_input, 1.f, 0, untyped_buffer_output); - verify(simple_input, 1.f, 0, simple_output); - verify(simple_input, 1.f, 0, tupled_output0); - verify(simple_input, 1.f, 1, tupled_output1); - verify(array_input0, 1.f, 0, simple_output); - verify(array_input0, 1.25f, 0, tuple_output0); - verify(array_input0, 1.25f, 33, tuple_output1); - verify(array_input0, 1.0f, 33, array_output0); - verify(array_input1, 1.0f, 66, array_output1); - verify(buffer_input, 1.0f, 42, static_compiled_buffer_output); - verify(array_buffer_input0, 1.f, 1, array_buffer_output0); - verify(array_buffer_input1, 1.f, 2, array_buffer_output1); - } - - // We can also make an explicitly-typed std::function if we prefer. - { - Buffer buffer_input = make_image(0); - Buffer simple_input = make_image(0); - Buffer array_input0 = make_image(0); - Buffer array_input1 = make_image(1); - Buffer typed_buffer_output(kSize, kSize, 3); - Buffer untyped_buffer_output(kSize, kSize, 3); - Buffer tupled_output0(kSize, kSize, 3); - Buffer tupled_output1(kSize, kSize, 3); - Buffer array_buffer_input0 = make_image(0); - Buffer array_buffer_input1 = make_image(1); - Buffer simple_output(kSize, kSize, 3); - // TODO: see Issues #3709, #3967 - Buffer float16_output(halide_type_t(halide_type_float, 16), kSize, kSize, 3); - Buffer bfloat16_output(halide_type_t(halide_type_bfloat, 16), kSize, kSize, 3); - Buffer tuple_output0(kSize, kSize, 3), tuple_output1(kSize, kSize, 3); - Buffer array_output0(kSize, kSize, 3), array_output1(kSize, kSize, 3); - Buffer static_compiled_buffer_output(kSize, kSize, 3); - Buffer array_buffer_output0(kSize, kSize, 3), array_buffer_output1(kSize, kSize, 3); - - // Note that this Generator has several GeneratorParams that need to be set correctly - // before compilation -- in the Stub case above, the values end up being inferred - // from the specific inputs we provide, but for the JIT (and AOT) cases, there are - // no such inputs available, so we must be explicit. (Note that these are the same - // values specified in our Make/CMake files.) - const GeneratorParamsMap gp = { - {"untyped_buffer_input.type", "uint8"}, - {"untyped_buffer_input.dim", "3"}, - {"simple_input.type", "float32"}, - {"array_input.type", "float32"}, - {"array_input.size", "2"}, - {"int_arg.size", "2"}, - {"tuple_output.type", "float32,float32"}, - {"vectorize", "true"}, - }; - - auto stubtest = create_callable_from_generator(context, "stubtest", gp) - .make_std_function< - Buffer, - Buffer, - Buffer, Buffer, - Buffer, - Buffer, Buffer, - float, - int32_t, - int32_t, - Buffer, - Buffer, Buffer, - Buffer, Buffer, - Buffer, - Buffer, - Buffer, Buffer, - Buffer, - Buffer, Buffer, - Buffer, - Buffer>(); - - int r = stubtest( - buffer_input, - buffer_input, - array_buffer_input0, array_buffer_input1, - simple_input, - array_input0, array_input1, - 1.25f, - 33, - 66, - simple_output, - tuple_output0, tuple_output1, - array_output0, array_output1, - typed_buffer_output, - untyped_buffer_output, - tupled_output0, tupled_output1, - static_compiled_buffer_output, - array_buffer_output0, array_buffer_output1, - float16_output, - bfloat16_output); - assert(r == 0); - - verify(buffer_input, 1.f, 0, typed_buffer_output); - verify(buffer_input, 1.f, 0, untyped_buffer_output); - verify(simple_input, 1.f, 0, simple_output); - verify(simple_input, 1.f, 0, tupled_output0); - verify(simple_input, 1.f, 1, tupled_output1); - verify(array_input0, 1.f, 0, simple_output); - verify(array_input0, 1.25f, 0, tuple_output0); - verify(array_input0, 1.25f, 33, tuple_output1); - verify(array_input0, 1.0f, 33, array_output0); - verify(array_input1, 1.0f, 66, array_output1); - verify(buffer_input, 1.0f, 42, static_compiled_buffer_output); - verify(array_buffer_input0, 1.f, 1, array_buffer_output0); - verify(array_buffer_input1, 1.f, 2, array_buffer_output1); - } - - printf("Success!\n"); - return 0; -} diff --git a/test/generator/stubuser_aottest.cpp b/test/generator/stubuser_aottest.cpp deleted file mode 100644 index 60ef87d40dea..000000000000 --- a/test/generator/stubuser_aottest.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include - -#include "HalideBuffer.h" -#include "HalideRuntime.h" -#include "halide_benchmark.h" - -#include "stubuser.h" -#include "stubuser_auto.h" - -using namespace Halide::Runtime; - -const int kSize = 32; - -template -Buffer make_image() { - Buffer im(kSize, kSize, 3); - for (int x = 0; x < kSize; x++) { - for (int y = 0; y < kSize; y++) { - for (int c = 0; c < 3; c++) { - im(x, y, c) = static_cast(x + y + c); - } - } - } - return im; -} - -const float kFloatArg = 1.234f; -const int kIntArg = 33; -const float kOffset = 2.f; - -template -void verify(const Buffer &input, float float_arg, int int_arg, float offset, const Buffer &output) { - if (input.width() != output.width() || - input.height() != output.height()) { - fprintf(stderr, "size mismatch\n"); - exit(1); - } - int channels = std::max(1, std::min(input.channels(), output.channels())); - for (int x = 0; x < output.width(); x++) { - for (int y = 0; y < output.height(); y++) { - for (int c = 0; c < channels; c++) { - const OutputType expected = static_cast(input(x, y, c) * float_arg + int_arg + offset); - const OutputType actual = output(x, y, c); - if (expected != actual) { - fprintf(stderr, "img[%d, %d, %d] = %f, expected %f\n", x, y, c, (double)actual, (double)expected); - exit(1); - } - } - } - } -} - -int main(int argc, char **argv) { - - Buffer input = make_image(); - Buffer calculated_output(kSize, kSize, 3); - Buffer float32_buffer_output(kSize, kSize, 3); - Buffer int32_buffer_output(halide_type_t(halide_type_int, 32), kSize, kSize, 3); - Buffer array_test_output(kSize, kSize, 3); - Buffer tupled_output0(kSize, kSize, 3); - Buffer tupled_output1(kSize, kSize, 3); - Buffer int_output(kSize, kSize, 3); - // TODO: see Issues #3709, #3967 - Buffer float16_output(halide_type_t(halide_type_float, 16), kSize, kSize, 3); - Buffer bfloat16_output(halide_type_t(halide_type_bfloat, 16), kSize, kSize, 3); - - struct FnInfo { - decltype(&stubuser) f; - const char *const name; - }; - FnInfo fns[2] = {{stubuser, "stubuser"}, {stubuser_auto, "stubuser_auto"}}; - for (auto f : fns) { - printf("Testing %s...\n", f.name); - f.f(input, calculated_output, float32_buffer_output, int32_buffer_output, - array_test_output, tupled_output0, tupled_output1, int_output, - float16_output, bfloat16_output); - verify(input, kFloatArg, kIntArg, kOffset, calculated_output); - verify(input, 1.f, 0, 0.f, float32_buffer_output); - verify(input, 1.f, 0, 0.f, int32_buffer_output); - verify(input, 1.f, 0, 2, array_test_output); - verify(input, 1.f, 0, 0, tupled_output0); - verify(input, 1.f, 1, 3, int_output); - } - - printf("Success!\n"); - return 0; -} diff --git a/test/generator/stubuser_generator.cpp b/test/generator/stubuser_generator.cpp deleted file mode 100644 index f5400f95912a..000000000000 --- a/test/generator/stubuser_generator.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "Halide.h" -#include "configure.stub.h" -#include "stubtest.stub.h" - -using Halide::Buffer; -using StubNS1::StubNS2::StubTest; - -namespace { - -template -Buffer make_image() { - Buffer im(size, size, 3); - for (int x = 0; x < size; x++) { - for (int y = 0; y < size; y++) { - for (int c = 0; c < 3; c++) { - im(x, y, c) = static_cast(x + y + c); - } - } - } - return im; -} - -class StubUser : public Halide::Generator { -public: - GeneratorParam int_arg{"int_arg", 33}; - - Input> input{"input"}; - Output> calculated_output{"calculated_output"}; - Output> float32_buffer_output{"float32_buffer_output"}; - Output> int32_buffer_output{"int32_buffer_output"}; - Output> array_test_output{"array_test_output"}; - // We can infer the tupled-output-type from the Stub - Output> tupled_output{"tupled_output"}; - Output> int_output{"int_output"}; - Output> float16_output{"float16_output"}; - Output> bfloat16_output{"bfloat16_output"}; - - void generate() { - Var x{"x"}, y{"y"}, c{"c"}; - - Buffer constant_image = make_image(); - - // We'll explicitly fill in the struct fields by name, just to show - // it as an option. (Alternately, we could fill it in by using - // aggregate-initialization syntax.) - StubTest::Inputs inputs; - inputs.typed_buffer_input = constant_image; - inputs.untyped_buffer_input = input; - inputs.array_buffer_input = {input, input}; - inputs.simple_input = input; - inputs.array_input = {input}; - inputs.float_arg = 1.234f; - inputs.int_arg = {int_arg}; - - StubTest::GeneratorParams gp; - gp.untyped_buffer_output_type = int32_buffer_output.type(); - gp.intermediate_level.set(LoopLevel(calculated_output, Var("y"))); - gp.vectorize = true; - gp.str_param = "2 x * y +"; - - // Stub outputs that are Output (rather than Output) - // can really only be assigned to another Output; this is - // nevertheless useful, as we can still set stride (etc) constraints - // on the Output. - StubTest::Outputs out = StubTest::generate(context(), inputs, gp); - - float32_buffer_output = out.typed_buffer_output; - int32_buffer_output = out.untyped_buffer_output; - array_test_output = out.array_buffer_output[1]; - tupled_output = out.tupled_output; - float16_output = out.float16_output; - bfloat16_output = out.bfloat16_output; - - const float kOffset = 2.f; - calculated_output(x, y, c) = cast(out.tuple_output(x, y, c)[1] + kOffset); - - Buffer configure_input = make_image(); - const int bias = 1; - Buffer extra_u8(32, 32); - extra_u8.fill(0); - Buffer extra_i16(32, 32); - extra_i16.fill(0); - Func extra_func; - extra_func(x, y, c) = cast(3); - const int extra_scalar = 0; - const int8_t extra_dynamic_scalar = 0; - int_output = configure::generate(context(), {configure_input, - bias, - extra_u8, - extra_u8, - extra_u8, - extra_i16, - extra_func, - extra_scalar, - cast(extra_dynamic_scalar)}) - .output; - - // Estimates (for autoscheduler): - constexpr int kSize = 32; - input.set_estimates({{0, kSize}, {0, kSize}, {0, 3}}); - calculated_output.set_estimates({{0, kSize}, {0, kSize}, {0, 3}}); - float32_buffer_output.set_estimates({{0, kSize}, {0, kSize}, {0, 3}}); - int32_buffer_output.set_estimates({{0, kSize}, {0, kSize}, {0, 3}}); - array_test_output.set_estimates({{0, kSize}, {0, kSize}, {0, 3}}); - tupled_output.set_estimates({{0, kSize}, {0, kSize}, {0, 3}}); - int_output.set_estimates({{0, kSize}, {0, kSize}, {0, 3}}); - float16_output.set_estimates({{0, kSize}, {0, kSize}, {0, 3}}); - bfloat16_output.set_estimates({{0, kSize}, {0, kSize}, {0, 3}}); - } -}; - -} // namespace - -HALIDE_REGISTER_GENERATOR(StubUser, stubuser) From c2e0c814c12664fd468493708506d175020820bb Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 9 Mar 2026 22:36:16 -0400 Subject: [PATCH 2/2] Run clang-format --- src/Generator.cpp | 2 -- src/Generator.h | 1 - test/correctness/compile_to_multitarget.cpp | 10 +++++----- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Generator.cpp b/src/Generator.cpp index 8780b67fbddd..cd9dde7ffed4 100644 --- a/src/Generator.cpp +++ b/src/Generator.cpp @@ -123,8 +123,6 @@ std::vector parse_halide_type_list(const std::string &types) { return result; } - - const std::map &get_halide_type_enum_map() { static const std::map halide_type_enum_map{ {"bool", Bool()}, diff --git a/src/Generator.h b/src/Generator.h index 8ea43af8ca52..a10f455240f3 100644 --- a/src/Generator.h +++ b/src/Generator.h @@ -1424,7 +1424,6 @@ class GeneratorInputBase : public GIOBase { void verify_internals() override; - virtual std::string get_c_type() const = 0; void check_value_writable() const override; diff --git a/test/correctness/compile_to_multitarget.cpp b/test/correctness/compile_to_multitarget.cpp index a00425142357..23b202482734 100644 --- a/test/correctness/compile_to_multitarget.cpp +++ b/test/correctness/compile_to_multitarget.cpp @@ -182,11 +182,11 @@ void test_compile_to_everything(Func j, bool do_object) { return j.compile_to_module(args, name, target); }; std::map outputs = { - {OutputFileType::assembly, filename_prefix + ".s"}, // IsMulti - {OutputFileType::bitcode, filename_prefix + ".bc"}, // IsMulti - {OutputFileType::c_header, filename_prefix + ".h"}, // IsSingle - {OutputFileType::c_source, filename_prefix + ".halide_generated.cpp"}, // IsSingle - {OutputFileType::compiler_log, filename_prefix + ".halide_compiler_log"}, // IsSingle + {OutputFileType::assembly, filename_prefix + ".s"}, // IsMulti + {OutputFileType::bitcode, filename_prefix + ".bc"}, // IsMulti + {OutputFileType::c_header, filename_prefix + ".h"}, // IsSingle + {OutputFileType::c_source, filename_prefix + ".halide_generated.cpp"}, // IsSingle + {OutputFileType::compiler_log, filename_prefix + ".halide_compiler_log"}, // IsSingle {OutputFileType::featurization, filename_prefix + ".featurization"}, // IsMulti {OutputFileType::function_info_header, filename_prefix + ".function_info.h"}, // IsSingle // Note: compile_multitarget() doesn't produce hlpipe output,