//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); } }
//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); } } }
//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; }
//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); } } }