//Return true if gvn is able to determine the result of 'ir'. bool IR_GVN::calc_cond_must_val(IN IR const* ir, bool & must_true, bool & must_false) { must_true = false; must_false = false; IS_TRUE0(ir->is_judge()); VN const* v1 = m_ir2vn.get(IR_id(BIN_opnd0(ir))); VN const* v2 = m_ir2vn.get(IR_id(BIN_opnd1(ir))); if (v1 == NULL || v2 == NULL) return false; switch (IR_type(ir)) { case IR_LT: case IR_GT: if (v1 == v2) { must_true = false; must_false = true; return true; } break; case IR_LE: case IR_GE: if (v1 == v2) { must_true = true; must_false = false; return true; } break; case IR_NE: if (v1 == v2) { must_true = false; must_false = true; return true; } if (v1 != v2) { must_true = true; must_false = false; return true; } IS_TRUE0(0); break; case IR_EQ: if (v1 == v2) { must_true = true; must_false = false; return true; } if (v1 != v2) { must_true = false; must_false = true; return true; } IS_TRUE0(0); break; case IR_LAND: case IR_LOR: case IR_LNOT: break; default: IS_TRUE0(0); } return false; }
/* Memory location may be parameter or global variable. 'emd': exact md */ VN * IR_GVN::alloc_livein_vn(IR const* exp, MD const* emd, bool & change) { VN * x = m_ir2vn.get(IR_id(exp)); if (x == NULL) { x = register_md_vn(emd); change = true; m_ir2vn.set(IR_id(exp), x); } return x; }
void IR_GVN::process_call(IR const* ir, bool & change) { for (IR const* p = CALL_param_list(ir); p != NULL; p = IR_next(p)) { comp_vn(p, change); } VN * x = m_ir2vn.get(IR_id(ir)); if (x == NULL) { x = new_vn(); VN_type(x) = VN_VAR; change = true; m_ir2vn.set(IR_id(ir), x); } return; }
//Compute VN for array according to anonymous domdef. VN * IR_GVN::comp_array_by_anon_domdef(IR const* arr, VN const* basevn, VN const* ofstvn, IR const* domdef, bool & change) { IS_TRUE0(IR_type(arr) == IR_ARRAY && m_du->is_may_def(domdef, arr, false)); ARR_VNE2VN * vnexp_map = m_def2arrtab.get(domdef); UINT dtsz = arr->get_dt_size(m_dm); VNE_ARR vexp(VN_id(basevn), VN_id(ofstvn), ARR_ofst(arr), dtsz); /* NOTE: foo(); array(v1); //s1 goo(); array(v1); //s2 vn of s1 should not same with s2. */ if (vnexp_map == NULL) { vnexp_map = new ARR_VNE2VN(m_pool, 16); //bsize to be evaluate. m_def2arrtab.set(domdef, vnexp_map); } VN * vn = vnexp_map->get(&vexp); if (vn == NULL) { vn = new_vn(); VN_type(vn) = VN_OP; VN_op(vn) = IR_ARRAY; vnexp_map->setv((OBJTY)&vexp, vn); } m_ir2vn.set(IR_id(arr), vn); change = true; return vn; }
//Compute VN for ild according to anonymous domdef. VN * IR_GVN::comp_ild_by_anon_domdef(IR const* ild, VN const* mlvn, IR const* domdef, bool & change) { IS_TRUE0(IR_type(ild) == IR_ILD && m_du->is_may_def(domdef, ild, false)); ILD_VNE2VN * vnexp_map = m_def2ildtab.get(domdef); UINT dtsz = ild->get_dt_size(m_dm); VNE_ILD vexp(VN_id(mlvn), ILD_ofst(ild), dtsz); /* NOTE: foo(); ild(v1); //s1 goo(); ild(v1); //s2 vn of s1 should not same with s2. */ if (vnexp_map == NULL) { vnexp_map = new ILD_VNE2VN(m_pool, 16); //bsize to be evaluate. m_def2ildtab.set(domdef, vnexp_map); } VN * ildvn = vnexp_map->get(&vexp); if (ildvn == NULL) { ildvn = new_vn(); VN_type(ildvn) = VN_OP; VN_op(ildvn) = IR_ILD; vnexp_map->setv((OBJTY)&vexp, ildvn); } m_ir2vn.set(IR_id(ild), ildvn); change = true; return ildvn; }
//Record IR list into 'irset'. void CfsMgr::recordStmt(IR * ir_list, BitSet & irset) { while (ir_list != NULL) { irset.bunion(IR_id(ir_list)); ir_list = ir_list->get_next(); } }
//Dump all IR expressions of region and its used MDs. void IR_EXPR_TAB::dump_ir_expr_tab() { if (g_tfile == NULL) return; fprintf(g_tfile, "\n==---- DUMP IR_EXPR_TAB ----=="); IR_DU_MGR * du_mgr = m_ru->get_du_mgr(); INT last = m_ir_expr_vec.get_last_idx(); for (INT i = 0; i <= last; i++) { ExpRep * ie = m_ir_expr_vec.get(i); if (ie == NULL) { continue; } ASSERT0(EXPR_id(ie) == (UINT)i); fprintf(g_tfile, "\n\n----------- ExpRep(%d)", i); dump_ir(EXPR_ir(ie), m_dm); fprintf(g_tfile, "\n\tOCC:"); for (IR * occ = EXPR_occ_list(ie).get_head(); occ != NULL; occ = EXPR_occ_list(ie).get_next()) { fprintf(g_tfile, "IR%d", IR_id(occ)); MDSet const* use_mds = du_mgr->get_may_use(occ); if (use_mds != NULL) { fprintf(g_tfile, "(use:"); use_mds->dump(m_ru->get_md_sys()); fprintf(g_tfile, ")"); } fprintf(g_tfile, ","); } } fflush(g_tfile); }
VN * IR_GVN::comp_sc_by_anon_domdef(IR const* exp, IR const* domdef, bool & change) { IS_TRUE0((IR_type(exp) == IR_LD || IR_type(exp) == IR_PR) && m_du->is_may_def(domdef, exp, false)); SCVNE2VN * vnexp_map = m_def2sctab.get(domdef); UINT dtsz = exp->get_dt_size(m_dm); MD const* md = exp->get_exact_ref(); IS_TRUE0(md); VNE_SC vexp(MD_id(md), exp->get_ofst(), dtsz); /* NOTE: foo(); v1; //s1 goo(); v1; //s2 vn of s1 should not same with s2. */ if (vnexp_map == NULL) { vnexp_map = new SCVNE2VN(m_pool, 16); //bsize to be evaluate. m_def2sctab.set(domdef, vnexp_map); } VN * vn = vnexp_map->get(&vexp); if (vn == NULL) { vn = new_vn(); VN_type(vn) = VN_VAR; vnexp_map->setv((OBJTY)&vexp, vn); } m_ir2vn.set(IR_id(exp), vn); change = true; return vn; }
//Record IR list into 'irset'. void CFS_MGR::record_ir_stmt(IR * ir_list, BITSET & irset) { while (ir_list != NULL) { irset.bunion(IR_id(ir_list)); ir_list = IR_next(ir_list); } }
VN * IR_GVN::comp_sc(IR const* exp, bool & change) { VN * evn = m_ir2vn.get(IR_id(exp)); if (evn != NULL) { return evn; } evn = comp_mem(exp, change); if (evn != NULL) { return evn; } DU_SET const* du = m_du->get_du_c(exp); IS_TRUE(du, ("This situation should be catched in comp_mem()")); IS_TRUE0(du->get_elem_count() > 0); IR const* exp_stmt = const_cast<IR*>(exp)->get_stmt(); IR const* domdef = m_du->find_dom_def(exp, exp_stmt, du, false); if (domdef == NULL) { return NULL; } if (domdef->is_stid() && ST_ofst(domdef) != exp->get_ofst()) { return NULL; } if (!domdef->is_stid() && !domdef->is_stpr()) { return comp_sc_by_anon_domdef(exp, domdef, change); } switch (IR_type(exp)) { case IR_LD: if (domdef->is_stpr() || (LD_idinfo(exp) != ST_idinfo(domdef))) { return NULL; } break; case IR_PR: if (domdef->is_stid() || PR_no(exp) != STPR_no(domdef)) { return NULL; } break; default: IS_TRUE(0, ("unsupport")); } VN * uni_vn = m_ir2vn.get(IR_id(domdef)); if (uni_vn == NULL) { uni_vn = new_vn(); VN_type(uni_vn) = VN_VAR; m_ir2vn.set(IR_id(domdef), uni_vn); } m_ir2vn.set(IR_id(exp), uni_vn); change = true; return uni_vn; }
//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; }
void IR_GVN::process_st(IR const* ir, bool & change) { if (IR_type(ir) == IR_IST) { if (IR_type(IST_base(ir)) == IR_ARRAY) { comp_array_addr_ref(ir, change); } else { comp_vn(IST_base(ir), change); } } VN * x = comp_vn(ir->get_rhs(), change); if (x == NULL) { return; } //IST's vn may be set by its dominated use-stmt ILD. if (m_ir2vn.get(IR_id(ir)) != x) { IS_TRUE0(m_ir2vn.get(IR_id(ir)) == NULL); m_ir2vn.set(IR_id(ir), x); change = true; } return; }
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 IR_GVN::dump_h1(IR const* k, VN * x) { fprintf(g_tfile, "\n\t%s", IRTNAME(IR_type(k))); if (k->is_pr()) { fprintf(g_tfile, "%d", PR_no(k)); } fprintf(g_tfile, " id:%d ", IR_id(k)); if (x != NULL) { fprintf(g_tfile, "vn%d", VN_id(x)); } else { fprintf(g_tfile, "--"); } }
CFS_INFO * CFS_MGR::map_ir2cfsinfo(IR * ir) { return m_map_ir2cfsinfo.get(IR_id(ir)); }
void CFS_MGR::set_map_ir2cfsinfo(IR * ir, CFS_INFO * ci) { m_map_ir2cfsinfo.set(IR_id(ir), ci); }
void IR_EXPR_TAB::set_map_ir2ir_expr(IR const* ir, ExpRep * ie) { m_map_ir2ir_expr.set(IR_id(ir), ie); }
//If 'ir' has been inserted in the table with an ExpRep, get that and return. ExpRep * IR_EXPR_TAB::map_ir2ir_expr(IR const* ir) { if (ir == NULL) return NULL; return m_map_ir2ir_expr.get(IR_id(ir)); }
void IR_GVN::dump_bb(UINT bbid) { if (g_tfile == NULL) { return; } IR_BB * bb = m_ru->get_bb(bbid); IS_TRUE0(bb); CIR_ITER ii; fprintf(g_tfile, "\n-- BB%d ", IR_BB_id(bb)); dump_bb_labs(IR_BB_lab_list(bb)); fprintf(g_tfile, "\n"); for (IR * ir = IR_BB_first_ir(bb); ir != NULL; ir = IR_BB_next_ir(bb)) { dump_ir(ir, m_ru->get_dm()); fprintf(g_tfile, "\n"); VN * x = m_ir2vn.get(IR_id(ir)); if (x != NULL) { fprintf(g_tfile, "vn%d", VN_id(x)); } fprintf(g_tfile, " <- {"); switch (IR_type(ir)) { case IR_ST: ii.clean(); for (IR const* k = ir_iter_init_c(ST_rhs(ir), ii); k != NULL; k = ir_iter_next_c(ii)) { VN * x = m_ir2vn.get(IR_id(k)); dump_h1(k, x); } break; case IR_STPR: ii.clean(); for (IR const* k = ir_iter_init_c(STPR_rhs(ir), ii); k != NULL; k = ir_iter_next_c(ii)) { VN * x = m_ir2vn.get(IR_id(k)); dump_h1(k, x); } break; case IR_IST: ii.clean(); for (IR const* k = ir_iter_init_c(IST_rhs(ir), ii); k != NULL; k = ir_iter_next_c(ii)) { VN * x = m_ir2vn.get(IR_id(k)); dump_h1(k, x); } ii.clean(); for (IR const* k = ir_iter_init_c(IST_base(ir), ii); k != NULL; k = ir_iter_next_c(ii)) { VN * x = m_ir2vn.get(IR_id(k)); dump_h1(k, x); } break; case IR_CALL: case IR_ICALL: { ii.clean(); for (IR const* k = ir_iter_init_c(CALL_param_list(ir), ii); k != NULL; k = ir_iter_next_c(ii)) { VN * x = m_ir2vn.get(IR_id(k)); dump_h1(k, x); } } break; case IR_TRUEBR: case IR_FALSEBR: ii.clean(); for (IR const* k = ir_iter_init_c(BR_det(ir), ii); k != NULL; k = ir_iter_next_c(ii)) { VN * x = m_ir2vn.get(IR_id(k)); dump_h1(k, x); } break; case IR_SWITCH: ii.clean(); for (IR const* k = ir_iter_init_c(SWITCH_vexp(ir), ii); k != NULL; k = ir_iter_next_c(ii)) { VN * x = m_ir2vn.get(IR_id(k)); dump_h1(k, x); } break; case IR_IGOTO: ii.clean(); for (IR const* k = ir_iter_init_c(IGOTO_vexp(ir), ii); k != NULL; k = ir_iter_next_c(ii)) { VN * x = m_ir2vn.get(IR_id(k)); dump_h1(k, x); } break; case IR_RETURN: ii.clean(); for (IR const* k = ir_iter_init_c(RET_exp(ir), ii); k != NULL; k = ir_iter_next_c(ii)) { VN * x = m_ir2vn.get(IR_id(k)); dump_h1(k, x); } break; case IR_GOTO: break; case IR_REGION: IS_TRUE0(0); //TODO break; default: IS_TRUE0(0); } fprintf(g_tfile, " }"); } fflush(g_tfile); }
void DUSet::removeDef(IR const* stmt, DefMiscBitSetMgr & m) { ASSERT0(stmt && stmt->is_stmt()); diff(IR_id(stmt), m); }
void DUSet::remove_use(IR const* exp, DefMiscBitSetMgr & m) { ASSERT0(exp && exp->is_exp()); diff(IR_id(exp), m); }
//Add define stmt with check if the stmt is unique in list. void DUSet::add_def(IR const* stmt, DefMiscBitSetMgr & m) { ASSERT0(stmt && stmt->is_stmt()); bunion(IR_id(stmt), m); }
//Add define stmt with check if the stmt is unique in list. void DUSet::add_use(IR const* exp, DefMiscBitSetMgr & m) { ASSERT0(exp && exp->is_exp()); bunion(IR_id(exp), m); }
//Only compute memory operation's vn. VN * IR_GVN::comp_mem(IR const* exp, bool & change) { IS_TRUE0(exp->is_memory_opnd()); MD const* emd = exp->get_exact_ref(); if (emd == NULL) { return NULL; } IR const* ed = m_du->get_exact_and_unique_def(exp); if (ed == NULL) { DU_SET const* defset = m_du->get_du_c(exp); if (defset == NULL) { return alloc_livein_vn(exp, emd, change); } else { //Check if some may-def or overlapped-def disrupts the emd. //Omit the DEF which has effect md and it does not overlapped //with emd. DU_ITER di; UINT defcount = 0; for (INT i = defset->get_first(&di); i >= 0; i = defset->get_next(i, &di), defcount++) { IR const* dir = m_ru->get_ir(i); IS_TRUE0(dir->is_stmt()); MD const* xd = m_du->get_must_def(dir); if (xd == NULL) { MD_SET const* xds = m_du->get_may_def(dir); if (xds != NULL && xds->is_contain(emd)) { IS_TRUE0(m_ir2vn.get(IR_id(exp)) == NULL); //exp's value is may defined, here we can not //determine if exp have an individual VN. return NULL; } } else { if (xd == emd || xd->is_overlap(emd)) { IS_TRUE0(m_ir2vn.get(IR_id(exp)) == NULL); //exp's value is defined by nonkilling define, //here we can not determine if exp have an //individual VN. return NULL; } } } if (defcount == 0) { return alloc_livein_vn(exp, emd, change); } } return alloc_livein_vn(exp, emd, change); } VN * defvn = NULL; IR const* exp_stmt = exp->get_stmt(); IS_TRUE0(exp_stmt->is_stmt()); IR_BB * b1 = ed->get_bb(); IR_BB * b2 = exp_stmt->get_bb(); IS_TRUE0(b1 && b2); if ((b1 != b2 && m_cfg->is_dom(IR_BB_id(b1), IR_BB_id(b2))) || (b1 == b2 && b1->is_dom(ed, exp_stmt, true))) { defvn = m_ir2vn.get(IR_id(ed)); } VN * ux = m_ir2vn.get(IR_id(exp)); if (defvn != ux) { m_ir2vn.set(IR_id(exp), defvn); change = true; } return defvn; }
VN * IR_GVN::comp_ild(IR const* exp, bool & change) { IS_TRUE0(IR_type(exp) == IR_ILD); VN * mlvn = comp_vn(ILD_base(exp), change); if (mlvn == NULL) { IS_TRUE0(m_ir2vn.get(IR_id(exp)) == NULL); IS_TRUE0(m_ir2vn.get(IR_id(ILD_base(exp))) == NULL); return NULL; } VN * evn = m_ir2vn.get(IR_id(exp)); if (evn != NULL) { return evn; } evn = comp_mem(exp, change); if (evn != NULL) { return evn; } DU_SET const* defset = m_du->get_du_c(exp); if (defset == NULL || defset->get_elem_count() == 0) { VN * v = register_tri_vn(IR_ILD, mlvn, register_int_vn(ILD_ofst(exp)), register_int_vn(exp->get_dt_size(m_dm))); m_ir2vn.set(IR_id(exp), v); return v; } IR const* exp_stmt = const_cast<IR*>(exp)->get_stmt(); IR const* domdef = m_stmt2domdef.get(exp_stmt); if (domdef == NULL) { domdef = m_du->find_dom_def(exp, exp_stmt, defset, false); if (domdef != NULL) { m_stmt2domdef.set(exp_stmt, domdef); } } if (domdef == NULL) { return NULL; } /* //ofst will be distinguished in comp_ild_by_anon_domdef(), so //we do not need to differentiate the various offset of ild and ist. if (IR_type(domdef) == IR_IST && !domdef->is_st_array() && IST_ofst(domdef) != ILD_ofst(exp)) { return NULL; } */ if (IR_type(domdef) != IR_IST || domdef->is_st_array() || IST_ofst(domdef) != ILD_ofst(exp)) { return comp_ild_by_anon_domdef(exp, mlvn, domdef, change); } //domdef is ist and the offset is matched. //Check if IR expression is match. VN const* mcvn = m_ir2vn.get(IR_id(IST_base(domdef))); if (mcvn == NULL || mcvn != mlvn) { return NULL; } VN * uni_vn = m_ir2vn.get(IR_id(domdef)); if (uni_vn == NULL) { uni_vn = register_tri_vn(IR_ILD, mlvn, register_int_vn(ILD_ofst(exp)), register_int_vn(exp->get_dt_size(m_dm))); m_ir2vn.set(IR_id(domdef), uni_vn); } m_ir2vn.set(IR_id(exp), uni_vn); change = true; return uni_vn; }
VN * IR_GVN::comp_vn(IR const* exp, bool & change) { IS_TRUE0(exp); switch (IR_type(exp)) { 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: //inclusive and & case IR_BOR: //inclusive or | case IR_XOR: //exclusive or case IR_LT: case IR_LE: case IR_GT: case IR_GE: case IR_EQ: //== case IR_NE: //!= case IR_ASR: case IR_LSR: case IR_LSL: { VN * vn1 = comp_vn(BIN_opnd0(exp), change); VN * vn2 = comp_vn(BIN_opnd1(exp), change); if (vn1 == NULL || vn2 == NULL) { if (m_ir2vn.get(IR_id(exp)) != NULL) { m_ir2vn.set(IR_id(exp), NULL); change = true; } return NULL; } VN * x = register_bin_vn((IR_TYPE)IR_type(exp), vn1, vn2); if (m_ir2vn.get(IR_id(exp)) != x) { m_ir2vn.set(IR_id(exp), x); change = true; } return x; } break; case IR_BNOT: //bitwise not case IR_LNOT: //logical not case IR_NEG: //negative { VN * x = comp_vn(UNA_opnd0(exp), change); if (x == NULL) { if (m_ir2vn.get(IR_id(exp)) != NULL) { m_ir2vn.set(IR_id(exp), NULL); change = true; } return NULL; } x = register_uni_vn((IR_TYPE)IR_type(exp), x); if (m_ir2vn.get(IR_id(exp)) != x) { m_ir2vn.set(IR_id(exp), x); change = true; } return x; } break; case IR_CVT: //type convertion { VN * x = comp_vn(CVT_exp(exp), change); if (x == NULL) { if (m_ir2vn.get(IR_id(exp)) != NULL) { m_ir2vn.set(IR_id(exp), NULL); change = true; } return NULL; } x = register_uni_vn((IR_TYPE)IR_type(exp), x); if (m_ir2vn.get(IR_id(exp)) != x) { m_ir2vn.set(IR_id(exp), x); change = true; } return x; } break; case IR_LDA: { IR const* ldabase = LDA_base(exp); VN * basevn; if (IR_type(ldabase) == IR_ID) { MD const* emd = ldabase->get_exact_ref(); if (emd == NULL) { //e.g: p = &"blabla", regard MD of "blabla" as inexact. IS_TRUE(ldabase->is_str(m_dm), ("only string's MD can be inexact.")); if (m_is_comp_lda_string) { emd = m_du->get_effect_use_md(ldabase); IS_TRUE(emd, ("string should have effect MD")); basevn = register_md_vn(emd); } else { basevn = NULL; } } else { IS_TRUE0(emd); basevn = register_md_vn(emd); } } else { basevn = comp_vn(LDA_base(exp), change); } if (basevn == NULL) { if (m_ir2vn.get(IR_id(exp)) != NULL) { m_ir2vn.set(IR_id(exp), NULL); change = true; } return NULL; } VN * ofstvn = register_int_vn(LDA_ofst(exp)); VN * x = register_bin_vn(IR_LDA, basevn, ofstvn); if (m_ir2vn.get(IR_id(exp)) != x) { m_ir2vn.set(IR_id(exp), x); change = true; } return x; } break; //case IR_ID: case IR_LD: case IR_PR: return comp_sc(exp, change); case IR_ARRAY: return comp_array(exp, change); case IR_ILD: return comp_ild(exp, change); case IR_CONST: { VN * x = m_ir2vn.get(IR_id(exp)); if (x != NULL) { return x; } if (exp->is_int(m_dm)) { x = register_int_vn(CONST_int_val(exp)); } else if (exp->is_fp(m_dm)) { if (!m_is_vn_fp) { return NULL; } x = register_fp_vn(CONST_fp_val(exp)); } else if (exp->is_str(m_dm)) { x = register_str_vn(CONST_str_val(exp)); } else { IS_TRUE(0, ("unsupport const type")); } IS_TRUE0(x); m_ir2vn.set(IR_id(exp), x); change = true; return x; } break; default: break; } return NULL; }
VN * IR_GVN::comp_array(IR const* exp, bool & change) { IS_TRUE0(IR_type(exp) == IR_ARRAY); for (IR const* s = ARR_sub_list(exp); s != NULL; s = IR_next(s)) { comp_vn(s, change); } VN * evn = m_ir2vn.get(IR_id(exp)); if (evn != NULL) { return evn; } evn = comp_mem(exp, change); if (evn != NULL) { return evn; } VN const* abase_vn = NULL; VN const* aofst_vn = NULL; if (((CARRAY*)exp)->get_dimn() == 1) { //only handle one dim array. abase_vn = comp_vn(ARR_base(exp), change); if (abase_vn == NULL) { return NULL; } aofst_vn = m_ir2vn.get(IR_id(ARR_sub_list(exp))); if (aofst_vn == NULL) { return NULL; } } else { return NULL; } DU_SET const* du = m_du->get_du_c(exp); if (du == NULL || du->get_elem_count() == 0) { //Array does not have any DEF. VN * x = register_qua_vn(IR_ARRAY, abase_vn, aofst_vn, register_int_vn(ARR_ofst(exp)), register_int_vn(exp->get_dt_size(m_dm))); if (m_ir2vn.get(IR_id(exp)) != x) { m_ir2vn.set(IR_id(exp), x); change = true; } return x; } IR const* exp_stmt = const_cast<IR*>(exp)->get_stmt(); IS_TRUE0(exp_stmt->is_stmt()); IR const* domdef = m_du->find_dom_def(exp, exp_stmt, du, false); if (domdef == NULL) { return NULL; } if (domdef->is_st_array() && IST_ofst(domdef) != ARR_ofst(exp)) { return NULL; } if (!domdef->is_st_array()) { return comp_array_by_anon_domdef(exp, abase_vn, aofst_vn, domdef, change); } IS_TRUE0(IR_type(domdef) == IR_IST); //Check if VN expression is match. IR const* narr = IST_base(domdef); IS_TRUE(((CARRAY*)narr)->get_dimn() == 1, ("only handle one dim array.")); VN const* b = m_ir2vn.get(IR_id(ARR_base(narr))); if (b == NULL || b != abase_vn) { return NULL; } VN const* o = m_ir2vn.get(IR_id(ARR_sub_list(narr))); if (o == NULL || o != aofst_vn) { return NULL; } VN * uni_vn = m_ir2vn.get(IR_id(domdef)); if (uni_vn == NULL) { uni_vn = register_qua_vn(IR_ARRAY, abase_vn, aofst_vn, register_int_vn(ARR_ofst(exp)), register_int_vn(exp->get_dt_size(m_dm))); m_ir2vn.set(IR_id(domdef), uni_vn); m_ir2vn.set(IR_id(narr), uni_vn); } m_ir2vn.set(IR_id(exp), uni_vn); change = true; return uni_vn; }