| 29 | /* ================ SubGraph ================ */ |
| 30 | |
| 31 | OperatorNodeBase* SubGraph::Rewriter::auto_replace_outputs(OperatorNodeBase* opr) { |
| 32 | auto&& new_inp = m_opr_new_inp_cache; |
| 33 | new_inp.clear(); |
| 34 | new_inp.reserve(opr->input().size()); |
| 35 | bool has_replaced_inp = false; |
| 36 | |
| 37 | for (auto i : opr->input()) { |
| 38 | auto new_var = get_var(i); |
| 39 | if (new_var != i) { |
| 40 | has_replaced_inp = true; |
| 41 | new_inp.push_back(new_var); |
| 42 | } else { |
| 43 | new_inp.push_back(i); |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | if (has_replaced_inp) { |
| 48 | auto new_opr = serialization::copy_opr_shallow(*opr, new_inp, opr->config()); |
| 49 | auto &&out0 = opr->output(), &&out1 = new_opr->output(); |
| 50 | size_t i = 0; |
| 51 | auto err_msg = [opr, new_opr] { |
| 52 | return ssprintf( |
| 53 | "bad opr copy: src=%s{%s} dst=%s{%s}", opr->cname(), |
| 54 | opr->dyn_typeinfo()->name, new_opr->cname(), |
| 55 | new_opr->dyn_typeinfo()->name); |
| 56 | }; |
| 57 | MGB_MARK_USED_VAR(err_msg); |
| 58 | // opr output size mismatch may be caused by: |
| 59 | // 0) inplace arith optimization (e.g. PowC need an extra workspace) |
| 60 | // 1) other post-insert optimization (e.g. const folding) |
| 61 | // we can't handle only usable_output here, since some output var with |
| 62 | // volatile flag could be the graph's endpoint (e.g. RemoteSend) |
| 63 | for (; i < std::min(out0.size(), out1.size()); ++i) { |
| 64 | bool v0 = out0[i]->contain_flag(VarNode::Flag::VOLATILE_CONTENT), |
| 65 | v1 = out1[i]->contain_flag(VarNode::Flag::VOLATILE_CONTENT); |
| 66 | mgb_assert(v0 == v1, "%s", err_msg().c_str()); |
| 67 | //! rename new var |
| 68 | out1[i]->name(out0[i]->cname()); |
| 69 | auto&& ins = m_varmap.insert({out0[i], {true, nullptr}}); |
| 70 | mgb_assert( |
| 71 | ins.second || ins.first->second.first, |
| 72 | "opr output already replaced"); |
| 73 | // handle repeated call on the same opr |
| 74 | ins.first->second.second = out1[i]; |
| 75 | on_var_replaced(out0[i], out1[i], nullptr); |
| 76 | } |
| 77 | for (; i < out0.size(); ++i) { |
| 78 | mgb_assert( |
| 79 | out0[i]->contain_flag(VarNode::Flag::VOLATILE_CONTENT), "%s", |
| 80 | err_msg().c_str()); |
| 81 | } |
| 82 | for (; i < out1.size(); ++i) { |
| 83 | mgb_assert( |
| 84 | out1[i]->contain_flag(VarNode::Flag::VOLATILE_CONTENT), "%s", |
| 85 | err_msg().c_str()); |
| 86 | } |
| 87 | return new_opr; |
| 88 | } |
no test coverage detected