//'cur_region' covered 'entry'. AbsNode * CfsMgr::constructAbsIf( IN IRBB * entry, IN AbsNode * parent, IN Graph & cur_graph, IN OUT BitSet & visited) { AbsNode * node = new_abs_node(ABS_IF); set_map_bb2abs(entry, node); ABS_NODE_parent(node) = parent; ABS_NODE_if_head(node) = entry; IRBB * true_body, * false_body; IR_CFG * cfg = m_ru->getCFG(); cfg->getKidOfIF(entry, &true_body, &false_body, NULL); CFS_INFO * ci = map_ir2cfsinfo(cfg->get_last_xr(entry)); ASSERT0(ci != NULL && CFS_INFO_head(ci) == entry); BitSet loc_visited; ABS_NODE_true_body(node) = constructAbsTree(true_body, node, CFS_INFO_true_body(ci), cur_graph, loc_visited); visited.bunion(loc_visited); loc_visited.clean(); ABS_NODE_false_body(node) = constructAbsTree(false_body, node, CFS_INFO_false_body(ci), cur_graph, loc_visited); visited.bunion(loc_visited); visited.bunion(BB_id(entry)); return node; }
ABS_NODE * CFS_MGR::construct_abs_loop( IN IR_BB * entry, IN ABS_NODE * parent, IN BITSET * cur_region, IN GRAPH & cur_graph, IN OUT BITSET & visited) { IS_TRUE0(cur_region == NULL || cur_region->is_contain(IR_BB_id(entry))); IR_CFG * cfg = m_ru->get_cfg(); LI<IR_BB> * li = cfg->map_bb2li(entry); IS_TRUE0(li != NULL && LI_loop_head(li) == entry); ABS_NODE * node = new_abs_node(ABS_LOOP); set_map_bb2abs(entry, node); ABS_NODE_parent(node) = parent; ABS_NODE_loop_head(node) = entry; IR_BB * body_start; cfg->get_loop_two_kids(entry, NULL, &body_start); IS_TRUE0(body_start != NULL); CFS_INFO * ci = map_ir2cfsinfo(cfg->get_last_xr(entry)); IS_TRUE0(ci != NULL && CFS_INFO_head(ci) == entry); IS_TRUE0(CFS_INFO_loop_body(ci)->is_contain(*LI_bb_set(li))); BITSET loc_visited; ABS_NODE_loop_body(node) = construct_abs_tree(body_start, node, LI_bb_set(li), cur_graph, loc_visited); visited.bunion(loc_visited); visited.bunion(IR_BB_id(entry)); return node; }
//Before removing bb or change bb successor, //you need remove the related PHI operand if BB successor has PHI stmt. void IRBB::removeSuccessorDesignatePhiOpnd(CFG<IRBB, IR> * cfg, IRBB * succ) { ASSERT0(cfg && succ); IR_CFG * ircfg = (IR_CFG*)cfg; Region * ru = ircfg->get_ru(); 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)) == succ->getNumOfPred(cfg)); IR * opnd; UINT lpos = pos; for (opnd = PHI_opnd_list(ir); lpos != 0; opnd = opnd->get_next()) { ASSERT0(opnd); lpos--; } if (opnd == NULL) { //PHI does not contain any operand. continue; } opnd->removeSSAUse(); ((CPhi*)ir)->removeOpnd(opnd); ru->freeIRTree(opnd); } }
//'cur_region' covered 'entry'. ABS_NODE * CFS_MGR::construct_abs_if( IN IR_BB * entry, IN ABS_NODE * parent, IN GRAPH & cur_graph, IN OUT BITSET & visited) { ABS_NODE * node = new_abs_node(ABS_IF); set_map_bb2abs(entry, node); ABS_NODE_parent(node) = parent; ABS_NODE_if_head(node) = entry; IR_BB * true_body, * false_body; IR_CFG * cfg = m_ru->get_cfg(); cfg->get_if_three_kids(entry, &true_body, &false_body, NULL); CFS_INFO * ci = map_ir2cfsinfo(cfg->get_last_xr(entry)); IS_TRUE0(ci != NULL && CFS_INFO_head(ci) == entry); BITSET loc_visited; ABS_NODE_true_body(node) = construct_abs_tree(true_body, node, CFS_INFO_true_body(ci), cur_graph, loc_visited); visited.bunion(loc_visited); loc_visited.clean(); ABS_NODE_false_body(node) = construct_abs_tree(false_body, node, CFS_INFO_false_body(ci), cur_graph, loc_visited); visited.bunion(loc_visited); visited.bunion(IR_BB_id(entry)); return node; }
//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); } } }
AbsNode * CfsMgr::constructAbsLoop( IN IRBB * entry, IN AbsNode * parent, IN BitSet * cur_region, IN Graph & cur_graph, IN OUT BitSet & visited) { DUMMYUSE(cur_region); ASSERT0(cur_region == NULL || cur_region->is_contain(BB_id(entry))); IR_CFG * cfg = m_ru->getCFG(); LI<IRBB> * li = cfg->mapBB2LabelInfo(entry); ASSERT0(li != NULL && LI_loop_head(li) == entry); AbsNode * node = new_abs_node(ABS_LOOP); set_map_bb2abs(entry, node); ABS_NODE_parent(node) = parent; ABS_NODE_loop_head(node) = entry; IRBB * body_start; cfg->getKidOfLoop(entry, NULL, &body_start); ASSERT0(body_start != NULL); CFS_INFO * ci = map_ir2cfsinfo(cfg->get_last_xr(entry)); CHECK_DUMMYUSE(ci); ASSERT0(CFS_INFO_head(ci) == entry); ASSERT0(CFS_INFO_loop_body(ci)->is_contain(*LI_bb_set(li))); BitSet loc_visited; ABS_NODE_loop_body(node) = constructAbsTree(body_start, node, LI_bb_set(li), cur_graph, loc_visited); visited.bunion(loc_visited); visited.bunion(BB_id(entry)); return node; }
void DexRegion::processSimply() { LOG("DexRegion::processSimply %s", getRegionName()); if (getIRList() == NULL) { return ; } OptCtx oc; OC_show_comp_time(oc) = g_show_comp_time; CHAR const* ru_name = getRegionName(); constructIRBBlist(); ASSERT0(verifyIRandBB(getBBList(), this)); //All IRs have been moved to each IRBB. setIRList(NULL); PassMgr * passmgr = initPassMgr(); ASSERT0(passmgr); ASSERT0(g_cst_bb_list); IR_CFG * cfg = (IR_CFG*)passmgr->registerPass(PASS_CFG); ASSERT0(cfg); cfg->initCfg(oc); ASSERT0(g_do_cfg_dom); cfg->LoopAnalysis(oc); destroyPassMgr(); //Do not allocate register. getPrno2Vreg()->clean(); getPrno2Vreg()->copy(*getDex2IR()->getPR2Vreg()); return; }
void DEX_REGION::process_simply(OUT PRNO2UINT & prno2v, UINT param_num, UINT vregnum, DEX2IR & d2ir, UINT2PR * v2pr, IN PRNO2UINT * pr2v, TYIDR * tr) { LOG("\t\t Invoke DEX_REGION::process_simply '%s'", get_ru_name()); if (get_ir_list() == NULL) { return ; } OPT_CTX oc; OPTC_show_comp_time(oc) = g_show_comp_time; CHAR const* ru_name = get_ru_name(); construct_ir_bb_list(); IS_TRUE0(verify_ir_and_bb(get_bb_list(), get_dm())); RU_ana(this)->m_ir_list = NULL; //All IRs have been moved to each IR_BB. IR_CFG * cfg = init_cfg(oc); cfg->loop_analysis(oc); PASS_MGR * pm = new_pass_mgr(); OPTC_pass_mgr(oc) = pm; //record pass manager. if (g_do_ssa && OPTC_pass_mgr(oc) != NULL) { //Convert program to ssa form. IR_SSA_MGR * ssamgr = (IR_SSA_MGR*)OPTC_pass_mgr(oc)-> register_opt(OPT_SSA_MGR); IS_TRUE0(ssamgr); ssamgr->construction(oc, this); } init_aa(oc); init_du(oc); IR_SSA_MGR * ssamgr = (IR_SSA_MGR*)pm->query_opt(OPT_SSA_MGR); if (ssamgr != NULL && ssamgr->is_ssa_construct()) { //Destruct ssa form. ssamgr->destruction_in_bblist_order(); } delete pm; OPTC_pass_mgr(oc) = NULL; #if 1 //Do not allocate register. prno2v.clean(); prno2v.copy(*d2ir.get_pr2v_map()); return; #else //Allocate register. RA ra(this, tr, param_num, vregnum, v2pr, pr2v, &m_var2pr); LOG("\t\tdo DEX Register Allcation for '%s'", ru_name); ra.perform(oc); update_ra_res(ra, prno2v); #endif }
//Construct Control Flow Structure. ABS_NODE * CFS_MGR::construct_abstract_cfs() { IR_CFG * cfg = m_ru->get_cfg(); IR_BB * entry = cfg->get_entry_list()->get_head(); IS_TRUE(cfg->get_entry_list()->get_elem_count() == 1, ("CFG should be single-entry")); BITSET visited; ABS_NODE * a = construct_abs_tree(entry, NULL, NULL, *(GRAPH*)cfg, visited); //dump_abs_tree(a); return a; }
//Construct Control Flow Structure. AbsNode * CfsMgr::constructAbstractControlFlowStruct() { IR_CFG * cfg = m_ru->getCFG(); ASSERT(cfg->get_entry(), ("CFG should be single-entry")); BitSet visited; AbsNode * a = constructAbsTree(cfg->get_entry(), NULL, NULL, *(Graph*)cfg, visited); //dump_abs_tree(a); return a; }
/* Find preheader BB. If it does not exist, insert one before loop 'li'. 'insert_bb': return true if this function insert a new bb before loop, otherwise return false. 'force': force to insert preheader BB whatever it has exist. Return the new BB if insertion is successful. Note if we find the preheader, the last IR of it may be call. So if you are going to insert IR at the tail of preheader, the best is force to insert a new bb. */ IR_BB * find_and_insert_prehead(LI<IR_BB> const* li, REGION * ru, OUT bool & insert_bb, bool force) { IS_TRUE0(li && ru); insert_bb = false; IR_CFG * cfg = ru->get_cfg(); IR_BB_LIST * bblst = ru->get_bb_list(); IR_BB * head = LI_loop_head(li); C<IR_BB*> * bbholder = NULL; bblst->find(head, &bbholder); IS_TRUE0(bbholder); C<IR_BB*> * tt = bbholder; IR_BB * prev = bblst->get_prev(&tt); //Find appropriate BB to be prehead. bool find_appropriate_prev_bb = false; EDGE_C const* ec = VERTEX_in_list(cfg->get_vertex(IR_BB_id(head))); while (ec != NULL) { UINT pred = VERTEX_id(EDGE_from(EC_edge(ec))); if (pred == IR_BB_id(prev)) { find_appropriate_prev_bb = true; break; } ec = EC_next(ec); } if (!force && find_appropriate_prev_bb) { return prev; } LIST<IR_BB*> preds; cfg->get_preds(preds, head); insert_bb = true; IR_BB * newbb = ru->new_bb(); bblst->insert_before(newbb, bbholder); BITSET * loop_body = LI_bb_set(li); for (IR_BB * p = preds.get_head(); p != NULL; p = preds.get_next()) { if (loop_body->is_contain(IR_BB_id(p))) { continue; } cfg->add_bb(newbb); cfg->insert_vertex_between(IR_BB_id(p), IR_BB_id(head), IR_BB_id(newbb)); IR_BB_is_fallthrough(newbb) = 1; } return newbb; }
bool DEX_REGION::high_process(OPT_CTX & oc) { CHAR const* ru_name = get_ru_name(); g_indent = 0; SIMP_CTX simp; SIMP_if(&simp) = 1; SIMP_do_loop(&simp) = 1; SIMP_do_while(&simp) = 1; SIMP_while_do(&simp) = 1; SIMP_switch(&simp) = 0; SIMP_break(&simp) = 1; SIMP_continue(&simp) = 1; RU_ana(this)->m_ir_list = simplify_stmt_list(get_ir_list(), &simp); IS_TRUE0(verify_simp(get_ir_list(), simp)); IS_TRUE0(verify_irs(get_ir_list(), NULL, get_dm())); construct_ir_bb_list(); IS_TRUE0(verify_ir_and_bb(get_bb_list(), get_dm())); RU_ana(this)->m_ir_list = NULL; //All IRs have been moved to each IR_BB. IS_TRUE0(g_do_cfg && g_do_aa && g_do_du_ana && g_do_cdg); IR_CFG * cfg = init_cfg(oc); cfg->loop_analysis(oc); if (g_do_ssa && OPTC_pass_mgr(oc) != NULL) { IR_SSA_MGR * ssamgr = (IR_SSA_MGR*)OPTC_pass_mgr(oc)-> register_opt(OPT_SSA_MGR); IS_TRUE0(ssamgr); ssamgr->construction(oc, this); } init_aa(oc); init_du(oc); if (g_opt_level == NO_OPT) { return false; } 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); } } }
void PassMgr::performScalarOpt(OptCtx & oc) { TTab<Pass*> opt_tab; List<Pass*> passlist; SimpCtx simp; if (g_do_gvn) { registerPass(PASS_GVN); } if (g_do_pre) { //Do PRE individually. //Since it will incur the opposite effect with Copy-Propagation. Pass * pre = registerPass(PASS_PRE); pre->perform(oc); ASSERT0(verifyIRandBB(m_ru->get_bb_list(), m_ru)); } if (g_do_dce) { IR_DCE * dce = (IR_DCE*)registerPass(PASS_DCE); passlist.append_tail(dce); if (g_do_dce_aggressive) { dce->set_elim_cfs(true); } } bool in_ssa_form = false; IR_SSA_MGR * ssamgr = (IR_SSA_MGR*)(m_ru->get_pass_mgr()->queryPass(PASS_SSA_MGR)); if (ssamgr != NULL && ssamgr->is_ssa_constructed()) { in_ssa_form = true; } if (!in_ssa_form) { //RP can reduce the memory operations and //improve the effect of PR SSA, so perform //RP before SSA construction. //TODO: Do SSA renaming when after register promotion done. if (g_do_rp) { //First RP. passlist.append_tail(registerPass(PASS_RP)); } } if (g_do_cp) { IR_CP * pass = (IR_CP*)registerPass(PASS_CP); pass->set_prop_kind(CP_PROP_SIMPLEX); passlist.append_tail(pass); } if (g_do_rp) { //Second RP. passlist.append_tail(registerPass(PASS_RP)); } if (g_do_gcse) { passlist.append_tail(registerPass(PASS_GCSE)); } if (g_do_lcse) { passlist.append_tail(registerPass(PASS_LCSE)); } if (g_do_rce) { passlist.append_tail(registerPass(PASS_RCE)); } if (g_do_dse) { passlist.append_tail(registerPass(PASS_DSE)); } if (g_do_licm) { passlist.append_tail(registerPass(PASS_LICM)); } if (g_do_ivr) { passlist.append_tail(registerPass(PASS_IVR)); } if (g_do_loop_convert) { passlist.append_tail(registerPass(PASS_LOOP_CVT)); } bool change; UINT count = 0; BBList * bbl = m_ru->get_bb_list(); IR_CFG * cfg = m_ru->get_cfg(); UNUSED(cfg); do { change = false; for (Pass * pass = passlist.get_head(); pass != NULL; pass = passlist.get_next()) { CHAR const* passname = pass->get_pass_name(); ASSERT0(verifyIRandBB(bbl, m_ru)); ULONGLONG t = getusec(); bool doit = pass->perform(oc); appendTimeInfo(passname, getusec() - t); if (doit) { change = true; ASSERT0(verifyIRandBB(bbl, m_ru)); ASSERT0(cfg->verify()); } RefineCtx rc; m_ru->refineBBlist(bbl, rc); ASSERT0(m_ru->verifyRPO(oc)); } count++; } while (change && count < 20); ASSERT0(!change); if (g_do_lcse) { IR_LCSE * lcse = (IR_LCSE*)registerPass(PASS_LCSE); lcse->set_enable_filter(false); ULONGLONG t = getusec(); lcse->perform(oc); t = getusec() - t; appendTimeInfo(lcse->get_pass_name(), t); } if (g_do_rp) { IR_RP * r = (IR_RP*)registerPass(PASS_RP); ULONGLONG t = getusec(); r->perform(oc); appendTimeInfo(r->get_pass_name(), getusec() - t); } }
/* Perform high-level optimizaitions. Basis step to do: 1. Build control flow graph. 2. Compute POINT-TO info. 3. Compute DEF-USE info. 4. Compute Lived Expression info. Optimizations to be performed: 1. Auto Parallel 2. Loop interchange 3. Loop reverese(may be a little helpful) 4. Loop tiling 5. Loop fusion 6. Loop unrolling */ bool Region::HighProcess(OptCTX & oc) { g_indent = 0; note("\n\n==== Region:%s HIGHEST LEVEL FARMAT ====\n\n", get_ru_name()); SimpCTX simp; if (g_do_cfs_opt) { IR_CFS_OPT co(this); co.perform(simp); ASSERT0(verify_irs(get_ir_list(), NULL, this)); } PassMgr * passmgr = initPassMgr(); ASSERT0(passmgr); if (g_build_cfs) { SIMP_is_record_cfs(&simp) = true; CfsMgr * cfsmgr = (CfsMgr*)passmgr->registerPass(PASS_CFS_MGR); ASSERT0(cfsmgr); SIMP_cfs_mgr(&simp) = cfsmgr; } simp.set_simp_cf(); set_ir_list(simplifyStmtList(get_ir_list(), &simp)); ASSERT0(verify_simp(get_ir_list(), simp)); ASSERT0(verify_irs(get_ir_list(), NULL, this)); if (g_cst_bb_list) { constructIRBBlist(); ASSERT0(verifyIRandBB(get_bb_list(), this)); set_ir_list(NULL); //All IRs have been moved to each IRBB. } if (g_do_cfg) { ASSERT0(g_cst_bb_list); IR_CFG * cfg = (IR_CFG*)passmgr->registerPass(PASS_CFG); ASSERT0(cfg); cfg->initCfg(oc); if (g_do_loop_ana) { ASSERT0(g_do_cfg_dom); cfg->LoopAnalysis(oc); } } if (g_do_ssa) { //Note lowering IR now may be too early and will be //a hindrance to optmizations. //low_to_pr_mode(oc); IR_SSA_MGR * ssamgr = (IR_SSA_MGR*)passmgr->registerPass(PASS_SSA_MGR); ASSERT0(ssamgr); ssamgr->construction(oc); } if (g_do_aa) { ASSERT0(g_cst_bb_list && OC_is_cfg_valid(oc)); IR_AA * aa = (IR_AA*)passmgr->registerPass(PASS_AA); ASSERT0(aa); aa->initAliasAnalysis(); aa->perform(oc); } if (g_do_du_ana) { ASSERT0(g_cst_bb_list && OC_is_cfg_valid(oc) && OC_is_aa_valid(oc)); IR_DU_MGR * dumgr = (IR_DU_MGR*)passmgr->registerPass(PASS_DU_MGR); ASSERT0(dumgr); UINT f = SOL_REACH_DEF|SOL_REF; //f |= SOL_AVAIL_REACH_DEF|SOL_AVAIL_EXPR|SOL_RU_REF; if (g_do_ivr) { f |= SOL_AVAIL_REACH_DEF|SOL_AVAIL_EXPR; } if (g_do_compute_available_exp) { f |= SOL_AVAIL_EXPR; } dumgr->perform(oc, f); dumgr->computeMDDUChain(oc); } if (g_do_expr_tab) { ASSERT0(g_cst_bb_list); IR_EXPR_TAB * exprtab = (IR_EXPR_TAB*)passmgr->registerPass(PASS_EXPR_TAB); ASSERT0(exprtab); exprtab->perform(oc); } if (g_do_cdg) { ASSERT0(g_cst_bb_list && OC_is_cfg_valid(oc)); CDG * cdg = (CDG*)passmgr->registerPass(PASS_CDG); ASSERT0(cdg); cdg->build(oc, *get_cfg()); } if (g_opt_level == NO_OPT) { return false; } /* Regenerate high level IR, and do high level optimizations. Now, I get one thing: We cannot or not very easy construct High Level Control IR, (IF,DO_LOOP,...) via analysing CFG. e.g: if (i > j) { //BB1 ... } else { return 2; //S1 } BB1 does not have a ipdom, so we can not find the indispensible 3 parts: True body, False body, and the Sibling node. Solution: We can scan IF stmt first, in order to mark start stmt and end stmt of IF. //AbsNode * an = REGION_analysis_instrument(this)->m_cfs_mgr->construct_abstract_cfs(); //Polyhedra optimization. //IR_POLY * poly = newPoly(); //if (poly->construct_poly(an)) { // poly->perform_poly_trans(); //} //delete poly; */ return true; }
ABS_NODE * CFS_MGR::construct_abs_tree( IN IR_BB * entry, IN ABS_NODE * parent, IN BITSET * cur_region, IN GRAPH & cur_graph, IN OUT BITSET & visited) { IR_CFG * cfg = m_ru->get_cfg(); ABS_NODE * lst = NULL; IR_BB * bb = entry; GRAPH g; g.clone(cur_graph); VERTEX * next = NULL; VERTEX * v; if (cur_region != NULL) { if (cur_region->get_elem_count() == 0) { visited.clean(); return NULL; } INT c; for (v = g.get_first_vertex(c); v != NULL; v = next) { next = g.get_next_vertex(c); if (cur_region->is_contain(VERTEX_id(v))) { continue; } g.remove_vertex(v); } } BITSET loc_visited; while (bb != NULL && (cur_region == NULL || cur_region->is_contain(IR_BB_id(bb)))) { ABS_NODE * node = NULL; loc_visited.clean(); LI<IR_BB> * li = cfg->map_bb2li(bb); if (li != NULL) { node = construct_abs_loop(bb, parent, LI_bb_set(li), g, loc_visited); } else { IR * last_xr = cfg->get_last_xr(bb); if (last_xr != NULL && //'bb' is branching node of IF. last_xr->is_cond_br()) { IS_TRUE0(map_ir2cfsinfo(last_xr) != NULL); /* There might not exist ipdom. e.g: if (x) //BB1 return 1; return 2; BB1 does not have a ipdom. */ UINT ipdom = ((DGRAPH*)cfg)->get_ipdom(IR_BB_id(bb)); IS_TRUE(ipdom > 0, ("bb does not have ipdom")); node = construct_abs_if(bb, parent, g, loc_visited); } else { node = construct_abs_bb(bb, parent); loc_visited.bunion(IR_BB_id(bb)); } } insertbefore_one(&lst, lst, node); visited.bunion(loc_visited); //Remove visited vertex. next = NULL; INT c; for (v = g.get_first_vertex(c); v != NULL; v = next) { next = g.get_next_vertex(c); if (!loc_visited.is_contain(VERTEX_id(v))) { continue; } g.remove_vertex(v); } IR_BB * cand = NULL; for (v = g.get_first_vertex(c); v != NULL; v = g.get_next_vertex(c)) { if (g.get_in_degree(v) == 0) { IS_TRUE(cand == NULL, ("multiple immediate-post-dominators")); cand = cfg->get_bb(VERTEX_id(v)); } } if (cand == NULL) { //Cannot find leading BB, there might be exist cycle in graph. bb = cfg->get_ipdom(bb); } else { bb = cand; } if (parent != NULL && bb == ABS_NODE_bb(parent)) { //Here control-flow is cyclic. break; } } lst = reverse_list(lst); return lst; }
void MDPhi::dump(Region * rg, UseDefMgr * mgr) { ASSERT0(rg); ASSERT0(is_phi()); if (g_tfile == NULL) { return; } List<IRBB*> preds; IR_CFG * cfg = rg->getCFG(); ASSERT0(cfg); cfg->get_preds(preds, getBB()); IRBB * pred = preds.get_head(); ASSERT0(getResult()); fprintf(g_tfile, "Phi: MD%dV%d <- ", getResult()->mdid(), getResult()->version()); for (IR const* opnd = getOpndList(); opnd != NULL; opnd = opnd->get_next()) { if (opnd != getOpndList()) { fprintf(g_tfile, ", "); } switch (opnd->get_code()) { case IR_CONST: fprintf(g_tfile, "Const"); break; case IR_LDA: fprintf(g_tfile, "Lda"); break; case IR_ID: { VMD * vopnd = getOpndVMD(opnd, mgr); fprintf(g_tfile, "MD%dV%d(id:%d)", vopnd->mdid(), vopnd->version(), opnd->id()); } break; default: UNREACH(); } ASSERT0(pred); fprintf(g_tfile, "(BB%d)", pred->id()); pred = preds.get_next(); } VMD * res = getResult(); ASSERT0(res); fprintf(g_tfile, "|UsedBy:"); SEGIter * vit = NULL; bool first = true; for (INT i2 = res->getOccSet()->get_first(&vit); i2 >= 0; i2 = res->getOccSet()->get_next(i2, &vit)) { if (first) { first = false; } else { fprintf(g_tfile, ","); } IR const* use = rg->getIR(i2); ASSERT0(use && (use->isMemoryRef() || use->is_id())); fprintf(g_tfile, "%s(id:%d)", IRNAME(use), use->id()); } fflush(g_tfile); }
AbsNode * CfsMgr::constructAbsTree( IN IRBB * entry, IN AbsNode * parent, IN BitSet * cur_region, IN Graph & cur_graph, IN OUT BitSet & visited) { IR_CFG * cfg = m_ru->getCFG(); AbsNode * lst = NULL; IRBB * bb = entry; Graph g; g.clone(cur_graph); Vertex * next = NULL; Vertex * v; if (cur_region != NULL) { if (cur_region->get_elem_count() == 0) { visited.clean(); return NULL; } INT c; for (v = g.get_first_vertex(c); v != NULL; v = next) { next = g.get_next_vertex(c); if (cur_region->is_contain(VERTEX_id(v))) { continue; } g.removeVertex(v); } } BitSet loc_visited; while (bb != NULL && (cur_region == NULL || cur_region->is_contain(BB_id(bb)))) { AbsNode * node = NULL; loc_visited.clean(); LI<IRBB> * li = cfg->mapBB2LabelInfo(bb); if (li != NULL) { node = constructAbsLoop(bb, parent, LI_bb_set(li), g, loc_visited); } else { IR * last_xr = cfg->get_last_xr(bb); if (last_xr != NULL && //'bb' is branching node of IF. last_xr->isConditionalBr()) { ASSERT0(map_ir2cfsinfo(last_xr) != NULL); //There might not exist ipdom. //e.g: // if (x) //BB1 // return 1; // return 2; // // BB1 does not have a ipdom. UINT ipdom = ((DGraph*)cfg)->get_ipdom(BB_id(bb)); DUMMYUSE(ipdom); ASSERT(ipdom > 0, ("bb does not have ipdom")); node = constructAbsIf(bb, parent, g, loc_visited); } else { node = constructAbsBB(bb, parent); loc_visited.bunion(BB_id(bb)); } } insertbefore_one(&lst, lst, node); visited.bunion(loc_visited); //Remove visited vertex. next = NULL; INT c; for (v = g.get_first_vertex(c); v != NULL; v = next) { next = g.get_next_vertex(c); if (!loc_visited.is_contain(VERTEX_id(v))) { continue; } g.removeVertex(v); } IRBB * cand = NULL; for (v = g.get_first_vertex(c); v != NULL; v = g.get_next_vertex(c)) { if (g.get_in_degree(v) == 0) { ASSERT(cand == NULL, ("multiple immediate-post-dominators")); cand = cfg->getBB(VERTEX_id(v)); } } if (cand == NULL) { //Cannot find leading BB, there might be exist cycle in graph. bb = cfg->get_ipdom(bb); } else { bb = cand; } if (parent != NULL && bb == ABS_NODE_bb(parent)) { //Here control-flow is cyclic. break; } } lst = reverse_list(lst); return lst; }