Ejemplo n.º 1
0
/* Hoist det of loop.
e.g: while (a=10,b+=3,c<a) {
		IR-LIST;
	 }

be replaced by

	 a = 10;
	 b += 3;
	 while (c<a) {
		IR-LIST;
		a = 10;
	    b += 3;
	 } */
bool IR_CFS_OPT::hoist_loop(IR ** head, IR * ir)
{
	IS_TRUE(IR_type(ir)==IR_DO_WHILE ||
		    IR_type(ir)==IR_WHILE_DO ||
			IR_type(ir)==IR_DO_LOOP, ("need LOOP"));
	IS_TRUE(LOOP_det(ir), ("DET is NULL"));
	IR * det = LOOP_det(ir);

	INT i = 0;
	while (det != NULL) {
		i++;
		det = IR_next(det);
	}

	IR * new_list = NULL, * new_body_list = NULL;
	if (i > 1) {
		det = LOOP_det(ir);
		while (i > 1) {
			IR * c = det;
			IS_TRUE(c->is_stmt(), ("Non-stmt ir should be remove "
								   "during reshape_ir_tree()"));
			det = IR_next(det);
			remove(&LOOP_det(ir), c);
			add_next(&new_list, c);
			i--;
		}
		new_body_list = m_ru->dup_irs_list(new_list);
		insertbefore(head, ir, new_list);
		add_next(&LOOP_body(ir), new_body_list);
		return true;
	}
	return false;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
/* Canonicalize det of IF.
e.g: if (a=10,b+=3,c<a) {...}
be replaced by
	 a = 10;
	 b += 3;
	 if (c<a) {...} */
bool IR_CFS_OPT::hoist_if(IR ** head, IR * ir)
{
	IS_TRUE(IR_type(ir) == IR_IF, ("need IF"));
	IS_TRUE(IF_det(ir), ("DET is NULL"));

	IR * det = IF_det(ir);
	INT i = 0;
	while (det != NULL) {
		i++;
		det = IR_next(det);
	}

	IR * new_list = NULL;
	if (i > 1) {
		det = IF_det(ir);
		while (i > 1) {
			IR * c = det;
			IS_TRUE(c->is_stmt(),
				("Non-stmt ir should be remove during reshape_ir_tree()"));
			det = IR_next(det);
			remove(&IF_det(ir), c);
			add_next(&new_list, c);
			i--;
		}
		insertbefore(head, ir, new_list);
		return true;
	}
	return false;
}
Ejemplo n.º 7
0
/*
Control flow struct optimizations.
Transform follow struct to do-while loop

	LABEL:
	IR-LIST
	IF DET
	   GOTO LABEL
	   ...(DEAD CODE)
	ELSE
	   FALSE-PART
	ENDIF

is replace by

	DO {
		IR-LIST
	} WHILE DET
	FALSE-PART
*/
bool IR_CFS_OPT::trans_to_do_while_loop(IR ** head, IR * ir)
{
	IS_TRUE(head != NULL && *head != NULL, ("invalid parameter"));
	if (ir->is_lab()) {
		IR * t = ir;
		LABEL_INFO * li = LAB_lab(ir);
		while (t != NULL) {
			if (IR_type(t) == IR_IF) {
				if (IF_truebody(t) != NULL &&
					IR_type(IF_truebody(t)) == IR_GOTO &&
					is_same_label(LAB_lab(ir), GOTO_lab(IF_truebody(t)))) {

					//start transform...
					IR * dowhile = m_ru->new_ir(IR_DO_WHILE);
					LOOP_det(dowhile) = m_ru->dup_irs(LOOP_det(t));

					IR * if_stmt = t;
					t = IR_next(ir);
					while (t != NULL && t != if_stmt) {
						IR * c = t;
						t = IR_next(t);
						remove(head, c);
						add_next(&LOOP_body(dowhile), c);
					}
					IS_TRUE(t == if_stmt, ("???"));
					remove(head, if_stmt);
					if (IF_falsebody(if_stmt)) {
						add_next(&dowhile, IF_falsebody(if_stmt));
						IF_falsebody(if_stmt) = NULL;
					}
					insertafter(&ir, dowhile);
					m_ru->free_irs(if_stmt); //free IF
					remove(head, ir);
					m_ru->free_irs(ir); //free LABEL
					return true;
				}
			}
			t = IR_next(t);
		}
	}
	return false;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
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, "--");
	}
}
Ejemplo n.º 10
0
ExpRep * IR_EXPR_TAB::encode_expr(IN IR * ir)
{
	if (ir == NULL) return NULL;

	ASSERT0(ir->is_exp());
	switch (IR_type(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;
}
Ejemplo n.º 11
0
//ONLY used in this file
bool IR_CFS_OPT::is_non_branch_ir(IR * ir)
{
	if (ir == NULL) {
		return false;
	}
	switch (IR_type(ir)) {
	case IR_ST:          //store
	case IR_IST:         //indirective store
	case IR_CALL:
	case IR_ICALL:       //indirective call
    	return true;
	default:
		return false;
	}
	return false;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
0
UINT IR_EXPR_TAB::compute_hash_key(IR const* ir)
{
	ASSERT0(ir != NULL);
	UINT hval = IR_type(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;
}
Ejemplo n.º 14
0
/* The followed forms

	if (cond) {

	} else {
		IR-list
	}

is replaced by

	if (!cond) {
		IR-list
	} */
bool IR_CFS_OPT::trans_if2(IR ** head, IR * ir)
{
	IS_TRUE(head && *head, ("invalid parameter"));
	if (ir == NULL || IR_type(ir) != IR_IF) { return false; }

	//Check true part
	if (!IF_truebody(ir)) {
		if (IF_falsebody(ir) == NULL) {
			remove(head, ir);
			m_ru->free_irs(ir);
			return true;
		}
		m_ru->invert_cond(&IF_det(ir));
		IF_truebody(ir) = IF_falsebody(ir);
		IF_falsebody(ir) = NULL;
		return true;
	}

	return false;
}
Ejemplo n.º 15
0
void IR_GVN::process_bb(IR_BB * bb, bool & change)
{
	C<IR*> * ct;
	for (IR * ir = IR_BB_ir_list(bb).get_head(&ct);
		 ir != NULL; ir = IR_BB_ir_list(bb).get_next(&ct)) {
		switch (IR_type(ir)) {
		case IR_ST:
		case IR_STPR:
		case IR_IST:
			process_st(ir, change);
			break;
		case IR_CALL:
		case IR_ICALL:
			process_call(ir, change);
			break;
		case IR_TRUEBR:
		case IR_FALSEBR:
			comp_vn(BR_det(ir), change);
			break;
		case IR_SWITCH:
			comp_vn(SWITCH_vexp(ir), change);
			break;
		case IR_IGOTO:
			comp_vn(IGOTO_vexp(ir), change);
			break;
		case IR_RETURN:
			comp_vn(RET_exp(ir), change);
			break;
		case IR_REGION:
			process_region(ir, change);
			break;
		case IR_PHI:
			process_phi(ir, change);
			break;
		case IR_GOTO: break;
		default: IS_TRUE0(0);
		}
	}
}
Ejemplo n.º 16
0
	void handle_ld(IR * ld, MD2MDS * mx)
	{
		IS_TRUE0(IR_type(ld) == IR_LD && mx);
		IR_AI * ai = IR_ai(ld);
		if (ai == NULL) { return; }

		TBAA_AI * ty = (TBAA_AI*)ai->get(IRAI_TBAA);
		if (ty == NULL) { return; }

		MD * md = m_tyid2md.get(ty->tyid);
		if (md != NULL) {
			MD const* t = alloc_ld_md(ld);
			set_point_to_set_add_md(t, *mx, md);
			return;
		}

		CHAR buf[64];
		sprintf(buf, "dummy%d", ty->tyid);
		VAR * dummy = m_var_mgr->register_var(buf,
											D_MC, D_UNDEF,
											0, 1, 1, VAR_GLOBAL);
		VAR_is_addr_taken(dummy) = true;
		VAR_allocable(dummy) = false;
		m_ru->add_to_var_tab(dummy);

		MD dummy_md;
		MD_base(&dummy_md) = dummy;
		MD_size(&dummy_md) = 0;
		MD_ty(&dummy_md) = MD_UNBOUND;
		MD_is_addr_taken(&dummy_md) = true;
		MD * entry = m_md_sys->register_md(dummy_md);
		m_tyid2md.set(ty->tyid, entry);

		MD const* t = alloc_ld_md(ld);
		set_point_to_set_add_md(t, *mx, entry);
	}
Ejemplo n.º 17
0
/* 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_type(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();
}
Ejemplo n.º 18
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;
}
Ejemplo n.º 19
0
//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_type(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);
	}
}
Ejemplo n.º 20
0
/* The followed forms
	x is signed
		IF(x > 0x7FFFFFFF) {a=1} ELSE {b=1}   =>  b=1
		IF(x < 0x80000000) {a=1} ELSE {b=1}   =>  b=1

	x is unsigned
		IF(x > 0xFFFFFFFF){a=1} ELSE {b=1}   =>  b=1
		IF(x < 0x0) {a=1} ELSE {b=1}         =>  b=1 */
bool IR_CFS_OPT::trans_if3(IR ** head, IR * ir)
{
	IS_TRUE(head && *head, ("invalid parameter"));
	if (ir == NULL || IR_type(ir) != IR_IF) { return false; }

	IR * det = IF_det(ir);
	if (IR_type(det) == IR_GT) {
		IR * opnd0 = BIN_opnd0(det);
		IR * opnd1 = BIN_opnd1(det);
		DTD const* op0_rty = opnd0->get_dtd(m_dm);
		DTD const* op1_rty = opnd1->get_dtd(m_dm);

		if (IR_type(opnd0) == IR_LD &&
			opnd1->is_const() &&
			opnd0->is_int(m_dm) &&
			CONST_int_val(opnd1) == MAX_INT_VALUE) {
			//x is signed, if(x>0x7FFFFFFF) {a=1} else {b=1} =>  b=1
			IR * new_ir = NULL;
			if (IF_falsebody(ir)) {
				new_ir = m_ru->dup_irs(IF_falsebody(ir));
			}
			replace(head, ir, new_ir);

			//Revise IR_parent.
			IR_parent(new_ir) = IR_parent(ir);

			m_ru->free_irs(ir);
			return true;
		} else if (IR_type(opnd0) == IR_LD &&
				   IR_is_const(opnd1) &&
				   opnd0->is_uint(m_dm) &&
				   CONST_int_val(opnd1) == MAX_UINT_VALUE) {
			//x is unsigned, if(x>0xFFFFFFFF) {a=1} else {b=1} => b=1
			IR * new_ir = NULL;
			if (IF_falsebody(ir)) {
				new_ir = m_ru->dup_irs(IF_falsebody(ir));
			}

			replace(head, ir, new_ir);

			//Revise IR_parent.
			IR_parent(new_ir) = IR_parent(ir);

			m_ru->free_irs(ir);
			return true;
		}
	} else if (IR_type(det) == IR_LT) {
		IR * opnd0 = BIN_opnd0(det);
		IR * opnd1 = BIN_opnd1(det);
		DTD const* op0_rty = opnd0->get_dtd(m_dm);
		DTD const* op1_rty = opnd1->get_dtd(m_dm);
		if (IR_type(opnd0) == IR_LD &&
			IR_is_const(opnd1) &&
			opnd0->is_int(m_dm) &&
			CONST_int_val(opnd1) == MIN_INT_VALUE) {
			//x is signed, IF(x < 0x80000000) {a=1} ELSE {b=1}  =>  b=1
			IR * new_ir = NULL;
			if (IF_falsebody(ir)) {
				new_ir = m_ru->dup_irs(IF_falsebody(ir));
			}
			replace(head, ir, new_ir);
			m_ru->free_irs(ir);
			return true;
		} else if (IR_type(opnd0) == IR_LD &&
					IR_is_const(opnd1) &&
					opnd0->is_uint(m_dm) &&
					CONST_int_val(opnd1) == 0) {
			//x is unsigned, if(x<0) {a=1} else {b=1}  =>  b=1
			IR * new_ir = NULL;
			if (IF_falsebody(ir)) {
				new_ir = m_ru->dup_irs(IF_falsebody(ir));
			}
			replace(head, ir, new_ir);

			//Revise IR_parent.
			IR_parent(new_ir) = IR_parent(ir);

			m_ru->free_irs(ir);
			return true;
		}
	}

	return false;
}
Ejemplo n.º 21
0
bool IR_CFS_OPT::perform_cfs_optimization(IN OUT IR ** ir_list,
										  IN SIMP_CTX const& sc)
{
	bool change = false;

	for (IR * ir = *ir_list; ir != NULL;) {
		if (trans_to_do_while_loop(ir_list, ir)) {
			change = true;
			ir = *ir_list;
			continue;
		}

		if (IR_type(ir) == IR_IF && trans_if1(ir_list, ir)) {
			change = true;
			ir = *ir_list;
			continue;
		}

		if (IR_type(ir) == IR_IF && trans_if2(ir_list, ir)) {
			change = true;
			ir = *ir_list;
			continue;
		}

		if (IR_type(ir) == IR_IF && trans_if3(ir_list, ir)) {
			change = true;
			ir = *ir_list;
			continue;
		}

		switch (IR_type(ir)) {
		case IR_IF:
			if (hoist_if(ir_list, ir)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			if (perform_cfs_optimization(&IF_truebody(ir), sc)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			if (perform_cfs_optimization(&IF_falsebody(ir), sc)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			break;
		case IR_DO_WHILE:
		case IR_WHILE_DO:
		case IR_DO_LOOP:
			if (hoist_loop(ir_list, ir)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			if (perform_cfs_optimization(&LOOP_body(ir), sc)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			break;
		case IR_SWITCH:
			if (perform_cfs_optimization(&SWITCH_body(ir), sc)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			break;
		default:;
		} //end switch

		 ir = IR_next(ir);
	}
	return change;
}
Ejemplo n.º 22
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);
}
Ejemplo n.º 23
0
/* The followed forms
	if (cond) {
		t=1
		a=1
		goto L1;
	}
	f=1
	goto L2;
	L1:

is replaced by

	if (!cond) {
		f=1
		goto L2;
	}
	t=1
	a=1
	L1:

'goto L1' is removed and free, and L1 is removed if it is not a target
of some other instruction. */
bool IR_CFS_OPT::trans_if1(IR ** head, IR * ir)
{
	IS_TRUE(head && *head, ("invalid parameter"));

	if (ir == NULL || IR_type(ir) != IR_IF) { return false; }

	//Check true part.
	IR * t = IF_truebody(ir);
	while (t != NULL) {
		if (!is_non_branch_ir(t)) {
			break;
		}
		t = IR_next(t);
	}

	if (t != NULL && IR_next(t) == NULL && IR_type(t) == IR_GOTO) {
		IR * first_goto = t;
		t = IR_next(ir);
		while (t != NULL) {
			if (!is_non_branch_ir(t)) break;
			t = IR_next(t);
		}

		if (t != NULL && IR_type(t) == IR_GOTO) {
			IR * second_goto = t;
			if (IR_next(second_goto) != NULL &&
				IR_next(second_goto)->is_lab() &&
				is_same_label(GOTO_lab(first_goto),
							  LAB_lab(IR_next(second_goto)))) {

				//Here we start to transform...
				m_ru->invert_cond(&IF_det(ir));
				IR * new_list1 = NULL;
				IR * new_list2 = NULL;

				t = IF_truebody(ir);

				//Split true body of IF.
				IR * last = NULL;
				while (t != first_goto) {
					IR * c = t;
					t = IR_next(t);
					remove(&IF_truebody(ir), c);
					add_next(&new_list1, &last, c);
				}
				IS_TRUE(t && t == first_goto, ("invalid control flow"));

				remove(&IF_truebody(ir), first_goto);
				m_ru->free_irs(first_goto);

				//Split all irs between IF and L1.
				t = IR_next(ir);
				while (t != second_goto) {
					IR * c = t;
					t = IR_next(t);
					remove(head, c);
					add_next(&new_list2, c);
				}
				IS_TRUE(t != NULL && t == second_goto, ("???"));
				remove(head, second_goto);
				add_next(&new_list2, second_goto);

				//Swap new_list1 and new_list2
				insertbefore(&IF_truebody(ir), IF_truebody(ir), new_list2);

				//Update the IR_parent for new_list2.
				for (IR * tmp = new_list2; tmp != NULL; tmp = IR_next(tmp)) {
					IR_parent(tmp) = ir;
				}

				IS_TRUE(IF_truebody(ir) == new_list2,
						("illegal insertbefore<T>"));

				insertafter(&ir, new_list1);

				//Update the IR_parent for new_list1.
				for (IR * tmp = new_list1; tmp != NULL; tmp = IR_next(tmp)) {
					IR_parent(tmp) = IR_parent(ir);
				}
				return true;
			}
		}
	}

	return false;
}
Ejemplo n.º 24
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;
}
Ejemplo n.º 25
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;
}