Beispiel #1
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->is_single());
        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 (is_bb_down_boundary(ir)) {
            ASSERT(ir == BB_last_ir(this), ("invalid BB down boundary."));
        }

        c++;
    }
    ASSERT0(c == getNumOfIR());
}
Beispiel #2
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 #3
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);
}
Beispiel #4
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();
}
Beispiel #5
0
//'usevec': for local used.
bool IR_CP::doProp(IN IRBB * bb, Vector<IR*> & usevec)
{
    bool change = false;
    C<IR*> * cur_iter, * next_iter;

    for (BB_irlist(bb).get_head(&cur_iter),
         next_iter = cur_iter; cur_iter != NULL; cur_iter = next_iter) {

        IR * def_stmt = cur_iter->val();

        BB_irlist(bb).get_next(&next_iter);

        if (!is_copy(def_stmt)) { continue; }

        DUSet const* useset = NULL;
        UINT num_of_use = 0;
        SSAInfo * ssainfo = NULL;
        bool ssadu = false;
        if ((ssainfo = def_stmt->get_ssainfo()) != NULL &&
            SSA_uses(ssainfo).get_elem_count() != 0) {
            //Record use_stmt in another vector to facilitate this function
            //if it is not in use-list any more after copy-propagation.
            SEGIter * sc;
            for    (INT u = SSA_uses(ssainfo).get_first(&sc);
                 u >= 0; u = SSA_uses(ssainfo).get_next(u, &sc)) {
                IR * use = m_ru->get_ir(u);
                ASSERT0(use);
                usevec.set(num_of_use, use);
                num_of_use++;
            }
            ssadu = true;
        } else if (def_stmt->get_exact_ref() == NULL &&
                   !def_stmt->is_void()) {
            //Allowing copy propagate exact or VOID value.
            continue;
        } else if ((useset = def_stmt->readDUSet()) != NULL &&
                   useset->get_elem_count() != 0) {
            //Record use_stmt in another vector to facilitate this function
            //if it is not in use-list any more after copy-propagation.
            DUIter di = NULL;
            for (INT u = useset->get_first(&di);
                 u >= 0; u = useset->get_next(u, &di)) {
                IR * use = m_ru->get_ir(u);
                usevec.set(num_of_use, use);
                num_of_use++;
            }
        } else  {
            continue;
        }

        IR const* prop_value = get_propagated_value(def_stmt);

        for (UINT i = 0; i < num_of_use; i++) {
            IR * use = usevec.get(i);
            ASSERT0(use->is_exp());
            IR * use_stmt = use->get_stmt();
            ASSERT0(use_stmt->is_stmt());

            ASSERT0(use_stmt->get_bb() != NULL);
            IRBB * use_bb = use_stmt->get_bb();
            if (!ssadu &&
                !(bb == use_bb && bb->is_dom(def_stmt, use_stmt, true)) &&
                !m_cfg->is_dom(BB_id(bb), BB_id(use_bb))) {
                //'def_stmt' must dominate 'use_stmt'.
                //e.g:
                //    if (...) {
                //        g = 10; //S1
                //    }
                //    ... = g; //S2
                //g can not be propagted since S1 is not dominate S2.
                continue;
            }

            if (!is_available(def_stmt, prop_value, use_stmt)) {
                //The value that will be propagated can
                //not be killed during 'ir' and 'use_stmt'.
                //e.g:
                //    g = a; //S1
                //    if (...) {
                //        a = ...; //S3
                //    }
                //    ... = g; //S2
                //g can not be propagted since a is killed by S3.
                continue;
            }

            if (!ssadu && !m_du->isExactAndUniqueDef(def_stmt, use)) {
                //Only single definition is allowed.
                //e.g:
                //    g = 20; //S3
                //    if (...) {
                //        g = 10; //S1
                //    }
                //    ... = g; //S2
                //g can not be propagted since there are
                //more than one definitions are able to get to S2.
                continue;
            }

            if (!canBeCandidate(prop_value)) {
                continue;
            }

            CPCtx lchange;
            IR * old_use_stmt = use_stmt;

            replaceExp(use, prop_value, lchange, ssadu);

            ASSERT(use_stmt && use_stmt->is_stmt(),
                    ("ensure use_stmt still legal"));
            change |= CPC_change(lchange);

            if (!CPC_change(lchange)) { continue; }

            //Indicate whether use_stmt is the next stmt of def_stmt.
            bool is_next = false;
            if (next_iter != NULL && use_stmt == next_iter->val()) {
                is_next = true;
            }

            RefineCtx rf;
            use_stmt = m_ru->refineIR(use_stmt, change, rf);
            if (use_stmt == NULL && is_next) {
                //use_stmt has been optimized and removed by refineIR().
                next_iter = cur_iter;
                BB_irlist(bb).get_next(&next_iter);
            }

            if (use_stmt != NULL && use_stmt != old_use_stmt) {
                //use_stmt has been removed and new stmt generated.
                ASSERT(old_use_stmt->is_undef(), ("the old one should be freed"));

                C<IR*> * irct = NULL;
                BB_irlist(use_bb).find(old_use_stmt, &irct);
                ASSERT0(irct);
                BB_irlist(use_bb).insert_before(use_stmt, irct);
                BB_irlist(use_bb).remove(irct);
            }
        } //end for each USE
    } //end for IR
    return change;
}