Esempio n. 1
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;
}
Esempio n. 2
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;
}
Esempio n. 3
0
//Before removing bb, revising phi opnd if there are phis
//in one of bb's successors.
void IRBB::removeSuccessorPhiOpnd(CFG<IRBB, IR> * cfg)
{
    IR_CFG * ircfg = (IR_CFG*)cfg;
    Region * ru = ircfg->get_ru();
    Vertex * vex = ircfg->get_vertex(BB_id(this));
    ASSERT0(vex);
    for (EdgeC * out = VERTEX_out_list(vex);
         out != NULL; out = EC_next(out)) {
        Vertex * succ_vex = EDGE_to(EC_edge(out));
        IRBB * succ = ircfg->get_bb(VERTEX_id(succ_vex));
        ASSERT0(succ);

        UINT const pos = ircfg->WhichPred(this, succ);

        for (IR * ir = BB_first_ir(succ);
             ir != NULL; ir = BB_next_ir(succ)) {
            if (!ir->is_phi()) { break; }

            ASSERT0(cnt_list(PHI_opnd_list(ir)) ==
                     cnt_list(VERTEX_in_list(succ_vex)));

            IR * opnd;
            UINT lpos = pos;
            for (opnd = PHI_opnd_list(ir);
                 lpos != 0; opnd = IR_next(opnd)) {
                ASSERT0(opnd);
                lpos--;
            }

            opnd->removeSSAUse();
            ((CPhi*)ir)->removeOpnd(opnd);
            ru->freeIRTree(opnd);
        }
    }
}
Esempio n. 4
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);
	}
}
Esempio n. 5
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);
	}
}
Esempio n. 6
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;
}
Esempio n. 7
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;
	}
}
Esempio n. 8
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;
}
Esempio n. 9
0
void IRBB::dump(Region * ru)
{
    if (g_tfile == NULL) { return; }

    g_indent = 0;

    fprintf(g_tfile, "\n----- BB%d ------", BB_id(this));
    if (get_lab_list().get_elem_count() > 0) {
        fprintf(g_tfile, "\nLABEL:");
        dumpBBLabel(get_lab_list(), g_tfile);
    }

    //Attributes
    fprintf(g_tfile, "\nATTR:");
    if (BB_is_entry(this)) {
        fprintf(g_tfile, "entry_bb ");
    }

    //if (BB_is_exit(this)) {
    //    fprintf(g_tfile, "exit_bb ");
    //}

    if (BB_is_fallthrough(this)) {
        fprintf(g_tfile, "fall_through ");
    }

    if (BB_is_target(this)) {
        fprintf(g_tfile, "branch_target ");
    }

    //IR list
    fprintf(g_tfile, "\nSTMT NUM:%d", getNumOfIR());
    g_indent += 3;
    TypeMgr * dm = ru->get_type_mgr();
    for (IR * ir = BB_first_ir(this);
        ir != NULL; ir = BB_irlist(this).get_next()) {
        ASSERT0(IR_next(ir) == NULL && IR_prev(ir) == NULL);
        ASSERT0(ir->get_bb() == this);
        dump_ir(ir, dm, NULL, true, true, false);
    }
    g_indent -= 3;
    fprintf(g_tfile, "\n");
    fflush(g_tfile);
}
Esempio n. 10
0
//Duplicate and add an operand that indicated by opnd_pos at phi stmt
//in one of bb's successors.
void IRBB::dupSuccessorPhiOpnd(CFG<IRBB, IR> * cfg, Region * ru, UINT opnd_pos)
{
    IR_CFG * ircfg = (IR_CFG*)cfg;
    Vertex * vex = ircfg->get_vertex(BB_id(this));
    ASSERT0(vex);
    for (EdgeC * out = VERTEX_out_list(vex);
         out != NULL; out = EC_next(out)) {
        Vertex * succ_vex = EDGE_to(EC_edge(out));
        IRBB * succ = ircfg->get_bb(VERTEX_id(succ_vex));
        ASSERT0(succ);

        for (IR * ir = BB_first_ir(succ);
             ir != NULL; ir = BB_next_ir(succ)) {
            if (!ir->is_phi()) { break; }

            ASSERT0(cnt_list(PHI_opnd_list(ir)) >= opnd_pos);

            IR * opnd;
            UINT lpos = opnd_pos;
            for (opnd = PHI_opnd_list(ir);
                 lpos != 0; opnd = IR_next(opnd)) {
                ASSERT0(opnd);
                lpos--;
            }

            IR * newopnd = ru->dupIRTree(opnd);
            if (opnd->is_read_pr()) {
                newopnd->copyRef(opnd, ru);
                ASSERT0(PR_ssainfo(opnd));
                PR_ssainfo(newopnd) = PR_ssainfo(opnd);
                SSA_uses(PR_ssainfo(newopnd)).append(newopnd);
            }

            ((CPhi*)ir)->addOpnd(newopnd);
        }
    }
}
Esempio n. 11
0
//Check that all basic blocks should only end with terminator IR.
void IRBB::verify()
{
    UINT c = 0;
    C<IR*> * ct;
    for (IR * ir = BB_irlist(this).get_head(&ct);
         ir != NULL; ir = BB_irlist(this).get_next(&ct)) {
        ASSERT0(IR_next(ir) == NULL && IR_prev(ir) == NULL);
        ASSERT0(ir->get_bb() == this);
        switch (IR_code(ir)) {
        case IR_ST:
        case IR_STPR:
        case IR_STARRAY:
        case IR_IST:
        case IR_PHI:
        case IR_REGION:
        case IR_CALL:
        case IR_ICALL:
        case IR_GOTO:
        case IR_IGOTO:
        case IR_TRUEBR:
        case IR_FALSEBR:
        case IR_RETURN:
        case IR_SWITCH:
            break;
        default: ASSERT(0, ("BB does not supported this kind of IR."));
        }

        if (ir->is_calls_stmt() || ir->is_cond_br() ||
            ir->is_multicond_br() || ir->is_uncond_br()) {
            ASSERT(ir == BB_last_ir(this), ("invalid bb boundary."));
        }

        c++;
    }
    ASSERT0(c == getNumOfIR());
}
Esempio n. 12
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();
}
Esempio n. 13
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);
    }
}
Esempio n. 14
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;
}
Esempio n. 15
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;
}
Esempio n. 16
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. 17
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;
}