| 77 | } |
| 78 | |
| 79 | void HalideExecutable::execute(JITExecutor* fusion_opr) { |
| 80 | // load func_ptr for current comp node |
| 81 | auto comp_node = fusion_opr->comp_node(); |
| 82 | std::atomic<FunctionHandle*>* func_ptr_ref; |
| 83 | { |
| 84 | MGB_LOCK_GUARD(m_mtx); |
| 85 | func_ptr_ref = &m_cn2func[comp_node]; |
| 86 | } |
| 87 | auto func_ptr = func_ptr_ref->load(); |
| 88 | if (!func_ptr) { |
| 89 | std::pair<std::mutex, FunctionHandle>* func_maker; |
| 90 | { |
| 91 | MGB_LOCK_GUARD(m_mtx); |
| 92 | func_maker = &m_feature_set2func[m_target_trait->features(comp_node)]; |
| 93 | } |
| 94 | |
| 95 | // compile the function |
| 96 | MGB_LOCK_GUARD(func_maker->first); |
| 97 | if (!(func_ptr = func_ptr_ref->load())) { |
| 98 | if (!func_maker->second.execute) { |
| 99 | func_maker->second = compile_and_load(comp_node); |
| 100 | mgb_assert(func_maker->second.execute); |
| 101 | } |
| 102 | func_ptr = &func_maker->second; |
| 103 | func_ptr_ref->store(func_ptr); |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | void* user_context = nullptr; |
| 108 | if (func_ptr->uctx_map) { |
| 109 | MGB_LOCK_GUARD(func_ptr->uctx_map->mtx); |
| 110 | auto&& ptr = func_ptr->uctx_map->cn2uctx[comp_node]; |
| 111 | if (!ptr) { |
| 112 | ptr = m_target_trait->get_user_context(comp_node); |
| 113 | } |
| 114 | user_context = ptr; |
| 115 | } |
| 116 | |
| 117 | invoke(user_context, *func_ptr, fusion_opr->input(), fusion_opr->output(0)); |
| 118 | } |
| 119 | |
| 120 | std::vector<Halide::Argument> HalideExecutable::halide_inputs() const { |
| 121 | std::vector<Argument> args; |