Tiramisuは、対象としている関数を Halideと同様に オブジェクトファイルに生成します。
その生成したオブジェクトファイルをリンクして使います。
その生成したオブジェクトファイルをリンクして使います。
では、どんな感じでオブジェクトファイルを生成しているのでしょうか?
テストプログラム(tests/test_01.cpp)の後半分を以下に示します。
function0.set_arguments({&buf0}); function0.gen_time_space_domain(); // gen_isl_astにて、ISLのAST(Abstruct Syntax Tree)を生成します function0.gen_isl_ast(); // ISLのASTからHalideのStatementに変換します function0.gen_halide_stmt(); // HalideのStatementからオブジェクトファイルを生成します function0.gen_halide_obj("build/generated_fct_test_01.o");
gen_halide_objでは、
// ここで、Lowering して Halide::Module m = lower_halide_pipeline(this->get_name(), target, fct_arguments, Halide::Internal::LoweredFunc::External, this->get_halide_stmt()); // オブジェクトファイルを生成 m.compile(Halide::Outputs().object(obj_file_name)); // ヘッダファイルを生成 m.compile(Halide::Outputs().c_header(obj_file_name + ".h"));
lower_halide_pipelineでは、以下のような Lowering を行っています。
デバッグ文等およびGPU関連コードは、削除しています。
デバッグ文等およびGPU関連コードは、削除しています。
Module result_module(pipeline_name, t); map<string, Function> env; s = sliding_window(s, env); s = remove_undef(s); s = uniquify_variable_names(s); s = storage_folding(s, env); s = simplify(s, false); s = skip_stages(s, order); s = unpack_buffers(s); s = simplify(s); s = unify_duplicate_lets(s); s = remove_trivial_for_loops(s); s = unroll_loops(s); s = simplify(s); s = vectorize_loops(s, t); s = simplify(s); s = rewrite_interleavings(s); s = simplify(s); s = partition_loops(s); s = simplify(s); s = trim_no_ops(s); s = inject_early_frees(s); s = common_subexpression_elimination(s); s = remove_dead_allocations(s); s = remove_trivial_for_loops(s); s = simplify(s); s = inject_hexagon_rpc(s, t, result_module); vector<Argument> public_args = args; class StrengthenRefs : public IRMutator { using IRMutator::visit; void visit(const Call *c) { IRMutator::visit(c); c = expr.as<Call>(); //internal_assert(c); if (c->func.defined()) { FunctionPtr ptr = c->func; ptr.strengthen(); expr = Call::make(c->type, c->name, c->args, c->call_type, ptr, c->value_index, c->image, c->param); } } }; s = StrengthenRefs().mutate(s);
ここまでで、Lowering は終了です。
LoweredFunc にて、関数に変換。。。LoweredFunc は、Halide内で定義。
LoweredFunc にて、関数に変換。。。LoweredFunc は、Halide内で定義。
LoweredFunc main_func(pipeline_name, public_args, s, linkage_type); result_module.append(main_func); if (!t.has_feature(Target::JIT)) { add_legacy_wrapper(result_module, main_func); } wrap_legacy_extern_stages(result_module); return result_module;
Tiramisu: A Code Optimization Framework for High Performance Systemsの7.1 Halide to Tiramisuの以下の部分
For CPU code generation, we convert Layer IV Tiramisu IR into low-level transformed Halide IR (bypassing all lowering in the original Halide compiler) and feed it into the Halide LLVM code generator.
CPUコード生成では、Layer IVのTiramisu IRをローレベルに変換したHalide IRにコンバートする。
この時、オリジナルのHalideコンパイラのすべてのLoweringをバイバスします。
生成したHalide IRは、Halideのコード生成に供給します。
と。。。
この時、オリジナルのHalideコンパイラのすべてのLoweringをバイバスします。
生成したHalide IRは、Halideのコード生成に供給します。
と。。。