Graph& Graph::operator*=(const Graph& r) { std::vector<std::size_t> sinks; std::vector<std::size_t> sources; for (std::size_t i = 0; i < nodes_.size(); i++) if (is_sink(i)) sinks.push_back(i); for (std::size_t i = 0; i < r.nodes_.size(); i++) if (r.is_source(i)) { if (r.nodes_[i].type() == Node::XID_TYPE_DUMMY_SOURCE) { for (std::vector<std::size_t>::const_iterator it = r.out_edges_[i].begin(); it != r.out_edges_[i].end(); ++it) vector_push_back_unique(sources, *it); } else { sources.push_back(i); } } std::vector<std::size_t> node_mapping_r; merge_graph(r, node_mapping_r, true); for (std::vector<std::size_t>::const_iterator it_sink = sinks.begin(); it_sink != sinks.end(); ++it_sink) for (std::vector<std::size_t>::const_iterator it_source = sources.begin(); it_source != sources.end(); ++it_source) add_edge(*it_sink, node_mapping_r[*it_source]); return *this; }
Graph& Graph::operator+=(const Graph& r) { std::vector<std::size_t> node_mapping_r; merge_graph(r, node_mapping_r); return *this; }
/* Drives the overall inlining process. */ void MVM_spesh_inline(MVMThreadContext *tc, MVMSpeshGraph *inliner, MVMSpeshCallInfo *call_info, MVMSpeshBB *invoke_bb, MVMSpeshIns *invoke_ins, MVMSpeshGraph *inlinee, MVMCode *inlinee_code) { /* Merge inlinee's graph into the inliner. */ merge_graph(tc, inliner, inlinee, inlinee_code, invoke_ins); /* If we're profiling, note it's an inline. */ if (inlinee->entry->linear_next->first_ins->info->opcode == MVM_OP_prof_enterspesh) { MVMSpeshIns *profenter = inlinee->entry->linear_next->first_ins; profenter->info = MVM_op_get_op(MVM_OP_prof_enterinline); profenter->operands = MVM_spesh_alloc(tc, inliner, sizeof(MVMSpeshOperand)); profenter->operands[0].lit_i16 = MVM_spesh_add_spesh_slot(tc, inliner, (MVMCollectable *)inlinee->sf); } /* Re-write returns to a set and goto. */ rewrite_returns(tc, inliner, inlinee, invoke_bb, invoke_ins); /* Re-write the argument passing instructions to poke values into the * appropriate slots. */ rewrite_args(tc, inliner, inlinee, invoke_bb, call_info); /* Annotate first and last instruction with inline table annotations. */ annotate_inline_start_end(tc, inliner, inlinee, inliner->num_inlines - 1); /* Finally, turn the invoke instruction into a goto. */ invoke_ins->info = MVM_op_get_op(MVM_OP_goto); invoke_ins->operands[0].ins_bb = inlinee->entry->linear_next; tweak_succ(tc, inliner, invoke_bb, inlinee->entry->linear_next); }