Expr lossless_cast(Type t, Expr e) { if (t == e.type()) { return e; } else if (t.can_represent(e.type())) { return cast(t, e); } if (const Cast *c = e.as<Cast>()) { if (t.can_represent(c->value.type())) { // We can recurse into widening casts. return lossless_cast(t, c->value); } else { return Expr(); } } if (const Broadcast *b = e.as<Broadcast>()) { Expr v = lossless_cast(t.element_of(), b->value); if (v.defined()) { return Broadcast::make(v, b->lanes); } else { return Expr(); } } if (const IntImm *i = e.as<IntImm>()) { if (t.can_represent(i->value)) { return make_const(t, i->value); } else { return Expr(); } } if (const UIntImm *i = e.as<UIntImm>()) { if (t.can_represent(i->value)) { return make_const(t, i->value); } else { return Expr(); } } if (const FloatImm *f = e.as<FloatImm>()) { if (t.can_represent(f->value)) { return make_const(t, f->value); } else { return Expr(); } } return Expr(); }
// Factor a float into 2^exponent * reduced, where reduced is between 0.75 and 1.5 void range_reduce_log(Expr input, Expr *reduced, Expr *exponent) { Type type = input.type(); Type int_type = Int(32, type.lanes()); Expr int_version = reinterpret(int_type, input); // single precision = SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM // exponent mask = 0111 1111 1000 0000 0000 0000 0000 0000 // 0x7 0xF 0x8 0x0 0x0 0x0 0x0 0x0 // non-exponent = 1000 0000 0111 1111 1111 1111 1111 1111 // = 0x8 0x0 0x7 0xF 0xF 0xF 0xF 0xF Expr non_exponent_mask = make_const(int_type, 0x807fffff); // Extract a version with no exponent (between 1.0 and 2.0) Expr no_exponent = int_version & non_exponent_mask; // If > 1.5, we want to divide by two, to normalize back into the // range (0.75, 1.5). We can detect this by sniffing the high bit // of the mantissa. Expr new_exponent = no_exponent >> 22; Expr new_biased_exponent = 127 - new_exponent; Expr old_biased_exponent = int_version >> 23; *exponent = old_biased_exponent - new_biased_exponent; Expr blended = (int_version & non_exponent_mask) | (new_biased_exponent << 23); *reduced = reinterpret(type, blended); }
Expr make_zero(Type t) { if (t.is_handle()) { return reinterpret(t, make_zero(UInt(64))); } else { return make_const(t, 0); } }
Expr make_zero(Type t) { if (t.is_handle()) { return Call::make(t, Call::null_handle, std::vector<Expr>(), Call::PureIntrinsic); } else { return make_const(t, 0); } }
Expr make_const(Type t, int val) { if (t == Int(32)) return val; if (t == Float(32)) return (float)val; if (t.is_vector()) { return new Broadcast(make_const(t.element_of(), val), t.width); } return new Cast(t, val); }
void bind_static_axis_aligned_box_library (Environment& environment) { InvokerRegistry aabox_box_corner_lib = environment.CreateLibrary (BV_STATIC_AXIS_ALIGNED_BOX_CORNER_LIBRARY); aabox_box_corner_lib.Register ("get_nxnynz", make_const (box_corner_nxnynz)); aabox_box_corner_lib.Register ("get_pxnynz", make_const (box_corner_pxnynz)); aabox_box_corner_lib.Register ("get_nxpynz", make_const (box_corner_nxpynz)); aabox_box_corner_lib.Register ("get_pxpynz", make_const (box_corner_pxpynz)); aabox_box_corner_lib.Register ("get_nxnypz", make_const (box_corner_nxnypz)); aabox_box_corner_lib.Register ("get_pxnypz", make_const (box_corner_pxnypz)); aabox_box_corner_lib.Register ("get_nxpypz", make_const (box_corner_nxpypz)); aabox_box_corner_lib.Register ("get_pxpypz", make_const (box_corner_pxpypz)); }
void check_representable(Type dst, int64_t x) { if (dst.is_handle()) { user_assert(dst.can_represent(x)) << "Integer constant " << x << " will be implicitly coerced to type " << dst << ", but Halide does not support pointer arithmetic.\n"; } else { user_assert(dst.can_represent(x)) << "Integer constant " << x << " will be implicitly coerced to type " << dst << ", which changes its value to " << make_const(dst, x) << ".\n"; } }
Expr make_two(Type t) { return make_const(t, 2); }
Expr make_one(Type t) { return make_const(t, 1); }
Expr make_bool(bool val, int w) { return make_const(UInt(1, w), val); }
Expr BufferBuilder::build() const { std::vector<Expr> args(10); if (buffer_memory.defined()) { args[0] = buffer_memory; } else { args[0] = Call::make(type_of<struct halide_buffer_t *>(), Call::alloca, {(int)sizeof(halide_buffer_t)}, Call::Intrinsic); } std::string shape_var_name = unique_name('t'); Expr shape_var = Variable::make(type_of<halide_dimension_t *>(), shape_var_name); if (shape_memory.defined()) { args[1] = shape_memory; } else if (dimensions == 0) { args[1] = make_zero(type_of<halide_dimension_t *>()); } else { args[1] = shape_var; } if (host.defined()) { args[2] = host; } else { args[2] = make_zero(type_of<void *>()); } if (device.defined()) { args[3] = device; } else { args[3] = make_zero(UInt(64)); } if (device_interface.defined()) { args[4] = device_interface; } else { args[4] = make_zero(type_of<struct halide_device_interface_t *>()); } args[5] = (int)type.code(); args[6] = type.bits(); args[7] = dimensions; std::vector<Expr> shape; for (size_t i = 0; i < (size_t)dimensions; i++) { if (i < mins.size()) { shape.push_back(mins[i]); } else { shape.push_back(0); } if (i < extents.size()) { shape.push_back(extents[i]); } else { shape.push_back(0); } if (i < strides.size()) { shape.push_back(strides[i]); } else { shape.push_back(0); } // per-dimension flags, currently unused. shape.push_back(0); } for (const Expr &e : shape) { internal_assert(e.type() == Int(32)) << "Buffer shape fields must be int32_t:" << e << "\n"; } Expr shape_arg = Call::make(type_of<halide_dimension_t *>(), Call::make_struct, shape, Call::Intrinsic); if (shape_memory.defined()) { args[8] = shape_arg; } else if (dimensions == 0) { args[8] = make_zero(type_of<halide_dimension_t *>()); } else { args[8] = shape_var; } Expr flags = make_zero(UInt(64)); if (host_dirty.defined()) { flags = select(host_dirty, make_const(UInt(64), halide_buffer_flag_host_dirty), make_zero(UInt(64))); } if (device_dirty.defined()) { flags = flags | select(device_dirty, make_const(UInt(64), halide_buffer_flag_device_dirty), make_zero(UInt(64))); } args[9] = flags; Expr e = Call::make(type_of<struct halide_buffer_t *>(), Call::buffer_init, args, Call::Extern); if (!shape_memory.defined() && dimensions != 0) { e = Let::make(shape_var_name, shape_arg, e); } return e; }
Expr make_zero(Type t) { return make_const(t, 0); }
void halide_pipeline_to_c( Stmt s, const vector<Function> &outputs, const map<string, Function> &env, const map<string, vector<int32_t>> &output_buffers_size, const string &func) { std::ostringstream stream; stream << "tiramisu::function " << func << "(\"" << func << "\")" << ";\n"; set<string> output_buffers; Scope<Expr> scope; std::ostringstream output_buffers_stream; output_buffers_stream << "{"; // Allocate the output buffers for (size_t k = 0; k < outputs.size(); ++k) { const Function &f = outputs[k]; const auto iter = output_buffers_size.find(f.name()); assert(iter != output_buffers_size.end()); assert(iter->second.size() == f.args().size()); std::ostringstream sizes; sizes << "{"; for (size_t i = 0; i < iter->second.size(); ++i) { sizes << "tiramisu::expr(" << iter->second[i] << ")"; scope.push(f.name() + "_min_" + std::to_string(i), make_const(Int(32), 0)); scope.push(f.name() + "_extent_" + std::to_string(i), make_const(Int(32), iter->second[i])); if (i != iter->second.size() - 1) { sizes << ", "; } } sizes << "}"; string buffer_name = "buff_" + f.name(); // TODO(psuriana): should make the buffer data type variable instead of uint8_t always stream << "tiramisu::buffer " << buffer_name << "(\"" << buffer_name << "\", " << f.args().size() << ", " << sizes.str() << ", tiramisu::p_uint8, NULL, tiramisu::a_output, " << "&" << func << ");\n"; output_buffers.insert(buffer_name); output_buffers_stream << "&" << buffer_name; if (k != outputs.size() - 1) { output_buffers_stream << ", "; } } output_buffers_stream << "}"; HalideToC converter(scope, outputs, env, output_buffers, func, stream); converter.print(s); stream << func << ".set_arguments(" << output_buffers_stream.str() << ");\n"; stream << func << ".gen_isl_ast();\n"; stream << func << ".gen_halide_stmt();\n"; stream << func << ".dump_halide_stmt();\n"; stream << func << ".gen_halide_obj(\"build/generated_fct_test_06.o\");\n"; std::cout << "\nTiramisu C output:\n\n" << stream.str() << "\n"; }
//Регистрация статических переменных void bind_static_media_player_library (Environment& environment) { InvokerRegistry player_state_lib = environment.CreateLibrary (MEDIA_STATIC_PLAYER_STATE_LIBRARY); InvokerRegistry player_repeat_mode_lib = environment.CreateLibrary (MEDIA_STATIC_PLAYER_REPEAT_MODE_LIBRARY); InvokerRegistry player_event_lib = environment.CreateLibrary (MEDIA_STATIC_PLAYER_EVENT_LIBRARY); player_state_lib.Register ("get_Stopped", make_const (MediaPlayerState_Stopped)); player_state_lib.Register ("get_Playing", make_const (MediaPlayerState_Playing)); player_state_lib.Register ("get_Paused", make_const (MediaPlayerState_Paused)); player_repeat_mode_lib.Register ("get_Off", make_const (MediaPlayerRepeatMode_Off)); player_repeat_mode_lib.Register ("get_Last", make_const (MediaPlayerRepeatMode_Last)); player_repeat_mode_lib.Register ("get_All", make_const (MediaPlayerRepeatMode_All)); player_event_lib.Register ("get_OnChangeName", make_const (MediaPlayerEvent_OnChangeName)); player_event_lib.Register ("get_OnChangeTarget", make_const (MediaPlayerEvent_OnChangeTarget)); player_event_lib.Register ("get_OnChangePlaylist", make_const (MediaPlayerEvent_OnChangePlaylist)); player_event_lib.Register ("get_OnChangeTrack", make_const (MediaPlayerEvent_OnChangeTrack)); player_event_lib.Register ("get_OnChangePlayback", make_const (MediaPlayerEvent_OnChangePlayback)); player_event_lib.Register ("get_OnChangeVolume", make_const (MediaPlayerEvent_OnChangeVolume)); player_event_lib.Register ("get_OnChangeRepeatMode", make_const (MediaPlayerEvent_OnChangeRepeatMode)); }