void FlowGraph::doTranslatorCleanupPhase()

in vm/jitrino/src/optimizer/FlowGraph.cpp [878:1082]


void FlowGraph::doTranslatorCleanupPhase(IRManager& irm) {
    U_32 id = irm.getCompilationContext()->getCurrentSessionNum();
    const char* stage = "trans_cleanup";
    if (Log::isLogEnabled(LogStream::IRDUMP)) {
        LogStream& irdump = Log::log(LogStream::IRDUMP);
        Log::printStageBegin(irdump.out(), id, "TRANS", stage, stage);
        irdump << OptPass::indent(irm) << "Trans:   Running " << "cleanup" << ::std::endl;
        Log::printIRDumpBegin(irdump.out(), id, stage, "before");
        printHIR(irdump.out(), irm.getFlowGraph(), irm.getMethodDesc());
        Log::printIRDumpEnd(irdump.out(), id, stage, "before");
    }

    ControlFlowGraph& fg = irm.getFlowGraph();
    InstFactory& instFactory = irm.getInstFactory();
    OpndManager& opndManager = irm.getOpndManager();


    static CountTime cleanupPhaseTimer("ptra::fg::cleanupPhase");
    AutoTimer tm(cleanupPhaseTimer);
    fg.purgeUnreachableNodes();

#ifdef _DEBUG
    //check if loop structure is valid after translator
    OptPass::computeLoops(irm, false);
#endif


    inlineJSRs(&irm);
    fg.purgeUnreachableNodes();

    checkBCMapping(irm);

    {
        static CountTime cleanupPhaseInternalTimer("ptra::fg::cleanupPhase::in");
        AutoTimer tm(cleanupPhaseInternalTimer);
        // Cleanup optimizations
        for (Nodes::const_iterator niter = fg.getNodes().begin(), end = fg.getNodes().end(); niter!=end; ++niter) {
            Node* node = *niter;
            if (node->isDispatchNode() || node == fg.getReturnNode() || node == fg.getExitNode()) {
                continue;
            }
            Inst *last = (Inst*)node->getLastInst();
            if (last->isBranch()) {
                if (last->isConditionalBranch()) { // loop peeling for conditional branches
                    Node *target  = ((BranchInst*)last)->getTargetLabel()->getNode();
                    if (((LabelInst*)target->getFirstInst())->getLabelId() > ((LabelInst*)node->getFirstInst())->getLabelId()) 
                    {
                        LabelInst *targetLabel = ((BranchInst*)last)->getTargetLabel();
                        Node *fthru = NULL, *taken = NULL;
                        const Edges& outEdges = node->getOutEdges();
                        Edges::const_iterator eIter;
                        for(eIter = outEdges.begin(); eIter != outEdges.end(); ++eIter) {
                            Edge* edge = *eIter;
                            Node * tar = edge->getTargetNode();
                            if (!tar->isDispatchNode()) {
                                if (tar->getFirstInst() == targetLabel) {
                                    taken = tar;
                                } else {
                                    fthru = tar; 
                                }
                            }
                        }
                        Inst *takenLdConst = (Inst*)taken->getSecondInst();
                        Inst *fthruLdConst = (Inst*)fthru->getSecondInst();
                        Inst *takenStVar   = (takenLdConst!=NULL) ? takenLdConst->getNextInst() : NULL;
                        Inst *fthruStVar   = (fthruLdConst!=NULL) ? fthruLdConst->getNextInst() : NULL;
                        if (takenStVar!=NULL && fthruStVar!=NULL                    &&
                            taken->hasOnlyOneSuccEdge()                             &&
                            taken->hasOnlyOnePredEdge()                             &&
                            fthru->hasOnlyOneSuccEdge()                             &&
                            fthru->hasOnlyOnePredEdge()                             &&
                            (taken->getOutEdges().front()->getTargetNode() ==
                            fthru->getOutEdges().front()->getTargetNode())         &&
                            takenLdConst->getOpcode()       == Op_LdConstant        &&
                            fthruLdConst->getOpcode()       == Op_LdConstant        &&
                            takenLdConst->getType()         == Type::Int32          &&
                            fthruLdConst->getType()         == Type::Int32          &&
                            takenStVar->getOpcode()         == Op_StVar             &&
                            fthruStVar->getOpcode()         == Op_StVar             &&
                            takenStVar->getDst()            == fthruStVar->getDst() &&
                            takenStVar->getNextInst()       == taken->getLastInst() &&
                            fthruStVar->getNextInst()       == fthru->getLastInst())
                        {

                                int takenint32 = ((ConstInst*)takenLdConst)->getValue().i4;
                                int fthruint32 = ((ConstInst*)fthruLdConst)->getValue().i4;
                                Node *meet = taken->getOutEdges().front()->getTargetNode();
                                // find the ldVar for the variable, if any
                                Inst *meetLdVar = (Inst*)meet->getSecondInst();
                                while (meetLdVar->getOpcode()==Op_LdVar) {
                                    if (meetLdVar->getSrc(0) == takenStVar->getDst())
                                        break;
                                    meetLdVar = meetLdVar->getNextInst();
                                }
                                if ((((takenint32==0) && (fthruint32==1)) ||
                                    ((takenint32==1) && (fthruint32==0))) &&
                                    meetLdVar->getOpcode()==Op_LdVar &&
                                    last->getNumSrcOperands()==2) {
                                        // change the instruction to reflect the compare instruction
                                        fg.removeEdge(node,taken);
                                        fg.removeEdge(node,fthru);
                                        fg.addEdge(node,meet);
                                        Opnd* dst = opndManager.createSsaTmpOpnd(meetLdVar->getDst()->getType());
                                        BranchInst *lastBranch = (BranchInst*)last;
                                        if (takenint32==0) 
                                            lastBranch->swapTargets(NULL);
                                        Inst *cmp = instFactory.makeCmp(
                                            lastBranch->getComparisonModifier(),
                                            lastBranch->getType(), dst, 
                                            lastBranch->getSrc(0),
                                            lastBranch->getSrc(1));
                                        cmp->insertBefore(lastBranch);
                                        Inst* newStVar = instFactory.makeStVar(meetLdVar->getSrc(0)->asVarOpnd(),dst);
                                        newStVar->insertBefore(lastBranch);
                                        lastBranch->unlink();
                                    }
                            }
                    }
                }
            }
            // remove trivial basic blocks
            if (node->hasOnlyOnePredEdge()) {
                Node *pred = node->getInEdges().front()->getSourceNode();
                if (!pred->isDispatchNode() &&  !((Inst*)pred->getLastInst())->isSwitch() &&
                    (pred->hasOnlyOneSuccEdge() ||  (node->isEmpty() && node->hasOnlyOneSuccEdge()))) 
                {                

                    // don't merge if the node has an exception edge 
                    Edge *edge = NULL;
                    Edges::const_iterator eiter;
                    for(eiter = node->getOutEdges().begin(); eiter != node->getOutEdges().end(); ++eiter) {
                        edge = *eiter;
                        if ((edge->getTargetNode())->isDispatchNode()) {
                            break;
                        }
                    }
                    // If the node has an exception edge, then merging is potentially illegal, so
                    // skip.
                    if (edge == NULL) {
                        if (Log::isEnabled()) {
                            Log::out()<<" MERGE ";FlowGraph::printLabel(Log::out(), pred);FlowGraph::printLabel(Log::out(), node);Log::out()<<"\n";
                            Log::out().flush();
                        }
                        BranchInst *branch = NULL;
                        if (!pred->hasOnlyOneSuccEdge() && node->isEmpty()) {
                            Inst* lastPred = (Inst*)pred->getLastInst();
                            Node* nodeSucc = node->getOutEdges().front()->getTargetNode();
                            if (lastPred->isBranch()) {
                                branch = (BranchInst*)lastPred;
                                if (branch->getTargetLabel() == node->getFirstInst()) {
                                    branch->replaceTargetLabel((LabelInst*)nodeSucc->getFirstInst());
                                }
                            }
                        }
                        fg.mergeBlocks(pred,node);

                        // remove useless branches
                        if (branch != NULL) {
                            Node *target = NULL;
                            for(eiter=pred->getOutEdges().begin(); eiter!=pred->getOutEdges().end();) {
                                Edge* edge = *eiter;
                                ++eiter;
                                Node *succ = edge->getTargetNode();
                                if (! succ->isDispatchNode()) {
                                    if (target == succ) {
                                        fg.removeEdge(pred,succ);
                                        branch->unlink();
                                        break;
                                    }
                                    target = succ;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    // Remove extra PseudoThrow insts
    DeadCodeEliminator dce(irm);
    dce.removeExtraPseudoThrow();

    //process all methods marked with @Inline pragma
    if (Log::isLogEnabled(LogStream::IRDUMP)) {
        LogStream& irdump = Log::log(LogStream::IRDUMP);
        Log::printIRDumpBegin(irdump.out(), id, stage, "before_pragma_inline");
        printHIR(irdump.out(), irm.getFlowGraph(), irm.getMethodDesc());
        Log::printIRDumpEnd(irdump.out(), id, stage, "before_pragma_inline");
    }
    Inliner::processInlinePragmas(irm);


    //
    // a quick cleanup of unreachable and empty basic blocks
    //
    fg.purgeUnreachableNodes();
    fg.purgeEmptyNodes(false);

    if (Log::isLogEnabled(LogStream::IRDUMP)) {
        LogStream& irdump = Log::log(LogStream::IRDUMP);
        Log::printStageEnd(irdump.out(), id, "TRANS", stage, stage);
    }

}