// //START PRDF // void PRDF::dump() { if (g_tfile == NULL) { return; } fprintf(g_tfile, "\n==---- DUMP PRDF : liveness of PR ----==\n"); List<IRBB*> * bbl = m_ru->get_bb_list(); g_indent = 2; for (IRBB * bb = bbl->get_head(); bb != NULL; bb = bbl->get_next()) { fprintf(g_tfile, "\n\n\n-- BB%d --", BB_id(bb)); DefSBitSetCore * live_in = get_livein(BB_id(bb)); DefSBitSetCore * live_out = get_liveout(BB_id(bb)); DefSBitSetCore * def = get_def(BB_id(bb)); DefSBitSetCore * use = get_use(BB_id(bb)); fprintf(g_tfile, "\nLIVE-IN: "); live_in->dump(g_tfile); fprintf(g_tfile, "\nLIVE-OUT: "); live_out->dump(g_tfile); fprintf(g_tfile, "\nDEF: "); def->dump(g_tfile); fprintf(g_tfile, "\nUSE: "); use->dump(g_tfile); } fflush(g_tfile); }
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 CfsMgr::dump_abs_tree(AbsNode * an, UINT indent) { while (an != NULL) { switch (ABS_NODE_type(an)) { case ABS_BB: fprintf(g_tfile, "\n"); dump_indent(indent); fprintf(g_tfile, "BB%d", BB_id(ABS_NODE_bb(an))); break; case ABS_LOOP: fprintf(g_tfile, "\n"); dump_indent(indent); fprintf(g_tfile, "LOOP: HEAD=BB%d", BB_id(ABS_NODE_loop_head(an))); dump_abs_tree(ABS_NODE_loop_body(an), indent + 4); break; case ABS_IF: fprintf(g_tfile, "\n"); dump_indent(indent); fprintf(g_tfile, "IF: HEAD=BB%d", BB_id(ABS_NODE_if_head(an))); if (ABS_NODE_true_body(an) != NULL) { fprintf(g_tfile, "\n"); dump_indent(indent); fprintf(g_tfile, "TRUE_BODY:"); dump_abs_tree(ABS_NODE_true_body(an), indent + 4); } if (ABS_NODE_false_body(an) != NULL) { fprintf(g_tfile, "\n"); dump_indent(indent); fprintf(g_tfile, "FALSE_BODY:"); dump_abs_tree(ABS_NODE_false_body(an), indent + 4); } break; } an = ABS_NODE_next(an); } }
//'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; }
//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); } }
//Return true if 'occ' does not be modified till meeting 'use_ir'. //e.g: // xx = occ //def_ir // .. // .. // yy = xx //use_ir // //'def_ir': ir stmt. //'occ': opnd of 'def_ir' //'use_ir': stmt in use-list of 'def_ir'. bool IR_CP::is_available(IR const* def_ir, IR const* occ, IR * use_ir) { if (def_ir == use_ir) { return false; } if (occ->is_const()) { return true; } //Need check overlapped MDSet. //e.g: Suppose occ is '*p + *q', p->a, q->b. //occ can NOT reach 'def_ir' if one of p, q, a, b //modified during the path. IRBB * defbb = def_ir->get_bb(); IRBB * usebb = use_ir->get_bb(); if (defbb == usebb) { //Both def_ir and use_ir are in same BB. C<IR*> * ir_holder = NULL; bool f = BB_irlist(defbb).find(const_cast<IR*>(def_ir), &ir_holder); CK_USE(f); IR * ir; for (ir = BB_irlist(defbb).get_next(&ir_holder); ir != NULL && ir != use_ir; ir = BB_irlist(defbb).get_next(&ir_holder)) { if (m_du->is_may_def(ir, occ, true)) { return false; } } if (ir == NULL) { ;//use_ir appears prior to def_ir. Do more check via live_in_expr. } else { ASSERT(ir == use_ir, ("def_ir should be in same bb to use_ir")); return true; } } ASSERT0(use_ir->is_stmt()); DefDBitSetCore const* availin_expr = m_du->getAvailInExpr(BB_id(usebb), NULL); ASSERT0(availin_expr); if (availin_expr->is_contain(IR_id(occ))) { IR * u; for (u = BB_first_ir(usebb); u != use_ir && u != NULL; u = BB_next_ir(usebb)) { //Check if 'u' override occ's value. if (m_du->is_may_def(u, occ, true)) { return false; } } ASSERT(u != NULL && u == use_ir, ("Not find use_ir in bb, may be it has " "been removed by other optimization")); return true; } return false; }
bool IR_CP::perform(OptCtx & oc) { START_TIMER_AFTER(); ASSERT0(OC_is_cfg_valid(oc)); if (m_prop_kind == CP_PROP_CONST) { m_ru->checkValidAndRecompute(&oc, PASS_DOM, PASS_DU_REF, PASS_DU_CHAIN, PASS_UNDEF); } else { m_ru->checkValidAndRecompute(&oc, PASS_DOM, PASS_DU_REF, PASS_LIVE_EXPR, PASS_DU_CHAIN, PASS_UNDEF); } if (!OC_is_du_chain_valid(oc)) { END_TIMER_AFTER(get_pass_name()); return false; } bool change = false; IRBB * entry = m_ru->get_cfg()->get_entry(); ASSERT(entry, ("Not unique entry, invalid Region")); Graph domtree; m_cfg->get_dom_tree(domtree); List<Vertex*> lst; Vertex * root = domtree.get_vertex(BB_id(entry)); m_cfg->sortDomTreeInPreorder(root, lst); Vector<IR*> usevec; for (Vertex * v = lst.get_head(); v != NULL; v = lst.get_next()) { IRBB * bb = m_cfg->get_bb(VERTEX_id(v)); ASSERT0(bb); change |= doProp(bb, usevec); } if (change) { doFinalRefine(); OC_is_expr_tab_valid(oc) = false; OC_is_aa_valid(oc) = false; OC_is_du_chain_valid(oc) = true; //already update. OC_is_ref_valid(oc) = true; //already update. ASSERT0(m_ru->verifyMDRef() && m_du->verifyMDDUChain()); ASSERT0(verifySSAInfo(m_ru)); } END_TIMER_AFTER(get_pass_name()); return change; }
//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 IRBB::dump(Region * ru) { if (g_tfile == NULL) { return; } g_indent = 0; fprintf(g_tfile, "\n----- BB%d ------", BB_id(this)); if (get_lab_list().get_elem_count() > 0) { fprintf(g_tfile, "\nLABEL:"); dumpBBLabel(get_lab_list(), g_tfile); } //Attributes fprintf(g_tfile, "\nATTR:"); if (BB_is_entry(this)) { fprintf(g_tfile, "entry_bb "); } //if (BB_is_exit(this)) { // fprintf(g_tfile, "exit_bb "); //} if (BB_is_fallthrough(this)) { fprintf(g_tfile, "fall_through "); } if (BB_is_target(this)) { fprintf(g_tfile, "branch_target "); } //IR list fprintf(g_tfile, "\nSTMT NUM:%d", getNumOfIR()); g_indent += 3; TypeMgr * dm = ru->get_type_mgr(); for (IR * ir = BB_first_ir(this); ir != NULL; ir = BB_irlist(this).get_next()) { ASSERT0(IR_next(ir) == NULL && IR_prev(ir) == NULL); ASSERT0(ir->get_bb() == this); dump_ir(ir, dm, NULL, true, true, false); } g_indent -= 3; fprintf(g_tfile, "\n"); fflush(g_tfile); }
//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 CfsMgr::set_map_bb2abs(IRBB const* bb, AbsNode * abs) { m_map_bb2abs.set(BB_id(bb), abs); }
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; }
void PRDF::computeLocal(IRBB * bb, List<IR const*> & lst) { DefSBitSetCore * gen = get_def(BB_id(bb)); DefSBitSetCore * use = get_use(BB_id(bb)); gen->clean(m_sbs_mgr); use->clean(m_sbs_mgr); for (IR * x = BB_last_ir(bb); x != NULL; x = BB_prev_ir(bb)) { ASSERT0(x->is_stmt()); switch (IR_code(x)) { case IR_ST: lst.clean(); processOpnd(ST_rhs(x), lst, use, gen); break; case IR_STPR: gen->bunion(STPR_no(x), m_sbs_mgr); use->diff(STPR_no(x), m_sbs_mgr); processMay(x, gen, use, true); lst.clean(); processOpnd(STPR_rhs(x), lst, use, gen); break; case IR_SETELEM: gen->bunion(SETELEM_prno(x), m_sbs_mgr); use->diff(SETELEM_prno(x), m_sbs_mgr); processMay(x, gen, use, true); lst.clean(); processOpnd(SETELEM_rhs(x), lst, use, gen); lst.clean(); processOpnd(SETELEM_ofst(x), lst, use, gen); break; case IR_GETELEM: gen->bunion(GETELEM_prno(x), m_sbs_mgr); use->diff(GETELEM_prno(x), m_sbs_mgr); processMay(x, gen, use, true); lst.clean(); processOpnd(GETELEM_base(x), lst, use, gen); lst.clean(); processOpnd(GETELEM_ofst(x), lst, use, gen); break; case IR_STARRAY: lst.clean(); processOpnd(x, lst, use, gen); break; case IR_IST: lst.clean(); processOpnd(x, lst, use, gen); break; case IR_SWITCH: lst.clean(); processOpnd(SWITCH_vexp(x), lst, use, gen); break; case IR_IGOTO: lst.clean(); processOpnd(IGOTO_vexp(x), lst, use, gen); break; case IR_GOTO: break; case IR_CALL: case IR_ICALL: if (x->hasReturnValue()) { gen->bunion(CALL_prno(x), m_sbs_mgr); use->diff(CALL_prno(x), m_sbs_mgr); processMay(x, gen, use, true); } lst.clean(); processOpnd(CALL_param_list(x), lst, use, gen); if (x->is_icall() && ICALL_callee(x)->is_pr()) { use->bunion(PR_no(ICALL_callee(x)), m_sbs_mgr); processMay(ICALL_callee(x), gen, use, false); } break; case IR_TRUEBR: case IR_FALSEBR: lst.clean(); processOpnd(BR_det(x), lst, use, gen); break; case IR_RETURN: lst.clean(); processOpnd(RET_exp(x), lst, use, gen); break; case IR_PHI: gen->bunion(PHI_prno(x), m_sbs_mgr); use->diff(PHI_prno(x), m_sbs_mgr); processMay(x, gen, use, true); lst.clean(); processOpnd(PHI_opnd_list(x), lst, use, gen); break; case IR_REGION: break; default: ASSERT0(0); } } }
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 }
//'usevec': for local used. bool IR_CP::doProp(IN IRBB * bb, Vector<IR*> & usevec) { bool change = false; C<IR*> * cur_iter, * next_iter; for (BB_irlist(bb).get_head(&cur_iter), next_iter = cur_iter; cur_iter != NULL; cur_iter = next_iter) { IR * def_stmt = cur_iter->val(); BB_irlist(bb).get_next(&next_iter); if (!is_copy(def_stmt)) { continue; } DUSet const* useset = NULL; UINT num_of_use = 0; SSAInfo * ssainfo = NULL; bool ssadu = false; if ((ssainfo = def_stmt->get_ssainfo()) != NULL && SSA_uses(ssainfo).get_elem_count() != 0) { //Record use_stmt in another vector to facilitate this function //if it is not in use-list any more after copy-propagation. SEGIter * sc; for (INT u = SSA_uses(ssainfo).get_first(&sc); u >= 0; u = SSA_uses(ssainfo).get_next(u, &sc)) { IR * use = m_ru->get_ir(u); ASSERT0(use); usevec.set(num_of_use, use); num_of_use++; } ssadu = true; } else if (def_stmt->get_exact_ref() == NULL && !def_stmt->is_void()) { //Allowing copy propagate exact or VOID value. continue; } else if ((useset = def_stmt->readDUSet()) != NULL && useset->get_elem_count() != 0) { //Record use_stmt in another vector to facilitate this function //if it is not in use-list any more after copy-propagation. DUIter di = NULL; for (INT u = useset->get_first(&di); u >= 0; u = useset->get_next(u, &di)) { IR * use = m_ru->get_ir(u); usevec.set(num_of_use, use); num_of_use++; } } else { continue; } IR const* prop_value = get_propagated_value(def_stmt); for (UINT i = 0; i < num_of_use; i++) { IR * use = usevec.get(i); ASSERT0(use->is_exp()); IR * use_stmt = use->get_stmt(); ASSERT0(use_stmt->is_stmt()); ASSERT0(use_stmt->get_bb() != NULL); IRBB * use_bb = use_stmt->get_bb(); if (!ssadu && !(bb == use_bb && bb->is_dom(def_stmt, use_stmt, true)) && !m_cfg->is_dom(BB_id(bb), BB_id(use_bb))) { //'def_stmt' must dominate 'use_stmt'. //e.g: // if (...) { // g = 10; //S1 // } // ... = g; //S2 //g can not be propagted since S1 is not dominate S2. continue; } if (!is_available(def_stmt, prop_value, use_stmt)) { //The value that will be propagated can //not be killed during 'ir' and 'use_stmt'. //e.g: // g = a; //S1 // if (...) { // a = ...; //S3 // } // ... = g; //S2 //g can not be propagted since a is killed by S3. continue; } if (!ssadu && !m_du->isExactAndUniqueDef(def_stmt, use)) { //Only single definition is allowed. //e.g: // g = 20; //S3 // if (...) { // g = 10; //S1 // } // ... = g; //S2 //g can not be propagted since there are //more than one definitions are able to get to S2. continue; } if (!canBeCandidate(prop_value)) { continue; } CPCtx lchange; IR * old_use_stmt = use_stmt; replaceExp(use, prop_value, lchange, ssadu); ASSERT(use_stmt && use_stmt->is_stmt(), ("ensure use_stmt still legal")); change |= CPC_change(lchange); if (!CPC_change(lchange)) { continue; } //Indicate whether use_stmt is the next stmt of def_stmt. bool is_next = false; if (next_iter != NULL && use_stmt == next_iter->val()) { is_next = true; } RefineCtx rf; use_stmt = m_ru->refineIR(use_stmt, change, rf); if (use_stmt == NULL && is_next) { //use_stmt has been optimized and removed by refineIR(). next_iter = cur_iter; BB_irlist(bb).get_next(&next_iter); } if (use_stmt != NULL && use_stmt != old_use_stmt) { //use_stmt has been removed and new stmt generated. ASSERT(old_use_stmt->is_undef(), ("the old one should be freed")); C<IR*> * irct = NULL; BB_irlist(use_bb).find(old_use_stmt, &irct); ASSERT0(irct); BB_irlist(use_bb).insert_before(use_stmt, irct); BB_irlist(use_bb).remove(irct); } } //end for each USE } //end for IR return change; }
AbsNode * CfsMgr::map_bb2abs(IRBB const* bb) { return m_map_bb2abs.get(BB_id(bb)); }