Beispiel #1
0
//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;
}
Beispiel #2
0
/*
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
//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;
}
Beispiel #5
0
//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;
}
Beispiel #6
0
//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();
    }
}
Beispiel #7
0
//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);
}
Beispiel #8
0
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;
}
Beispiel #9
0
//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);
	}
}
Beispiel #10
0
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;
}
Beispiel #11
0
//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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
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;
	}
}
Beispiel #14
0
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, "--");
	}
}
Beispiel #15
0
CFS_INFO * CFS_MGR::map_ir2cfsinfo(IR * ir)
{
	return m_map_ir2cfsinfo.get(IR_id(ir));
}
Beispiel #16
0
void CFS_MGR::set_map_ir2cfsinfo(IR * ir, CFS_INFO * ci)
{
	m_map_ir2cfsinfo.set(IR_id(ir), ci);
}
Beispiel #17
0
void IR_EXPR_TAB::set_map_ir2ir_expr(IR const* ir, ExpRep * ie)
{
    m_map_ir2ir_expr.set(IR_id(ir), ie);
}
Beispiel #18
0
//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));
}
Beispiel #19
0
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);
}
Beispiel #20
0
void DUSet::removeDef(IR const* stmt, DefMiscBitSetMgr & m)
{
    ASSERT0(stmt && stmt->is_stmt());
    diff(IR_id(stmt), m);
}
Beispiel #21
0
void DUSet::remove_use(IR const* exp, DefMiscBitSetMgr & m)
{
    ASSERT0(exp && exp->is_exp());
    diff(IR_id(exp), m);
}
Beispiel #22
0
//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);
}
Beispiel #23
0
//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);
}
Beispiel #24
0
//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;
}
Beispiel #25
0
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;
}
Beispiel #26
0
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;
}
Beispiel #27
0
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;
}