//Check that all basic blocks should only end with terminator IR. void IRBB::verify() { UINT c = 0; C<IR*> * ct; for (IR * ir = BB_irlist(this).get_head(&ct); ir != NULL; ir = BB_irlist(this).get_next(&ct)) { ASSERT0(ir->is_single()); ASSERT0(ir->get_bb() == this); switch (IR_code(ir)) { case IR_ST: case IR_STPR: case IR_STARRAY: case IR_IST: case IR_PHI: case IR_REGION: case IR_CALL: case IR_ICALL: case IR_GOTO: case IR_IGOTO: case IR_TRUEBR: case IR_FALSEBR: case IR_RETURN: case IR_SWITCH: break; default: ASSERT(0, ("BB does not supported this kind of IR.")); } if (is_bb_down_boundary(ir)) { ASSERT(ir == BB_last_ir(this), ("invalid BB down boundary.")); } c++; } ASSERT0(c == getNumOfIR()); }
//Could ir be looked as a last stmt in basic block? bool IRBB::is_bb_down_boundary(IR * ir) { ASSERT(ir->isStmtInBB() || ir->is_lab(), ("illegal stmt in bb")); switch (IR_code(ir)) { case IR_CALL: case IR_ICALL: //indirective call return ((CCall*)ir)->isMustBBbound(); case IR_GOTO: case IR_IGOTO: return true; case IR_SWITCH: ASSERT(SWITCH_body(ir) == NULL, ("Peel switch-body to enable switch in bb-list construction")); return true; case IR_TRUEBR: case IR_FALSEBR: return true; case IR_RETURN: case IR_REGION: return true; default: break; } return false; }
//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; }
ExpRep * IR_EXPR_TAB::encode_expr(IN IR * ir) { if (ir == NULL) return NULL; ASSERT0(ir->is_exp()); switch (IR_code(ir)) { case IR_ID: case IR_LD: case IR_LDA: case IR_CONST: case IR_PR: return NULL; case IR_ILD: case IR_ADD: case IR_SUB: case IR_MUL: case IR_DIV: case IR_REM: case IR_MOD: case IR_LAND: //logical and && case IR_LOR: //logical or || case IR_BAND: //bit and & case IR_BOR: //bit or | case IR_XOR: case IR_BNOT: //bitwise not case IR_LNOT: //logical not case IR_NEG: case IR_LT: case IR_LE: case IR_GT: case IR_GE: case IR_EQ: case IR_NE: case IR_ARRAY: case IR_ASR: case IR_LSR: case IR_LSL: case IR_CVT: //type convertion case IR_SELECT: //formulized determinate-expr?exp:exp { ExpRep * ie = append_expr(ir); ASSERT(!EXPR_occ_list(ie).find(ir), ("process same IR repeated.")); EXPR_occ_list(ie).append_tail(ir); return ie; } default: ASSERT0(0); } return NULL; }
UINT IR_EXPR_TAB::compute_hash_key(IR const* ir) { ASSERT0(ir != NULL); UINT hval = IR_code(ir) + (ir->get_offset() + 1) + (UINT)(size_t)IR_dt(ir); if (ir->is_id()) { VAR * var = ID_info(ir); /* SYM * name = VAR_name(id_info); CHAR * s = SYM_name(name); UINT v = 0 ; while (*s != 0) { v += (UINT)(*s++); } hval += v; */ hval += 5 * (UINT)(size_t)var; } return hval; }
/* Encode expression for single BB. Scan IR statement literally, and encoding it for generating the unique id for each individual expressions, and update the 'GEN-SET' and 'KILL-SET' of IR-EXPR for BB as well as. */ void IR_EXPR_TAB::encode_bb(IRBB * bb) { C<IR*> * ct; for (IR * ir = BB_irlist(bb).get_head(&ct); ir != NULL; ir = BB_irlist(bb).get_next(&ct)) { ASSERT0(ir->is_stmt()); switch (IR_code(ir)) { case IR_ST: { ExpRep * ie = encode_expr(ST_rhs(ir)); if (ie != NULL) { set_map_ir2ir_expr(ST_rhs(ir), ie); } } break; case IR_STPR: { ExpRep * ie = encode_expr(STPR_rhs(ir)); if (ie != NULL) { set_map_ir2ir_expr(STPR_rhs(ir), ie); } } break; case IR_STARRAY: { ExpRep * ie = encode_expr(ARR_base(ir)); if (ie != NULL) { set_map_ir2ir_expr(ARR_base(ir), ie); } for (IR * sub = ARR_sub_list(ir); sub != NULL; sub = IR_next(sub)) { ExpRep * ie = encode_expr(sub); if (ie != NULL) { set_map_ir2ir_expr(sub, ie); } } ie = encode_expr(STARR_rhs(ir)); if (ie != NULL) { set_map_ir2ir_expr(STARR_rhs(ir), ie); } } break; case IR_IST: { ExpRep * ie = encode_expr(IST_rhs(ir)); if (ie != NULL) { set_map_ir2ir_expr(IST_rhs(ir), ie); } ie = encode_istore_memaddr(IST_base(ir)); if (ie != NULL) { set_map_ir2ir_expr(IST_base(ir), ie); } } break; case IR_ICALL: //indirective call { ExpRep * ie = encode_expr(ICALL_callee(ir)); if (ie != NULL) { set_map_ir2ir_expr(ICALL_callee(ir), ie); } } case IR_CALL: { IR * parm = CALL_param_list(ir); while (parm != NULL) { ExpRep * ie = encode_expr(parm); if (ie != NULL) { set_map_ir2ir_expr(parm, ie); } parm = IR_next(parm); } } break; case IR_GOTO: break; case IR_IGOTO: { ExpRep * ie = encode_expr(IGOTO_vexp(ir)); if (ie != NULL) { set_map_ir2ir_expr(IGOTO_vexp(ir), ie); } } break; case IR_DO_WHILE: case IR_WHILE_DO: case IR_DO_LOOP: //loop with init , boundary , and step info case IR_IF: ASSERT(0, ("High level IR should be simplified")); break; case IR_LABEL: break; case IR_CASE: case IR_REGION: break; case IR_TRUEBR: case IR_FALSEBR: { ExpRep * ie = encode_expr(BR_det(ir)); if (ie != NULL) { set_map_ir2ir_expr(BR_det(ir), ie); } } break; case IR_SWITCH: { ExpRep * ie = encode_expr(SWITCH_vexp(ir)); if (ie != NULL) { set_map_ir2ir_expr(SWITCH_vexp(ir), ie); } } break; case IR_RETURN: { ExpRep * ie = encode_expr(RET_exp(ir)); if (ie != NULL) { set_map_ir2ir_expr(RET_exp(ir), ie); } } break; case IR_PHI: break; default: ASSERT0(0); } //end switch } //end for IR //dump_ir_expr_tab(); }
//Remove all expr for given stmt out of occ list in expr-tab. void IR_EXPR_TAB::remove_occs(IR * ir) { ASSERT0(ir->is_stmt()); switch (IR_code(ir)) { case IR_ST: { IR * stv = ST_rhs(ir); if (stv->is_const()) { return; } this->remove_occ(stv); } break; case IR_IST: { IR * stv = IST_rhs(ir); if (!stv->is_const()) { this->remove_occ(stv); } IR * m = IST_base(ir); if (m->is_const()) { return; } this->remove_occ(m); } break; case IR_CALL: case IR_ICALL: { IR * p = CALL_param_list(ir); while (p != NULL) { if (!p->is_const()) { this->remove_occ(p); } p = IR_next(p); } } break; case IR_TRUEBR: case IR_FALSEBR: this->remove_occ(BR_det(ir)); break; case IR_SWITCH: ASSERT0(SWITCH_vexp(ir)); if (!SWITCH_vexp(ir)->is_const()) { this->remove_occ(SWITCH_vexp(ir)); } break; case IR_IGOTO: ASSERT0(IGOTO_vexp(ir)); if (!IGOTO_vexp(ir)->is_const()) { this->remove_occ(IGOTO_vexp(ir)); } break; case IR_RETURN: if (RET_exp(ir) != NULL) { if (!RET_exp(ir)->is_const()) { this->remove_occ(RET_exp(ir)); } } break; case IR_GOTO: case IR_DO_WHILE: case IR_WHILE_DO: case IR_DO_LOOP: case IR_IF: case IR_LABEL: case IR_CASE: case IR_BREAK: case IR_CONTINUE: case IR_PHI: break; default: ASSERT0(0); } }
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); } } }