//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::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); } }
//Get the value expression that to be propagated. inline static IR * get_propagated_value(IR * stmt) { switch (IR_code(stmt)) { case IR_ST: return ST_rhs(stmt); case IR_STPR: return STPR_rhs(stmt); case IR_IST: return IST_rhs(stmt); case IR_PHI: return PHI_opnd_list(stmt); default:; } UNREACH(); return NULL; }
//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); } } }
bool IR_CP::is_copy(IR * ir) const { switch (ir->get_code()) { case IR_ST: case IR_STPR: case IR_IST: return canBeCandidate(ir->get_rhs()); case IR_PHI: if (cnt_list(PHI_opnd_list(ir)) == 1) { return true; } default: break; } return false; }
void IR_GVN::process_phi(IR const* ir, bool & change) { VN * phivn = NULL; IR const* p = PHI_opnd_list(ir); if (p != NULL) { phivn = comp_vn(p, change); p = IR_next(p); } for (; p != NULL; p = IR_next(p)) { VN * opndvn = comp_vn(p, change); if (phivn != NULL && phivn != opndvn) { phivn = NULL; } } if (m_ir2vn.get(IR_id(ir)) != phivn) { IS_TRUE0(m_ir2vn.get(IR_id(ir)) == NULL); m_ir2vn.set(IR_id(ir), phivn); change = true; } }
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); } } }