Esempio n. 1
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);
}
Esempio n. 2
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);
}
Esempio n. 3
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::transformIf3(IR ** head, IR * ir)
{
    ASSERT(head && *head, ("invalid parameter"));
    if (ir == NULL || !ir->is_if()) { return false; }

    IR * det = IF_det(ir);
    if (det->is_gt()) {
        IR * opnd0 = BIN_opnd0(det);
        IR * opnd1 = BIN_opnd1(det);
        if (opnd0->is_ld() &&
            opnd0->is_int() &&
            opnd1->is_const() &&
            opnd1->is_int() &&
            m_ru->getIntegerInDataTypeValueRange(opnd1) ==
              m_ru->getMaxInteger(m_tm->get_dtype_bitsize(
                TY_dtype(opnd1->get_type())), opnd1->is_signed())) {
            //e.g:
            //x is unsigned, if(x>0xFFFFFFFF) {a=1} else {b=1} => b=1
            //x is signed, if(x>0x7FFFFFFF) {a=1} else {b=1} =>  b=1
            IR * allocIR = NULL;
            if (IF_falsebody(ir) != NULL) {
                allocIR = m_ru->dupIRTree(IF_falsebody(ir));
            }

            xcom::replace(head, ir, allocIR);

            if (allocIR != NULL) {
                IR_parent(allocIR) = IR_parent(ir);
            }

            m_ru->freeIRTree(ir);
            return true;
        }
    } else if (det->is_lt()) {
        IR * opnd0 = BIN_opnd0(det);
        IR * opnd1 = BIN_opnd1(det);
        if (opnd0->is_ld() &&
            opnd0->is_int() &&
            opnd1->is_const() &&
            opnd1->is_int() &&
            m_ru->getIntegerInDataTypeValueRange(opnd1) ==
              m_ru->getMinInteger(m_tm->get_dtype_bitsize(
                TY_dtype(opnd1->get_type())), opnd1->is_signed())) {
            //x is signed, IF(x < 0x80000000) {a=1} ELSE {b=1}  =>  b=1
            IR * allocIR = NULL;
            if (IF_falsebody(ir) != NULL) {
                allocIR = m_ru->dupIRTree(IF_falsebody(ir));
            }

            xcom::replace(head, ir, allocIR);

            if (allocIR != NULL) {
                IR_parent(allocIR) = IR_parent(ir);
            }

            m_ru->freeIRTree(ir);
            return true;
        } else if (opnd0->is_ld() &&
                   opnd1->is_const() &&
                   opnd0->is_uint() &&
                   CONST_int_val(opnd1) == 0) {
            //x is unsigned, if(x<0) {a=1} else {b=1}  =>  b=1
            IR * allocIR = NULL;
            if (IF_falsebody(ir) != NULL) {
                allocIR = m_ru->dupIRTree(IF_falsebody(ir));
            }

            xcom::replace(head, ir, allocIR);

            if (allocIR != NULL) {
                IR_parent(allocIR) = IR_parent(ir);
            }

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

    return false;
}
Esempio n. 4
0
//The followed forms
//   if (cond) {
//       t=1
//       a=1
//       goto L1;
//   }
//   f=1
//   goto L2;
//   L1:
//
//is replaced with
//
//   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::transformIf1(IR ** head, IR * ir)
{
    ASSERT(head && *head, ("invalid parameter"));

    if (ir == NULL || !ir->is_if()) { return false; }

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

    if (t != NULL && t->get_next() == NULL && t->is_goto()) {
        IR * first_goto = t;
        t = ir->get_next();
        while (t != NULL) {
            if (!is_non_branch_ir(t)) { break; }
            t = t->get_next();
        }

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

                //Start transforming.
                m_ru->invertCondition(&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 = t->get_next();
                    xcom::remove(&IF_truebody(ir), c);
                    xcom::add_next(&new_list1, &last, c);
                }
                ASSERT(t && t == first_goto, ("invalid control flow"));

                xcom::remove(&IF_truebody(ir), first_goto);
                m_ru->freeIRTree(first_goto);

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

                //Swap new_list1 and new_list2
                xcom::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;
                }

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

                xcom::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;
}
Esempio n. 5
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;
}
Esempio n. 6
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;
}