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::hoistIf(IR ** head, IR * ir)
{
    ASSERT(ir->is_if(), ("need IF"));
    ASSERT(IF_det(ir), ("DET is NULL"));

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

    IR * new_list = NULL;
    if (i > 1) {
        det = IF_det(ir);
        while (i > 1) {
            IR * c = det;
            ASSERT(c->is_stmt(),
                ("Non-stmt ir should be remove during reshape_ir_tree()"));
            det = det->get_next();
            xcom::remove(&IF_det(ir), c);
            xcom::add_next(&new_list, c);
            i--;
        }
        xcom::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::hoistLoop(IR ** head, IR * ir)
{
    ASSERT0(ir->is_dowhile() || ir->is_whiledo() || ir->is_doloop());
    ASSERT(LOOP_det(ir), ("DET is NULL"));
    IR * det = LOOP_det(ir);

    INT i = 0;
    while (det != NULL) {
        i++;
        det = det->get_next();
    }

    IR * new_list = NULL, * new_body_list = NULL;
    if (i > 1) {
        det = LOOP_det(ir);
        while (i > 1) {
            IR * c = det;
            ASSERT(c->is_stmt(), ("Non-stmt ir should be remove "
                                   "during reshape_ir_tree()"));
            det = det->get_next();
            xcom::remove(&LOOP_det(ir), c);
            xcom::add_next(&new_list, c);
            i--;
        }
        new_body_list = m_ru->dupIRTreeList(new_list);
        xcom::insertbefore(head, ir, new_list);
        xcom::add_next(&LOOP_body(ir), new_body_list);
        return true;
    }
    return false;
}
Esempio n. 3
0
//Before removing bb or change bb successor,
//you need remove the related PHI operand if BB successor has PHI stmt.
void IRBB::removeSuccessorDesignatePhiOpnd(CFG<IRBB, IR> * cfg, IRBB * succ)
{
    ASSERT0(cfg && succ);
    IR_CFG * ircfg = (IR_CFG*)cfg;
    Region * ru = ircfg->get_ru();
    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)) == succ->getNumOfPred(cfg));

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

        if (opnd == NULL) {
            //PHI does not contain any operand.
            continue;
        }

        opnd->removeSSAUse();
        ((CPhi*)ir)->removeOpnd(opnd);
        ru->freeIRTree(opnd);
    }
}
Esempio n. 4
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::transformToDoWhile(IR ** head, IR * ir)
{
    ASSERT(head != NULL && *head != NULL, ("invalid parameter"));
    if (!ir->is_lab()) { return false; }

    for (IR * t = ir; t != NULL; t = t->get_next()) {
        if (!t->is_if()) { continue; }

        if (IF_truebody(t) != NULL &&
            IF_truebody(t)->is_goto() &&
            isSameLabel(LAB_lab(ir), GOTO_lab(IF_truebody(t)))) {

            //Start transform.
            IR * dowhile = m_ru->allocIR(IR_DO_WHILE);
            LOOP_det(dowhile) = m_ru->dupIRTree(LOOP_det(t));

            IR * if_stmt = t;
            t = ir->get_next();
            while (t != NULL && t != if_stmt) {
                IR * c = t;
                t = t->get_next();
                xcom::remove(head, c);
                xcom::add_next(&LOOP_body(dowhile), c);
            }

            ASSERT(t == if_stmt, ("illegal IR layout"));

            xcom::remove(head, if_stmt);
            if (IF_falsebody(if_stmt)) {
                xcom::add_next(&dowhile, IF_falsebody(if_stmt));
                IF_falsebody(if_stmt) = NULL;
            }
            xcom::insertafter(&ir, dowhile);
            m_ru->freeIRTree(if_stmt); //free IF
            xcom::remove(head, ir);
            m_ru->freeIRTree(ir); //free LABEL
            return true;
        }
    }

    return false;
}
Esempio n. 5
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 = opnd->get_next()) {
                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. 6
0
bool IR_CFS_OPT::CfsOpt(
        IN OUT IR ** ir_list,
        SimpCtx const& sc)
{
    bool change = false;

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

        if (ir->is_if() && transformIf1(ir_list, ir)) {
            change = true;
            ir = *ir_list;
            continue;
        }

        if (ir->is_if() && transformIf2(ir_list, ir)) {
            change = true;
            ir = *ir_list;
            continue;
        }

        if (ir->is_if() && transformIf3(ir_list, ir)) {
            change = true;
            ir = *ir_list;
            continue;
        }

        switch (ir->get_code()) {
        case IR_IF:
            if (hoistIf(ir_list, ir)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            if (CfsOpt(&IF_truebody(ir), sc)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            if (CfsOpt(&IF_falsebody(ir), sc)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            break;
        case IR_DO_WHILE:
        case IR_WHILE_DO:
        case IR_DO_LOOP:
            if (hoistLoop(ir_list, ir)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            if (CfsOpt(&LOOP_body(ir), sc)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            break;
        case IR_SWITCH:
            if (CfsOpt(&SWITCH_body(ir), sc)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            break;
        default:;
        } //end switch

         ir = ir->get_next();
    }
    return change;
}
Esempio n. 7
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;
}