6#include "halide_thread_pool.h"
76 static constexpr int max_i32 = 0x7fffffff;
150 const std::string &op,
151 const std::string &name,
153 const std::vector<Argument> &arg_types,
154 std::ostringstream &error_msg) {
155 std::string
fn_name =
"test_" + name;
159 std::map<OutputFileType, std::string> outputs = {
171 std::ostringstream msg;
172 msg << op <<
" did not generate for target=" <<
get_run_target().
to_string() <<
" vector_width=" << vector_width <<
". Instead we got:\n";
183 error_msg <<
"Failed: " << msg.str() <<
"\n";
192 while (*
p && *str && *
p == *str && *
p !=
'*') {
199 }
else if (*
p ==
'*') {
206 }
else if (*
p ==
' ') {
211 }
else if (*str ==
' ') {
237 std::ostringstream error_msg;
259 p.dim(0).set_min((
p.dim(0).
min() / alignment) * alignment);
268 if (op->
name ==
"input") {
270 if (
p.type() == op->
type) {
271 return p(mutate(op->
args[0]));
300 IRVisitor::visit(op);
331 .split(x,
xo,
xi, vector_width)
333 .vectorize(g.rvars()[0])
349 std::vector<Runtime::Buffer<>> inputs(
image_params.size());
352 for (
size_t i = 0;
i < args.size();
i++) {
362 assert(inputs.size() == 12);
363 (void)
callable(inputs[0], inputs[1], inputs[2], inputs[3],
364 inputs[4], inputs[5], inputs[6], inputs[7],
365 inputs[8], inputs[9], inputs[10], inputs[11],
372 for (
size_t i = 0;
i < inputs.size();
i++) {
373 if (inputs[
i].size_in_bytes()) {
374 inputs[
i].allocate();
376 Type t = inputs[
i].type();
380 if (t ==
Float(32)) {
381 inputs[
i].as<
float>().for_each_value([&](
float &f) { f = (rng() & 0xfff) / 8.0f - 0xff; });
382 }
else if (t ==
Float(64)) {
383 inputs[
i].as<
double>().for_each_value([&](
double &f) { f = (rng() & 0xfff) / 8.0 - 0xff; });
384 }
else if (t ==
Float(16)) {
389 ptr != (
uint32_t *)inputs[
i].data() + inputs[
i].size_in_bytes() / 4;
393 *ptr = ((
uint32_t)rng()) & 0x0fffffff;
400 (void)
callable(inputs[0], inputs[1], inputs[2], inputs[3],
401 inputs[4], inputs[5], inputs[6], inputs[7],
402 inputs[8], inputs[9], inputs[10], inputs[11],
411 error_msg <<
"The vector and scalar versions of " << name <<
" disagree. Maximum error: " << e <<
"\n";
419 error_msg <<
"Error assembly: \n";
422 error_msg <<
line <<
"\n";
429 return {op, error_msg.str()};
434 std::string name =
"op_" + op;
435 for (
size_t i = 0;
i < name.size();
i++) {
439 name +=
"_" + std::to_string(
tasks.size());
446 tasks.emplace_back(
Task{op, name, vector_width, e});
467 Halide::Tools::ThreadPool<TestResult> pool(
469 Halide::Tools::ThreadPool<TestResult>::num_processors_online() :
471 std::vector<std::future<TestResult>>
futures;
473 for (
size_t t = 0; t <
tasks.size(); t++) {
474 if (!
sharder.should_run(t))
continue;
475 const auto &task =
tasks.at(t);
476 futures.push_back(pool.async([&]() {
477 return check_one(task.op, task.name, task.vector_width, task.expr);
482 auto result = f.get();
484 const int spaces = std::max(1,
tabstop - (
int)result.op.size());
486 if (!result.error_msg.empty()) {
487 std::cerr << result.error_msg;
498 template<
typename SIMDOpCheckT>
501 std::cout <<
"host is: " << host <<
"\n";
504 std::cout <<
"simd_op_check test seed: " <<
seed <<
"\n";
507 if (!t.supported()) {
508 std::cout <<
"[SKIP] Unsupported target: " << t <<
"\n";
513 if (!t.supported()) {
514 std::cout <<
"Halide was compiled without support for " << t.to_string() <<
". Skipping.\n";
519 test.filter = argv[1];
522 if (
getenv(
"HL_SIMD_OP_CHECK_FILTER")) {
523 test.filter =
getenv(
"HL_SIMD_OP_CHECK_FILTER");
535 test.output_directory = argv[2];
538 bool success = test.test_all();
548 std::cout <<
"Success!\n";
void compile_to_assembly(const std::string &filename, const std::vector< Argument > &, const std::string &fn_name, const Target &target=get_target_from_environment())
Statically compile this function to text assembly equivalent to the object file generated by compile_...
Func & compute_root()
Compute all of this function once ahead of time.
Callable compile_to_callable(const std::vector< Argument > &args, const Target &target=get_jit_target_from_environment())
Eagerly jit compile the function to machine code and return a callable struct that behaves like a fun...
void compile_to(const std::map< OutputFileType, std::string > &output_files, const std::vector< Argument > &args, const std::string &fn_name, const Target &target=get_target_from_environment())
Compile and generate multiple target files with single call.
Func & vectorize(const VarOrRVar &var)
Mark a dimension to be computed all-at-once as a single vector.
Func & bound(const Var &var, Expr min, Expr extent)
Statically declare that the range over which a function should be evaluated is given by the second an...
An Image parameter to a halide pipeline.
const StageSchedule & schedule() const
Get the default (no-specialization) stage-specific schedule associated with this definition.
A reference-counted handle to Halide's internal representation of a function.
bool has_update_definition() const
Does this function have an update definition?
void mutate(IRMutator *mutator)
Accept a mutator to mutator all of the definitions and arguments of this function.
Definition & update(int idx=0)
Get a mutable handle to this function's update definition at index 'idx'.
A base class for passes over the IR which modify it (e.g.
virtual Expr visit(const IntImm *)
A base class for algorithms that need to recursively walk over the IR.
virtual void visit(const IntImm *)
const std::vector< ReductionVariable > & rvars() const
RVars of reduction domain associated with this schedule if there is any.
A multi-dimensional domain over which to iterate.
A reduction variable represents a single dimension of a reduction domain (RDom).
A templated Buffer class that wraps halide_buffer_t and adds functionality.
static Buffer< T, Dims, InClassDimStorage > make_scalar()
Make a zero-dimensional Buffer.
static constexpr int max_u8
std::string output_directory
static constexpr int max_i32
virtual bool use_multiple_threads() const
virtual void add_tests()=0
virtual int image_param_alignment()
bool wildcard_match(const std::string &p, const std::string &str) const
static constexpr int max_i8
static constexpr int max_u16
bool wildcard_search(const std::string &p, const std::string &str) const
bool wildcard_match(const char *p, const char *str) const
virtual ~SimdOpCheckTest()=default
SimdOpCheckTest(const Target t, int w, int h)
void check(std::string op, int vector_width, Expr e)
Target get_run_target() const
static int main(int argc, char **argv, const std::vector< Target > &targets_to_test)
static constexpr int max_i16
TestResult check_one(const std::string &op, const std::string &name, int vector_width, Expr e)
virtual bool can_run_code() const
std::vector< Task > tasks
virtual void compile_and_check(Func error, const std::string &op, const std::string &name, int vector_width, const std::vector< Argument > &arg_types, std::ostringstream &error_msg)
A Halide variable, to be used when defining functions.
std::map< OutputFileType, const OutputInfo > get_output_info(const Target &target)
std::string get_test_tmp_dir()
Return the path to a directory that can be safely written to when running tests; the contents directo...
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Target get_host_target()
Return the target corresponding to the host machine.
Type BFloat(int bits, int lanes=1)
Construct a floating-point type in the bfloat format.
Type UInt(int bits, int lanes=1)
Constructing an unsigned integer type.
Type Float(int bits, int lanes=1)
Construct a floating-point type.
Expr maximum(Expr, const std::string &s="maximum")
Type Int(int bits, int lanes=1)
Constructing a signed integer type.
Expr absd(Expr a, Expr b)
Return the absolute difference between two values.
void compile_standalone_runtime(const std::string &object_filename, const Target &t)
Create an object file containing the Halide runtime for a given target.
Internal::ConstantInterval cast(Type t, const Internal::ConstantInterval &a)
Cast operators for ConstantIntervals.
unsigned __INT32_TYPE__ uint32_t
char * getenv(const char *)
A fragment of Halide syntax.
@ Extern
A call to an external C-ABI function, possibly with side-effects.
@ Halide
A call to a Func.
static Expr make(Type type, IntrinsicOp op, const std::vector< Expr > &args, CallType call_type, FunctionPtr func=FunctionPtr(), int value_index=0, const Buffer<> &image=Buffer<>(), Parameter param=Parameter())
int64_t min
The lower and upper bound of the interval.
void accept(IRVisitor *v) const
Dispatch to the correct visitor method for this node.
static bool can_jit_target(const Target &target)
If the given target can be executed via the wasm executor, return true.
A struct representing a target machine and os to generate code for.
enum Halide::Target::Arch arch
bool has_feature(Feature f) const
int bits
The bit-width of the target machine.
enum Halide::Target::OS os
std::string to_string() const
Convert the Target into a string form that can be reconstituted by merge_string(),...
Target without_feature(Feature f) const
Return a copy of the target with the given feature cleared.
Feature
Optional features a target can have.
Target with_feature(Feature f) const
Return a copy of the target with the given feature set.
Types in the halide type system.
Expr max() const
Return an expression which is the maximum value of this type.
Class that provides a type that implements half precision floating point (IEEE754 2008 binary16) in s...