1 #ifndef SIMD_OP_CHECK_H
2 #define SIMD_OP_CHECK_H
43 const std::vector<ImageParam>
image_params{
in_f32,
in_f64,
in_bf16,
in_i8,
in_u8,
in_i16,
in_u16,
in_i32,
in_u32,
in_i64,
in_u64};
44 const std::vector<Argument>
arg_types{
in_f32,
in_f64,
in_bf16,
in_i8,
in_u8,
in_i16,
in_u16,
in_i32,
in_u32,
in_i64,
in_u64};
79 bool can_run_the_code =
92 can_run_the_code =
false;
95 return can_run_the_code;
98 virtual void compile_and_check(
Func error,
const std::string &op,
const std::string &name,
int vector_width, std::ostringstream &error_msg) {
99 std::string fn_name =
"test_" + name;
103 std::map<Output, std::string> outputs = {
110 std::ifstream asm_file;
111 asm_file.open(file_name +
".s");
113 bool found_it =
false;
115 std::ostringstream msg;
116 msg << op <<
" did not generate for target=" <<
target.
to_string() <<
" vector_width=" << vector_width <<
". Instead we got:\n";
119 while (getline(asm_file, line)) {
127 error_msg <<
"Failed: " << msg.str() <<
"\n";
136 while (*p && *str && *p == *str && *p !=
'*') {
143 }
else if (*p ==
'*') {
150 }
else if (*p ==
' ') {
155 }
else if (*str ==
' ') {
174 std::ostringstream error_msg;
182 inline_reduction = f;
186 IRVisitor::visit(op);
192 } has_inline_reduction;
193 e.
accept(&has_inline_reduction);
205 if (has_inline_reduction.result) {
210 Func g{has_inline_reduction.inline_reduction};
217 .split(x, xo, xi, vector_width)
219 .vectorize(g.rvars()[0])
226 error() = Halide::cast<double>(
maximum(
absd(f(r_check.
x, r_check.
y), f_scalar(r_check.
x, r_check.
y))));
232 if (can_run_the_code) {
242 if (!
buf.defined())
continue;
248 if (t ==
Float(32)) {
249 buf.as<
float>().for_each_value([&](
float &f) { f = (
rng() & 0xfff) / 8.0f - 0xff; });
250 }
else if (t ==
Float(64)) {
251 buf.as<
double>().for_each_value([&](
double &f) { f = (
rng() & 0xfff) / 8.0 - 0xff; });
270 error_msg <<
"The vector and scalar versions of " << name <<
" disagree. Maximum error: " << e <<
"\n";
275 std::ifstream error_file;
276 error_file.open(error_filename);
278 error_msg <<
"Error assembly: \n";
280 while (getline(error_file, line)) {
281 error_msg << line <<
"\n";
288 return {op, error_msg.str()};
293 std::string name =
"op_" + op;
294 for (
size_t i = 0; i < name.size(); i++) {
295 if (!isalnum(name[i])) name[i] =
'_';
298 name +=
"_" + std::to_string(
tasks.size());
305 tasks.emplace_back(
Task{op, name, vector_width, e});
312 const int alignment_bytes = 16;
313 p.set_host_alignment(alignment_bytes);
314 const int alignment = alignment_bytes / p.type().bytes();
315 p.dim(0).set_min((p.dim(0).min() / alignment) * alignment);
322 std::vector<std::future<TestResult>> futures;
324 futures.push_back(pool.
async([
this, task]() {
325 return check_one(task.op, task.name, task.vector_width, task.expr);
330 for (
auto &f : futures) {
332 std::cout << result.
op <<
"\n";
A Halide::Buffer is a named shared reference to a Halide::Runtime::Buffer.
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.
Stage update(int idx=0)
Get a handle on an update step for the purposes of scheduling it.
void infer_input_bounds(const std::vector< int32_t > &sizes, const Target &target=get_jit_target_from_environment(), const ParamMap ¶m_map=ParamMap::empty_map())
For a given size of output, or a given output buffer, determine the bounds required of all unbound Im...
Func & vectorize(const VarOrRVar &var)
Mark a dimension to be computed all-at-once as a single vector.
Func & compute_at(const Func &f, const Var &var)
Compute this function as needed for each unique value of the given var for the given calling function...
Realization realize(std::vector< int32_t > sizes={}, const Target &target=Target(), const ParamMap ¶m_map=ParamMap::empty_map())
Evaluate this function over some rectangular domain and return the resulting buffer or buffers.
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...
void compile_to(const std::map< Output, 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 clone_in(const Func &f)
Similar to Func::in; however, instead of replacing the call to this Func with an identity Func that r...
An Image parameter to a halide pipeline.
A reference-counted handle to Halide's internal representation of a function.
bool has_update_definition() const
Does this function have an update definition?
A base class for algorithms that need to recursively walk over the IR.
virtual void visit(const IntImm *)
std::future< T > async(Func func, Args... args)
static size_t num_processors_online()
A multi-dimensional domain over which to iterate.
RVar x
Direct access to the first four dimensions of the reduction domain.
A reduction variable represents a single dimension of a reduction domain (RDom).
A Realization is a vector of references to existing Buffer objects.
size_t get_num_threads() const
virtual void compile_and_check(Func error, const std::string &op, const std::string &name, int vector_width, std::ostringstream &error_msg)
const std::vector< Argument > arg_types
std::string output_directory
virtual void setup_images()
virtual void add_tests()=0
bool wildcard_match(const std::string &p, const std::string &str) const
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)
const std::vector< ImageParam > image_params
TestResult check_one(const std::string &op, const std::string &name, int vector_width, Expr e)
void set_num_threads(size_t n)
virtual bool can_run_code() const
std::vector< Task > tasks
A Halide variable, to be used when defining functions.
std::map< Output, 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.
unsigned __INT32_TYPE__ uint32_t
A fragment of Halide syntax.
@ Halide
A call to a Func.
void accept(IRVisitor *v) const
Dispatch to the correct visitor method for this node.
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.