Skip to content

Commit

Permalink
Trim code size for Printer
Browse files Browse the repository at this point in the history
This builds on top of #6472 to de-inline as much of Printer as possible, moving things into a new 'printer' runtime module using a PrinterBase class.

This is, admittedly, a pretty small improvement: comparing before-and-after on OSX for target=host shows only a ~4k reduction in object size (115k -> 111k for `runtime.o`) but adding targets with more verbose error reporting and such increases the benefit (eg host-opencl gives a 179k -> 164k reduction for runtime.o).

Since ~all of the usages of Printer in runtime are for error handling, debugging, profiling, or tracing, any possible reduction in performance seems unlikely to be significant.
  • Loading branch information
steven-johnson committed Dec 6, 2021
1 parent 319fb63 commit 3c5e2d2
Show file tree
Hide file tree
Showing 7 changed files with 228 additions and 143 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,7 @@ RUNTIME_CPP_COMPONENTS = \
posix_threads_tsan \
powerpc_cpu_features \
prefetch \
printer \
profiler \
profiler_inlined \
pseudostack \
Expand Down
3 changes: 3 additions & 0 deletions src/LLVM_Runtime_Linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ DECLARE_CPP_INITMOD(posix_print)
DECLARE_CPP_INITMOD(posix_threads)
DECLARE_CPP_INITMOD(posix_threads_tsan)
DECLARE_CPP_INITMOD(prefetch)
DECLARE_CPP_INITMOD(printer)
DECLARE_CPP_INITMOD(profiler)
DECLARE_CPP_INITMOD(profiler_inlined)
DECLARE_CPP_INITMOD(pseudostack)
Expand Down Expand Up @@ -1111,8 +1112,10 @@ std::unique_ptr<llvm::Module> get_initial_module_for_target(Target t, llvm::LLVM

if (module_type == ModuleJITShared || module_type == ModuleGPU) {
modules.push_back(get_initmod_module_jit_ref_count(c, bits_64, debug));
modules.push_back(get_initmod_printer(c, bits_64, debug));
} else if (module_type == ModuleAOT) {
modules.push_back(get_initmod_module_aot_ref_count(c, bits_64, debug));
modules.push_back(get_initmod_printer(c, bits_64, debug));
}

if (module_type == ModuleAOT || module_type == ModuleGPU) {
Expand Down
5 changes: 3 additions & 2 deletions src/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -711,9 +711,10 @@ std::map<Output, std::string> compile_standalone_runtime(const std::map<Output,

Module empty("standalone_runtime", t.without_feature(Target::NoRuntime).without_feature(Target::JIT));
// For runtime, it only makes sense to output object files or static_library, so ignore
// everything else.
// everything else. (Well, LLVM IR and actual assembly can be useful for debugging and optimzation
// as well, so let's allow that, too.)
std::map<Output, std::string> actual_outputs;
for (auto key : {Output::object, Output::static_library}) {
for (auto key : {Output::object, Output::static_library, Output::llvm_assembly, Output::assembly}) {
auto it = output_files.find(key);
if (it != output_files.end()) {
actual_outputs[key] = it->second;
Expand Down
1 change: 1 addition & 0 deletions src/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ set(RUNTIME_CPP
posix_threads_tsan
powerpc_cpu_features
prefetch
printer
profiler
profiler_inlined
pseudostack
Expand Down
129 changes: 129 additions & 0 deletions src/runtime/printer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#include "printer.h"
#include "HalideRuntime.h"

namespace Halide {
namespace Runtime {
namespace Internal {

static const char *const kAllocationError = "Printer buffer allocation failed.\n";

WEAK PrinterBase::PrinterBase(void *ctx, char *mem, uint64_t length)
: user_context(ctx), length(length) {

if (mem == nullptr) {
mem = (char *)malloc(length);
mem_to_free = mem;
} else {
mem_to_free = nullptr;
}

dst = buf = mem;
if (dst) {
end = buf + length - 1;
*end = 0;
} else {
end = dst;
}
}

WEAK PrinterBase::PrinterBase(void *ctx)
: PrinterBase(ctx, nullptr, default_printer_buffer_length) {
}

WEAK PrinterBase &PrinterBase::operator<<(const char *arg) {
dst = halide_string_to_string(dst, end, arg);
return *this;
}

WEAK PrinterBase &PrinterBase::operator<<(int64_t arg) {
dst = halide_int64_to_string(dst, end, arg, 1);
return *this;
}

WEAK PrinterBase &PrinterBase::operator<<(int32_t arg) {
dst = halide_int64_to_string(dst, end, arg, 1);
return *this;
}

WEAK PrinterBase &PrinterBase::operator<<(uint64_t arg) {
dst = halide_uint64_to_string(dst, end, arg, 1);
return *this;
}

WEAK PrinterBase &PrinterBase::operator<<(uint32_t arg) {
dst = halide_uint64_to_string(dst, end, arg, 1);
return *this;
}

WEAK PrinterBase &PrinterBase::operator<<(double arg) {
dst = halide_double_to_string(dst, end, arg, 1);
return *this;
}

WEAK PrinterBase &PrinterBase::operator<<(float arg) {
dst = halide_double_to_string(dst, end, arg, 0);
return *this;
}

WEAK PrinterBase &PrinterBase::operator<<(const void *arg) {
dst = halide_pointer_to_string(dst, end, arg);
return *this;
}

WEAK PrinterBase &PrinterBase::write_float16_from_bits(const uint16_t arg) {
double value = halide_float16_bits_to_double(arg);
dst = halide_double_to_string(dst, end, value, 1);
return *this;
}

WEAK PrinterBase &PrinterBase::operator<<(const halide_type_t &t) {
dst = halide_type_to_string(dst, end, &t);
return *this;
}

WEAK PrinterBase &PrinterBase::operator<<(const halide_buffer_t &buf) {
dst = halide_buffer_to_string(dst, end, &buf);
return *this;
}

// Use it like a stringstream.
WEAK const char *PrinterBase::str() {
if (!buf) {
return kAllocationError;
}

// This is really only needed for StringStreamPrinter, but is easier to do unconditionally
halide_msan_annotate_memory_is_initialized(user_context, buf, dst - buf + 1);
return buf;
}

// Clear it. Useful for reusing a stringstream.
WEAK void PrinterBase::clear() {
dst = buf;
if (dst) {
dst[0] = 0;
}
}

// Delete the last N characters
WEAK void PrinterBase::erase(int n) {
if (dst) {
dst -= n;
if (dst < buf) {
dst = buf;
}
dst[0] = 0;
}
}

WEAK void PrinterBase::finish_error() {
halide_error(user_context, str());
}

WEAK void PrinterBase::finish_print() {
halide_print(user_context, str());
}

} // namespace Internal
} // namespace Runtime
} // namespace Halide
Loading

0 comments on commit 3c5e2d2

Please sign in to comment.