Exemplo n.º 1
0
void IR_GVN::comp_array_addr_ref(IR const* ir, bool & change)
{
	IS_TRUE0(ir->is_st_array());
	IR const* arr = IST_base(ir);
	comp_vn(ARR_base(arr), change);

	for (IR const* s = ARR_sub_list(arr); s != NULL; s = IR_next(s)) {
		comp_vn(s, change);
	}
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
//Check and replace 'exp' with 'cand_expr' if they are
//equal, and update SSA info. If 'cand_expr' is NOT leaf,
//that will create redundant computation, and
//depends on later Redundancy Elimination to reverse back.
//
//'cand_expr': substitute cand_expr for exp.
//    e.g: exp is pr1 of S2, cand_expr is 10.
//        pr1 = 10 //S1
//        g = pr1 //S2
//    =>
//        pr1 = 10
//        g = 10
//
//NOTE: Do NOT handle stmt.
void IR_CP::replaceExpViaSSADu(IR * exp, IR const* cand_expr,
                                    IN OUT CPCtx & ctx)
{
    ASSERT0(exp && exp->is_exp() && cand_expr && cand_expr->is_exp());
    ASSERT0(exp->get_exact_ref());

    if (!checkTypeConsistency(exp, cand_expr)) {
        return;
    }

    IR * parent = IR_parent(exp);
    if (parent->is_ild()) {
        CPC_need_recomp_aa(ctx) = true;
    } else if (parent->is_ist() && exp == IST_base(parent)) {
        if (!cand_expr->is_ld() &&
            !cand_expr->is_pr() &&
            !cand_expr->is_lda()) {
            return;
        }
        CPC_need_recomp_aa(ctx) = true;
    }

    IR * newir = m_ru->dupIRTree(cand_expr);

    if (cand_expr->is_read_pr() && PR_ssainfo(cand_expr) != NULL) {
        PR_ssainfo(newir) = PR_ssainfo(cand_expr);
        SSA_uses(PR_ssainfo(newir)).append(newir);
    } else {
        m_du->copyIRTreeDU(newir, cand_expr, true);
    }

    //cand_expr may be IR tree. And there might be PR or LD on the tree.
    newir->copyRefForTree(cand_expr, m_ru);

    //Add SSA use for new exp.
    SSAInfo * cand_ssainfo = NULL;
    if ((cand_ssainfo = cand_expr->get_ssainfo()) != NULL) {
        SSA_uses(cand_ssainfo).append(newir);
    }

    //Remove old exp SSA use.
    SSAInfo * exp_ssainfo = exp->get_ssainfo();
    ASSERT0(exp_ssainfo);
    ASSERT0(SSA_uses(exp_ssainfo).find(exp));
    SSA_uses(exp_ssainfo).remove(exp);

    CPC_change(ctx) = true;

    ASSERT0(exp->get_stmt());
    bool doit = parent->replaceKid(exp, newir, false);
    ASSERT0(doit);
    UNUSED(doit);
    m_ru->freeIRTree(exp);
}
Exemplo n.º 4
0
//Check and replace 'ir' with 'cand_expr' if they are
//equal, and update DU info. If 'cand_expr' is NOT leaf,
//that will create redundant computation, and
//depends on later Redundancy Elimination to reverse back.
//exp: expression which will be replaced.
//
//cand_expr: substitute cand_expr for exp.
//    e.g: cand_expr is *p, cand_expr_md is MD3
//        *p(MD3) = 10 //p point to MD3
//        ...
//        g = *q(MD3) //q point to MD3
//
//exp_use_ssadu: true if exp used SSA du info.
//
//NOTE: Do NOT handle stmt.
void IR_CP::replaceExp(IR * exp, IR const* cand_expr,
                        IN OUT CPCtx & ctx, bool exp_use_ssadu)
{
    ASSERT0(exp && exp->is_exp() && cand_expr);
    ASSERT0(exp->get_exact_ref());

    if (!checkTypeConsistency(exp, cand_expr)) {
        return;
    }

    IR * parent = IR_parent(exp);
    if (parent->is_ild()) {
        CPC_need_recomp_aa(ctx) = true;
    } else if (parent->is_ist() && exp == IST_base(parent)) {
        if (!cand_expr->is_ld() && !cand_expr->is_pr() && !cand_expr->is_lda()) {
            return;
        }
        CPC_need_recomp_aa(ctx) = true;
    }

    IR * newir = m_ru->dupIRTree(cand_expr);
    m_du->copyIRTreeDU(newir, cand_expr, true);

    ASSERT0(cand_expr->get_stmt());
    if (exp_use_ssadu) {
        //Remove exp SSA use.
        ASSERT0(exp->get_ssainfo());
        ASSERT0(exp->get_ssainfo()->get_uses().find(exp));

        exp->removeSSAUse();
    } else {
        m_du->removeUseOutFromDefset(exp);
    }
    CPC_change(ctx) = true;

    ASSERT0(exp->get_stmt());
    bool doit = parent->replaceKid(exp, newir, false);
    ASSERT0(doit);
    UNUSED(doit);
    m_ru->freeIRTree(exp);
}
Exemplo n.º 5
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_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();
}
Exemplo n.º 6
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_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);
    }
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
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);
}