EDGE * GRAPH::remove_edge(EDGE * e) { IS_TRUE(m_pool != NULL, ("not yet initialized.")); if (e == NULL) return NULL; VERTEX * from = EDGE_from(e); VERTEX * to = EDGE_to(e); //remove out of out-list of 'from' EDGE_C * el = VERTEX_out_list(from); while (el != NULL) { if (EC_edge(el) == e) { break; } el = EC_next(el); } IS_TRUE(el != NULL, ("can not find out-edge, it is illegal graph")); remove(&VERTEX_out_list(from), el); m_el_free_list.add_free_elem(el); //remove out of in-list of 'to' el = VERTEX_in_list(to); while (el != NULL) { if (EC_edge(el) == e) break; el = EC_next(el); } IS_TRUE(el != NULL, ("can not find in-edge, it is illegal graph")); remove(&VERTEX_in_list(to), el); m_el_free_list.add_free_elem(el); //remove edge out of edge-hash e = m_edges.removed(e); m_e_free_list.add_free_elem(e); return e; }
EDGE * GRAPH::get_edge(VERTEX const* from, VERTEX const* to) { IS_TRUE(m_pool != NULL, ("not yet initialized.")); if (from == NULL || to == NULL) return NULL; EDGE_C * el = VERTEX_out_list(from); while (el != NULL) { EDGE * e = EC_edge(el); if (EDGE_from(e) == from && EDGE_to(e) == to) { return e; } if (!m_is_direction && (EDGE_from(e) == to && EDGE_to(e) == from)) { return e; } el = EC_next(el); } if (!m_is_direction) { EDGE_C * el = VERTEX_out_list(to); while (el != NULL) { EDGE * e = EC_edge(el); if (EDGE_from(e) == to && EDGE_to(e) == from) { return e; } el = EC_next(el); } } return NULL; }
//Add 'e' into out-edges of 'vex' void GRAPH::add_out_list(VERTEX * vex, EDGE * e) { IS_TRUE(m_pool != NULL, ("not yet initialized.")); if (vex == NULL || e == NULL)return; EDGE_C * el = VERTEX_out_list(vex); while (el != NULL) { if (EC_edge(el) == e) return; el = EC_next(el); } el = new_ec(e); add_next(&VERTEX_out_list(vex), el); }
bool GRAPH::is_equal(GRAPH & g) { if (get_vertex_num() != g.get_vertex_num() || get_edge_num() != g.get_edge_num()) { return false; } BITSET vs; INT c; for (VERTEX * v1 = get_first_vertex(c); v1 != NULL; v1 = get_next_vertex(c)) { VERTEX * v2 = g.get_vertex(VERTEX_id(v1)); if (v2 == NULL) { return false; } vs.clean(); EDGE_C * el = VERTEX_out_list(v1); EDGE * e = NULL; UINT v1_succ_n = 0; if (el == NULL) { if (VERTEX_out_list(v2) != NULL) { return false; } continue; } for (e = EC_edge(el); e != NULL; el = EC_next(el), e = el ? EC_edge(el) : NULL) { vs.bunion(VERTEX_id(EDGE_to(e))); v1_succ_n++; } UINT v2_succ_n = 0; el = VERTEX_out_list(v2); for (e = EC_edge(el); e != NULL; el = EC_next(el), e = el ? EC_edge(el) : NULL) { v2_succ_n++; if (!vs.is_contain(VERTEX_id(EDGE_to(e)))) { return false; } } if (v1_succ_n != v2_succ_n) { return false; } } return true; }
void DGRAPH::sort_dom_tree_in_postorder(IN GRAPH & dom_tree, IN VERTEX * root, OUT LIST<VERTEX*> & lst) { IS_TRUE0(root); BITSET is_visited; //Find the leaf node. VERTEX * v; SSTACK<VERTEX*> stk; stk.push(root); while ((v = stk.pop()) != NULL) { //Visit children first. EDGE_C * el = VERTEX_out_list(v); bool find = false; //find unvisited kid. VERTEX * succ; while (el != NULL) { succ = EDGE_to(EC_edge(el)); if (!is_visited.is_contain(VERTEX_id(succ))) { stk.push(v); stk.push(succ); find = true; break; } el = EC_next(el); } if (!find) { is_visited.bunion(VERTEX_id(v)); //The only place to process vertex. lst.append_tail(v); } } }
/* Sort vertice by rporder, and record to vlst in incremental order. */ void DGRAPH::compute_rpo_norec(IN VERTEX * root, OUT LIST<VERTEX*> & vlst) { BITSET is_visited; SSTACK<VERTEX*> stk; stk.push(root); VERTEX * v; while ((v = stk.pop()) != NULL) { is_visited.bunion(VERTEX_id(v)); EDGE_C * el = VERTEX_out_list(v); bool find = false; //find unvisited kid. while (el != NULL) { VERTEX * succ = EDGE_to(EC_edge(el)); if (!is_visited.is_contain(VERTEX_id(succ))) { stk.push(v); stk.push(succ); find = true; break; } el = EC_next(el); } if (!find) { vlst.append_head(v); } } }
void DGRAPH::sort_dom_tree_in_preorder(IN GRAPH & dom_tree, IN VERTEX * root, OUT LIST<VERTEX*> & lst) { IS_TRUE0(root); BITSET is_visited; is_visited.bunion(VERTEX_id(root)); lst.append_tail(root); VERTEX * v; SSTACK<VERTEX*> stk; stk.push(root); while ((v = stk.pop()) != NULL) { if (!is_visited.is_contain(VERTEX_id(v))) { is_visited.bunion(VERTEX_id(v)); stk.push(v); //The only place to process vertex. lst.append_tail(v); } //Visit children. EDGE_C * el = VERTEX_out_list(v); VERTEX * succ; while (el != NULL) { succ = EDGE_to(EC_edge(el)); if (!is_visited.is_contain(VERTEX_id(succ))) { stk.push(v); stk.push(succ); break; } el = EC_next(el); } } }
//Before removing bb, revising phi opnd if there are phis //in one of bb's successors. void IRBB::removeSuccessorPhiOpnd(CFG<IRBB, IR> * cfg) { IR_CFG * ircfg = (IR_CFG*)cfg; Region * ru = ircfg->get_ru(); Vertex * vex = ircfg->get_vertex(BB_id(this)); ASSERT0(vex); for (EdgeC * out = VERTEX_out_list(vex); out != NULL; out = EC_next(out)) { Vertex * succ_vex = EDGE_to(EC_edge(out)); IRBB * succ = ircfg->get_bb(VERTEX_id(succ_vex)); ASSERT0(succ); UINT const pos = ircfg->WhichPred(this, succ); for (IR * ir = BB_first_ir(succ); ir != NULL; ir = BB_next_ir(succ)) { if (!ir->is_phi()) { break; } ASSERT0(cnt_list(PHI_opnd_list(ir)) == cnt_list(VERTEX_in_list(succ_vex))); IR * opnd; UINT lpos = pos; for (opnd = PHI_opnd_list(ir); lpos != 0; opnd = IR_next(opnd)) { ASSERT0(opnd); lpos--; } opnd->removeSSAUse(); ((CPhi*)ir)->removeOpnd(opnd); ru->freeIRTree(opnd); } } }
//Before removing bb or change bb successor, //you need remove the related PHI operand if BB successor has PHI stmt. void IRBB::removeSuccessorPhiOpnd(CFG<IRBB, IR> * cfg) { Vertex * vex = cfg->get_vertex(BB_id(this)); ASSERT0(vex); for (EdgeC * out = VERTEX_out_list(vex); out != NULL; out = EC_next(out)) { IRBB * succ = ((IR_CFG*)cfg)->get_bb(VERTEX_id(EDGE_to(EC_edge(out)))); ASSERT0(succ); removeSuccessorDesignatePhiOpnd(cfg, succ); } }
void CDG::get_cd_succs(UINT id, OUT LIST<VERTEX*> & lst) { VERTEX * v = get_vertex(id); IS_TRUE0(v != NULL); EDGE_C * out = VERTEX_out_list(v); while (out != NULL) { VERTEX * succ = EDGE_to(EC_edge(out)); lst.append_tail(succ); out = EC_next(out); } }
//Return true if 'succ' is successor of 'v'. bool GRAPH::is_succ(VERTEX * v, VERTEX * succ) { EDGE_C * e = VERTEX_out_list(v); while (e != NULL) { if (EDGE_to(EC_edge(e)) == succ) { return true; } e = EC_next(e); } return false; }
bool CDG::is_only_cd_self(UINT id) { VERTEX * v = get_vertex(id); IS_TRUE0(v != NULL); EDGE_C * out = VERTEX_out_list(v); while (out != NULL) { VERTEX * succ = EDGE_to(EC_edge(out)); if (succ != v) return false; out = EC_next(out); } return true; }
UINT GRAPH::get_out_degree(VERTEX const* vex) const { IS_TRUE(m_pool != NULL, ("not yet initialized.")); if (vex == NULL) return 0; UINT degree = 0; EDGE_C * el = VERTEX_out_list(vex); while (el != NULL) { degree++; el = EC_next(el); } return degree; }
void DGRAPH::_remove_unreach_node(UINT id, BITSET & visited) { visited.bunion(id); VERTEX * vex = get_vertex(id); EDGE_C * el = VERTEX_out_list(vex); while (el != NULL) { UINT succ = VERTEX_id(EDGE_to(EC_edge(el))); if (!visited.is_contain(succ)) { _remove_unreach_node(succ, visited); } el = EC_next(el); } }
//Return true if b is control dependent on a. bool CDG::is_cd(UINT a, UINT b) { IS_TRUE0(get_vertex(b)); VERTEX * v = get_vertex(a); IS_TRUE0(v != NULL); EDGE_C * out = VERTEX_out_list(v); while (out != NULL) { if (VERTEX_id(EDGE_to(EC_edge(out))) == b) { return true; } out = EC_next(out); } return false; }
//Return true if one of bb's successor has a phi. bool IRBB::successorHasPhi(CFG<IRBB, IR> * cfg) { Vertex * vex = cfg->get_vertex(BB_id(this)); ASSERT0(vex); for (EdgeC * out = VERTEX_out_list(vex); out != NULL; out = EC_next(out)) { Vertex * succ_vex = EDGE_to(EC_edge(out)); IRBB * succ = cfg->get_bb(VERTEX_id(succ_vex)); ASSERT0(succ); for (IR * ir = BB_first_ir(succ); ir != NULL; ir = BB_next_ir(succ)) { if (ir->is_phi()) { return true; } } } return false; }
//'order_buf': record the bfs-order for each vertex. void DGRAPH::sort_in_bfs_order(SVECTOR<UINT> & order_buf, GRAPH & domtree, VERTEX * root) { LIST<VERTEX*> worklst; worklst.append_tail(root); UINT order = 1; while (worklst.get_elem_count() > 0) { VERTEX * sv = worklst.remove_head(); order_buf.set(VERTEX_id(sv), order); order++; EDGE_C * el = VERTEX_out_list(sv); while (el != NULL) { VERTEX * to = EDGE_to(EC_edge(el)); worklst.append_tail(to); el = EC_next(el); } } }
/* Find the bb that is the start of the unqiue backedge of loop. BB1: loop start bb BB2: body start bb BB3: goto loop start bb BB2 is the loop header fallthrough bb. */ bool find_loop_header_two_succ_bb(LI<IR_BB> const* li, IR_CFG * cfg, UINT * succ1, UINT * succ2) { IS_TRUE0(li && cfg && succ1 && succ2); IR_BB * head = LI_loop_head(li); VERTEX * headvex = cfg->get_vertex(IR_BB_id(head)); if (cfg->get_out_degree(headvex) != 2) { //Not natural loop. return false; } EDGE_C const* ec = VERTEX_out_list(headvex); IS_TRUE0(ec && EC_next(ec)); *succ1 = VERTEX_id(EDGE_to(EC_edge(ec))); *succ2 = VERTEX_id(EDGE_to(EC_edge(EC_next(ec)))); return true; }
//Duplicate and add an operand that indicated by opnd_pos at phi stmt //in one of bb's successors. void IRBB::dupSuccessorPhiOpnd(CFG<IRBB, IR> * cfg, Region * ru, UINT opnd_pos) { IR_CFG * ircfg = (IR_CFG*)cfg; Vertex * vex = ircfg->get_vertex(BB_id(this)); ASSERT0(vex); for (EdgeC * out = VERTEX_out_list(vex); out != NULL; out = EC_next(out)) { Vertex * succ_vex = EDGE_to(EC_edge(out)); IRBB * succ = ircfg->get_bb(VERTEX_id(succ_vex)); ASSERT0(succ); for (IR * ir = BB_first_ir(succ); ir != NULL; ir = BB_next_ir(succ)) { if (!ir->is_phi()) { break; } ASSERT0(cnt_list(PHI_opnd_list(ir)) >= opnd_pos); IR * opnd; UINT lpos = opnd_pos; for (opnd = PHI_opnd_list(ir); lpos != 0; opnd = opnd->get_next()) { ASSERT0(opnd); lpos--; } IR * newopnd = ru->dupIRTree(opnd); if (opnd->is_read_pr()) { newopnd->copyRef(opnd, ru); ASSERT0(PR_ssainfo(opnd)); PR_ssainfo(newopnd) = PR_ssainfo(opnd); SSA_uses(PR_ssainfo(newopnd)).append(newopnd); } ((CPhi*)ir)->addOpnd(newopnd); } } }
//Is there exist a path connect 'from' and 'to'. bool GRAPH::is_reachable(VERTEX * from, VERTEX * to) { IS_TRUE(m_pool != NULL, ("not yet initialized.")); IS_TRUE(from != NULL && to != NULL, ("parameters cannot be NULL")); EDGE_C * el = VERTEX_out_list(from); EDGE * e = NULL; if (el == NULL) return false; //Walk through each succ of 'from' for (e = EC_edge(el); e != NULL; el = EC_next(el), e = el ? EC_edge(el):NULL) { VERTEX * succ = EDGE_to(e); if (VERTEX_id(succ) == VERTEX_id(to)) { return true; } else { if (is_reachable(succ, to)) { return true; } } } //end for return false; }
VERTEX * GRAPH::remove_vertex(VERTEX * vex) { IS_TRUE(m_pool != NULL, ("not yet initialized.")); if (vex == NULL) return NULL; EDGE_C * el = VERTEX_out_list(vex); //remove all out-edge while (el != NULL) { EDGE_C * tmp = el; el = EC_next(el); remove_edge(EC_edge(tmp)); } //remove all in-edge el = VERTEX_in_list(vex); while (el != NULL) { EDGE_C * tmp = el; el = EC_next(el); remove_edge(EC_edge(tmp)); } vex = m_vertexs.removed(vex); m_v_free_list.add_free_elem(vex); return vex; }
/* Sort graph vertices in topological order. 'vex_vec': record nodes with topological sort. NOTE: current graph will be empty at function return. If one need to keep the graph unchanged, clone graph as a tmpgraph and operate on the tmpgraph. e.g: GRAPH org; And org must be unchanged, GRAPH tmp(org); tmp.sort_in_toplog_order(...) */ bool GRAPH::sort_in_toplog_order(OUT SVECTOR<UINT> & vex_vec, bool is_topdown) { IS_TRUE(m_pool != NULL, ("Graph still not yet initialize.")); if (get_vertex_num() == 0) { return true; } LIST<VERTEX*> vlst; UINT pos = 0; vex_vec.clean(); vex_vec.grow(get_vertex_num()); while (this->get_vertex_num() != 0) { vlst.clean(); VERTEX * v; INT c; for (v = this->get_first_vertex(c); v != NULL; v = this->get_next_vertex(c)) { if (is_topdown) { if (VERTEX_in_list(v) == NULL) { vlst.append_tail(v); } } else if (VERTEX_out_list(v) == NULL) { vlst.append_tail(v); } } if (vlst.get_elem_count() == 0 && this->get_vertex_num() != 0) { IS_TRUE(0, ("exist cycle in graph")); return false; } for (v = vlst.get_head(); v != NULL; v = vlst.get_next()) { vex_vec.set(pos, VERTEX_id(v)); pos++; this->remove_vertex(v); } } return true; }
/* Return all neighbors of 'vid' on graph. Return false if 'vid' is not on graph. */ bool GRAPH::get_neighbor_list(OUT LIST<UINT> & ni_list, IN UINT vid) { IS_TRUE(m_pool != NULL, ("not yet initialized.")); UINT degree = 0; VERTEX * vex = m_vertexs.find(vid); if (vex == NULL) return false; EDGE_C * el = VERTEX_in_list(vex); while (el != NULL) { INT v = VERTEX_id(EDGE_from(EC_edge(el))); if (!ni_list.find(v)) { ni_list.append_tail(v); } el = EC_next(el); } el = VERTEX_out_list(vex); while (el != NULL) { INT v = VERTEX_id(EDGE_to(EC_edge(el))); if (!ni_list.find(v)) { ni_list.append_tail(v); } el = EC_next(el); } return true; }
//Remove all edges between v1 and v2. void GRAPH::remove_edges_between(VERTEX * v1, VERTEX * v2) { EDGE_C * ec = VERTEX_out_list(v1); while (ec != NULL) { EDGE_C * next = EC_next(ec); EDGE * e = EC_edge(ec); if ((EDGE_from(e) == v1 && EDGE_to(e) == v2) || (EDGE_from(e) == v2 && EDGE_to(e) == v1)) { remove_edge(e); } ec = next; } ec = VERTEX_in_list(v1); while (ec != NULL) { EDGE_C * next = EC_next(ec); EDGE * e = EC_edge(ec); if ((EDGE_from(e) == v1 && EDGE_to(e) == v2) || (EDGE_from(e) == v2 && EDGE_to(e) == v1)) { remove_edge(e); } ec = next; } }
void PRDF::computeGlobal() { ASSERT0(BB_is_entry(m_cfg->get_entry_list()->get_head()) && m_cfg->get_entry_list()->get_elem_count() == 1); //Rpo should be available. List<IRBB*> * vlst = m_cfg->get_bblist_in_rpo(); ASSERT0(vlst->get_elem_count() == m_ru->get_bb_list()->get_elem_count()); C<IRBB*> * ct; for (vlst->get_head(&ct); ct != vlst->end(); ct = vlst->get_next(ct)) { IRBB * bb = ct->val(); ASSERT0(bb); UINT bbid = BB_id(bb); get_livein(bbid)->clean(m_sbs_mgr); get_liveout(bbid)->clean(m_sbs_mgr); } bool change; UINT count = 0; UINT thres = 1000; DefSBitSetCore news; do { change = false; C<IRBB*> * ct; for (vlst->get_tail(&ct); ct != vlst->end(); ct = vlst->get_prev(ct)) { IRBB * bb = ct->val(); ASSERT0(bb); UINT bbid = BB_id(bb); DefSBitSetCore * out = m_liveout.get(bbid); news.copy(*out, m_sbs_mgr); ASSERT0(m_def.get(bbid)); news.diff(*m_def.get(bbid), m_sbs_mgr); news.bunion(*m_use.get(bbid), m_sbs_mgr); m_livein.get(bbid)->copy(news, m_sbs_mgr); EdgeC const* ec = VERTEX_out_list(m_cfg->get_vertex(BB_id(bb))); if (ec != NULL) { INT succ = VERTEX_id(EDGE_to(EC_edge(ec))); news.copy(*m_livein.get(succ), m_sbs_mgr); ec = EC_next(ec); for (; ec != NULL; ec = EC_next(ec)) { news.bunion(*m_livein.get(succ), m_sbs_mgr); } if (!out->is_equal(news)) { out->copy(news, m_sbs_mgr); change = true; } } } count++; } while (change && count < thres); ASSERT(!change, ("result of equation is convergent slowly")); news.clean(m_sbs_mgr); #ifdef STATISTIC_PRDF g_max_times = MAX(g_max_times, count); FILE * h = fopen("prdf.sat.dump", "a+"); fprintf(h, "\n%s run %u times, maxtimes %u", m_ru->get_ru_name(), count, g_max_times); fclose(h); #endif }
//Vertexs should have been sorted in topological order. //And we access them by reverse-topological order. bool DGRAPH::compute_pdom(IN LIST<VERTEX*> * vlst, BITSET const* uni) { LIST<VERTEX*> tmpvlst; LIST<VERTEX*> * pvlst = &tmpvlst; if (vlst != NULL) { pvlst = vlst; } else { INT c; for (VERTEX * v = get_first_vertex(c); v != NULL; v = get_next_vertex(c)) { pvlst->append_tail(v); } } BITSET const* luni = NULL; if (uni != NULL) { luni = uni; } else { BITSET * x = new BITSET(); for (VERTEX * u = pvlst->get_head(); u != NULL; u = pvlst->get_next()) { x->bunion(VERTEX_id(u)); } luni = x; } //Initialize pdom for each bb for (VERTEX * v = pvlst->get_head(); v != NULL; v = pvlst->get_next()) { if (is_graph_exit(v)) { BITSET * pdom = get_pdom_set(v); pdom->clean(); pdom->bunion(VERTEX_id(v)); } else { get_pdom_set(v)->copy(*luni); } } /* PDOM[exit] = {exit} PDOM[n] = {n} U {¡É(PDOM[succ] of each succ of n)} */ bool change = true; BITSET tmp; UINT count = 0; while (change && count < 10) { count++; change = false; for (VERTEX * v = pvlst->get_head(); v != NULL; v = pvlst->get_next()) { UINT vid = VERTEX_id(v); if (is_graph_exit(v)) { continue; } else { tmp.clean(); //Access each succs EDGE_C * ec = VERTEX_out_list(v); while (ec != NULL) { VERTEX * succ = EDGE_to(EC_edge(ec)); if (ec == VERTEX_out_list(v)) { tmp.copy(*m_pdom_set.get(VERTEX_id(succ))); } else { tmp.intersect(*m_pdom_set.get(VERTEX_id(succ))); } ec = EC_next(ec); } tmp.bunion(vid); BITSET * pdom = m_pdom_set.get(VERTEX_id(v)); if (!pdom->is_equal(tmp)) { pdom->copy(tmp); change = true; } } } //end for }// end while IS_TRUE0(!change); if (uni == NULL && luni != NULL) { delete luni; } return true; }