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; }
EDGE * GRAPH::new_edge(VERTEX * from, VERTEX * to) { IS_TRUE(m_pool != NULL, ("not yet initialized.")); if (from == NULL || to == NULL) return NULL; EDGE teste; VERTEX testfrom, testto; if (m_is_unique) { VERTEX_id(&testfrom) = VERTEX_id(from); VERTEX_id(&testto) = VERTEX_id(to); EDGE_from(&teste) = &testfrom; EDGE_to(&teste) = &testto; if (m_is_direction) { return m_edges.append((ULONG)&teste, NULL); } else { EDGE * e = NULL; if (m_edges.find(&teste, &e)) { IS_TRUE0(e); return e; } //Both check from->to and to->from EDGE_from(&teste) = &testto; EDGE_to(&teste) = &testfrom; return m_edges.append((ULONG)&teste, NULL); } IS_TRUE0(0); } return m_edges.append(new_edge_c(from, to)); }
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; }
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; }
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); } } }
void GRAPH::dump_dot(CHAR const* name) { if (name == NULL) { name = "graph.dot"; } unlink(name); FILE * h = fopen(name, "a+"); IS_TRUE(h, ("%s create failed!!!", name)); fprintf(h, "digraph G {\n"); //Print node INT c; for (VERTEX const* v = m_vertexs.get_first(c); v != NULL; v = m_vertexs.get_next(c)) { fprintf(h, "\nnode%d [shape = Mrecord, label=\"{BB%d}\"];", VERTEX_id(v), VERTEX_id(v)); } //Print edge for (EDGE const* e = m_edges.get_first(c); e != NULL; e = m_edges.get_next(c)) { fprintf(h, "\nnode%d->node%d[label=\"%s\"]", VERTEX_id(EDGE_from(e)), VERTEX_id(EDGE_to(e)), ""); } fprintf(h, "\n}\n"); fclose(h); }
/* 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_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); } } }
//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); } } }
// //START EDGE_HASH // EDGE * EDGE_HASH::create(ULONG v) { EDGE * t = (EDGE*)v; VERTEX * from = m_g->get_vertex(VERTEX_id(EDGE_from(t))); VERTEX * to = m_g->get_vertex(VERTEX_id(EDGE_to(t))); IS_TRUE0(from && to); t = m_g->new_edge_c(from, to); return t; }
//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); } }
/* 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; }
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; }
//Reverse edge direction EDGE * GRAPH::rev_edge(EDGE * e) { IS_TRUE(m_pool != NULL, ("not yet initialized.")); IS_TRUE(m_is_direction, ("graph is indirection")); void * einfo = EDGE_info(e); VERTEX * from = EDGE_from(e); VERTEX * to = EDGE_to(e); remove_edge(e); e = add_edge(VERTEX_id(to), VERTEX_id(from)); EDGE_info(e) = einfo; return e; }
EDGE * GRAPH::new_edge_c(VERTEX * from, VERTEX * to) { EDGE * e = m_e_free_list.get_free_elem(); if (e == NULL) { e = (EDGE*)_xmalloc(sizeof(EDGE)); } EDGE_from(e) = from; EDGE_to(e) = to; add_in_list(to, e); add_out_list(from, e); return e; }
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; }
/*----------------------------------------------------------------------*/ EINDEX add_edge(GRAPH *g, VINDEX from, VINDEX to, void *user) { EINDEX new_edge, e2; MEM_POOL *m = GRAPH_m(g); GR_ASSERT(is_vertex(g,from), "add_edge is_vertex(g, from\n"); GR_ASSERT(is_vertex(g,from), "add_edge is_vertex(g, to\n"); /* are there any free edges? */ if(GRAPH_efree(g) == -1) /* grow the edge list if no free edges */ grow_edge(g); /* get a free edge */ new_edge = GRAPH_efree(g); /* reset the free edge pointer */ GRAPH_efree(g)= EDGE_nfrom(&GRAPH_e_i(g,new_edge)); /* store the user information */ EDGE_user(&GRAPH_e_i(g,new_edge)) = user; /* from vertex is = from */ EDGE_from(&GRAPH_e_i(g,new_edge)) = from; /* to vertex is = to */ EDGE_to(&GRAPH_e_i(g,new_edge)) = to; /* incr. from count for from vertex */ VERTEX_fcnt(&GRAPH_v_i(g,from))++; /* incr. to count for to vertex */ VERTEX_tcnt(&GRAPH_v_i(g,to))++; /* incr. total used edge count */ GRAPH_ecnt(g)++; /* set up the list of from edges for the from vertex */ e2 = VERTEX_from(&GRAPH_v_i(g,from)); EDGE_nfrom(&GRAPH_e_i(g,new_edge)) = e2; VERTEX_from(&GRAPH_v_i(g,from)) = new_edge; /* set up the list of to edges for the to vertex */ e2 = VERTEX_to(&GRAPH_v_i(g,to)); EDGE_nto(&GRAPH_e_i(g,new_edge)) = e2; VERTEX_to(&GRAPH_v_i(g,to)) = new_edge; /* set the recursive edge field to be zero */ EDGE_etype(&GRAPH_e_i(g,new_edge)) = 0; return new_edge; }
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; }
//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; } }
//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; }
/*---------------------------------------------------------------*/ void* get_edge(GRAPH *g, VINDEX from, VINDEX to) { EINDEX e; GR_ASSERT(is_vertex(g, from), "get_edge is_vertex from\n"); GR_ASSERT(is_vertex(g, to), "get_edge is_vertex to\n"); e = VERTEX_from(&GRAPH_v_i(g, from)); while ( e != INVALID_EINDEX ) { if(EDGE_to(&GRAPH_e_i(g,e)) == to) break; e = (EDGE_nfrom(&GRAPH_e_i(g,e))); } return EDGE_user(&GRAPH_e_i(g,e)); }
/*---------------------------------------------------------------*/ int edge_count(GRAPH* g, VINDEX from, VINDEX to) { int count= 0; EINDEX e; GR_ASSERT(is_vertex(g, from), "edge_count is_vertex from\n"); GR_ASSERT(is_vertex(g, to), "edge_count is_vertex to\n"); e = VERTEX_from(&GRAPH_v_i(g, from)); while ( e != INVALID_EINDEX ) { if(EDGE_to(&GRAPH_e_i(g,e)) == to) ++count; e = (EDGE_nfrom(&GRAPH_e_i(g,e))); } return count; }
//'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); } } }
/*---------------------------------------------------------------*/ VINDEX first_v_succs(V_ITER *v_i) { EINDEX e; VINDEX to; /* get the first from edge */ if ( V_ITER_from_e(v_i) == INVALID_EINDEX ) { MEM_POOL_FREE(V_ITER_m(v_i),v_i); return INVALID_VINDEX; } /* return it's to vertex */ e = V_ITER_from_e(v_i); to = EDGE_to(&GRAPH_e_i(V_ITER_g(v_i),e)); V_ITER_nfrom(v_i) = EDGE_nfrom(&GRAPH_e_i(V_ITER_g(v_i),e)); /* store the current edge */ V_ITER_c_e(v_i) = e; return to; }
//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); } } }
/*---------------------------------------------------------------*/ VINDEX next_v_succs(V_ITER *v_i) { EINDEX ei; VINDEX to; /* get the next from edge */ if(V_ITER_nfrom(v_i) == -1) { MEM_POOL_FREE(V_ITER_m(v_i),v_i); return INVALID_VINDEX; } /* return it's to vertex */ ei = V_ITER_nfrom(v_i); to = EDGE_to(&GRAPH_e_i(V_ITER_g(v_i), ei)); V_ITER_nfrom(v_i) = EDGE_nfrom(&GRAPH_e_i(V_ITER_g(v_i),ei)); /* store the current edge */ V_ITER_c_e(v_i) = ei; return to; }
//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; }
/* 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; }