Esempio n. 1
0
void CfgCodeSelector::genUnconditionalEdge(U_32 tailNodeId,U_32 headNodeId, double prob) 
{
    Node * tailNode = nodes[tailNodeId];
    Node * headNode = nodes[headNodeId];
    assert(tailNode->isBlockNode());
    assert(headNode->isBlockNode() || headNode == irManager.getFlowGraph()->getExitNode());
    Inst* lastInst = (Inst*)tailNode->getLastInst();
    if (lastInst!=NULL && lastInst->hasKind(Inst::Kind_BranchInst)) {
        BranchInst* br = (BranchInst*)lastInst;
        assert(br->getTrueTarget() != NULL);
        assert(br->getFalseTarget() == NULL);
        br->setFalseTarget(headNode);
    }
    irManager.getFlowGraph()->addEdge(tailNode, headNode, prob);
}
Esempio n. 2
0
void CfgCodeSelector::fixNodeInfo() 
{
    MemoryManager tmpMM("Ia32CS:fixNodeInfoMM");
    ControlFlowGraph* fg = irManager.getFlowGraph();
    Nodes nodes(tmpMM);
    fg->getNodes(nodes); //copy nodes -> loop creates new ones, so we can't use reference to cfg->getNodes()
    for (Nodes::const_iterator it = nodes.begin(), end = nodes.end(); it!=end; ++it) {
        Node* node = *it;
        // connect throw nodes added during inst code selection to corresponding dispatch or unwind nodes
        if (node->isBlockNode()){
            Inst * lastInst = (Inst*)node->getLastInst();
            if (lastInst) {
                Inst * prevInst = lastInst->getPrevInst();
                if(prevInst && prevInst->getKind() == Inst::Kind_BranchInst) {
                    Edge * ftEdge = node->getFalseEdge();
                    Edge * dbEdge = node->getTrueEdge();
                    assert(ftEdge && dbEdge);

                    Node* newBB =  fg->createBlockNode();
                    Node* nextFT =  ftEdge->getTargetNode();
                    Node* nextDB = dbEdge->getTargetNode();

                    fg->removeEdge(ftEdge);
                    fg->removeEdge(dbEdge);

                    newBB->appendInst(irManager.newBranchInst(lastInst->getMnemonic(), nextDB, nextFT));
                    lastInst->unlink();

                    //now fix prev branch successors
                    BranchInst* prevBranch = (BranchInst*)prevInst;
                    assert(prevBranch->getTrueTarget() == NULL && prevBranch->getFalseTarget() == NULL);
                    prevBranch->setTrueTarget(lastInst->getMnemonic() == Mnemonic_JZ? nextFT : nextDB);
                    prevBranch->setFalseTarget(newBB);
              
                    
                    fg->addEdge(node, lastInst->getMnemonic() == Mnemonic_JZ? nextFT : nextDB, 0);
                    fg->addEdge(node, newBB, 0);
                    fg->addEdge(newBB, nextDB, 0); 
                    fg->addEdge(newBB, nextFT, 0);
                }
            }
            if (node->getOutDegree() == 0){ // throw node
                assert(node->getInDegree()==1);
                Node* bbIn = node->getInEdges().front()->getSourceNode();
                assert(bbIn!=NULL);
                Node * target=bbIn->getExceptionEdgeTarget();
                assert(target!=NULL);
                fg->addEdge(node, target, 1.0);
            }
            // fixup empty catch blocks otherwise respective catchEdges will be lost
            // There is no [catchBlock]-->[catchHandler] edge. Catch block will be removed
            // as an empty one and exception handling will be incorrect
            if (node->isCatchBlock() && node->isEmpty()) {
                assert(node->getInDegree()==1);
                Edge* catchEdge = node->getInEdges().front();
                assert(catchEdge->getSourceNode()->isDispatchNode());
                assert(node->getOutDegree()==1);
                Node* succ = node->getUnconditionalEdgeTarget();
                while( succ->isEmpty() && (succ->getOutDegree() == 1) ) {
                    succ = succ->getUnconditionalEdgeTarget();
                }
                assert(succ && ((Inst*)succ->getFirstInst())->hasKind(Inst::Kind_CatchPseudoInst));
                fg->replaceEdgeTarget(catchEdge,succ,true/*keepOldBody*/);
            }
        }
    }
}
Esempio n. 3
0
/**
 *  The algorithm finds conditional instruction (=condInst) first, then
 *  corresponding CMP instruction (=cmpInst) and arithmetic instruction (=inst)
 *  which affects flags in the same way as CMP. Combination is considered as
 *  available to be reduced if there are no instructions between CMP and
 *  arithmetic instruction which influence to flags or CMP operands.
 *
 *  Also it transforms some conditional instruction to make them more suitable
 *  for optimizations
 */
void
RCE::runImpl() 
{
    Inst * inst, * cmpInst, *condInst;
    Opnd * cmpOp = NULL; 
    cmpInst = condInst = NULL;
    const Nodes& nodes = irManager->getFlowGraph()->getNodesPostOrder();
    for (Nodes::const_iterator it = nodes.begin(), end = nodes.end(); it!=end; ++it) {
        Node* node = *it;
        if (node->isBlockNode()) {
            if(node->isEmpty()) {
                continue;
            }
            cmpInst = NULL;
            Inst* prevInst = NULL;
            for(inst = (Inst*)node->getLastInst(); inst != NULL; inst = prevInst) {
                prevInst = inst->getPrevInst();
                //find conditional instruction
                Mnemonic baseMnem = getBaseConditionMnemonic(inst->getMnemonic());
                if (baseMnem != Mnemonic_NULL) {
                    condInst = condInst ? NULL : inst;
                    cmpInst = NULL;
                } else if (condInst) {
                    //find CMP instruction corresponds to conditional instruction
                    if(inst->getMnemonic() == Mnemonic_CMP || inst->getMnemonic() == Mnemonic_UCOMISD || inst->getMnemonic() == Mnemonic_UCOMISS) {
                        if (cmpInst) {
                            //this comparison is redundant because of overrided by cmpInst
                            inst->unlink();
                            continue;
                        }
                        cmpInst = inst;
                        U_32 defCount = inst->getOpndCount(Inst::OpndRole_InstLevel|Inst::OpndRole_Def);
                        if(inst->getOpnd(defCount+1)->isPlacedIn(OpndKind_Imm)) {
                            //try to change conditional instruction to make combination available to optimize
                            cmpOp = inst->getOpnd(defCount);
                            Inst * newCondInst = NULL; 
                            Mnemonic mnem;
                            int64 val = inst->getOpnd(defCount+1)->getImmValue();
                            
                            if (val == 0) {
                                continue;
                            } else if (val == 1 && ConditionMnemonic(condInst->getMnemonic()-getBaseConditionMnemonic(condInst->getMnemonic())) == ConditionMnemonic_L){
                                mnem = Mnemonic((condInst->getMnemonic() - Mnemonic(ConditionMnemonic_L)) + Mnemonic(ConditionMnemonic_LE));
                            } else if (val == -1 && ConditionMnemonic(condInst->getMnemonic()-getBaseConditionMnemonic(condInst->getMnemonic())) == ConditionMnemonic_G) {
                                mnem = Mnemonic((condInst->getMnemonic() - Mnemonic(ConditionMnemonic_G)) + Mnemonic(ConditionMnemonic_GE));
                            } else if (val == -1 && ConditionMnemonic(condInst->getMnemonic()-getBaseConditionMnemonic(condInst->getMnemonic())) == ConditionMnemonic_B) {
                                mnem = Mnemonic((condInst->getMnemonic() - Mnemonic(ConditionMnemonic_B)) + Mnemonic(ConditionMnemonic_BE));
                            } else {
                                continue;
                            }
                            //replace old conditional instruction
                            if (condInst->hasKind(Inst::Kind_BranchInst)) {
                                BranchInst* br = (BranchInst*)condInst;
                                newCondInst = irManager->newBranchInst(mnem,br->getTrueTarget(), br->getFalseTarget(), condInst->getOpnd(0));
                            } else {
                                Mnemonic condMnem = getBaseConditionMnemonic(condInst->getMnemonic());
                                Inst::Opnds defs(condInst,Inst::OpndRole_Def|Inst::OpndRole_Explicit);
                                if (condMnem == Mnemonic_CMOVcc) {
                                    Inst::Opnds uses(condInst,Inst::OpndRole_Use|Inst::OpndRole_Explicit);
                                    newCondInst = irManager->newInst(mnem, condInst->getOpnd(defs.begin()), inst->getOpnd(uses.begin()));
                                } else if (condMnem == Mnemonic_SETcc) {
                                    newCondInst = irManager->newInst(mnem, condInst->getOpnd(defs.begin()));
                                } else {
                                    assert(0);
                                    continue;
                                }
                            }
                            newCondInst->insertAfter(condInst);
                            condInst->unlink();
                            condInst = newCondInst;
                            inst->setOpnd(defCount+1, irManager->newImmOpnd(inst->getOpnd(defCount+1)->getType(),0));
                        } 
                    //find flags affected instruction precedes cmpInst
                    } else if (instAffectsFlagsAsCmpInst(inst, condInst)) {
                        if (cmpInst) {
                            if (isSuitableToRemove(inst, condInst, cmpInst, cmpOp))
                            {
                                cmpInst->unlink();
                            } 
                        }
                        condInst = NULL; // do not optimize cmpInst any more in this block
                    } else {
                        if (inst->getOpndCount(Inst::OpndRole_Implicit|Inst::OpndRole_Def) || inst->getMnemonic() == Mnemonic_CALL) {
                            // instruction affects flags, skip optimizing cmpInst
                            condInst = NULL;
                        } else {
                            //check for moving cmpInst operands 
                            if ((inst->getMnemonic() == Mnemonic_MOV) && (inst->getOpnd(0) == cmpOp)) {
                                cmpOp = inst->getOpnd(1);
                            }
                        }
                    } 
                }//end if/else by condInst
            }//end for() by Insts
        }//end if BasicBlock
    }//end for() by Nodes
}
PeepHoleOpt::Changed PeepHoleOpt::handleInst_SETcc(Inst* inst)
{
    if (((BasicBlock*)inst->getNode())->getLayoutSucc() == NULL)
    {
        Mnemonic mn = inst->getMnemonic();
        
        Inst* prev = inst->getPrevInst();
        Inst *next = inst->getNextInst();

        Node *currNode = inst->getNode();
        bool methodMarkerOccur = false;
        MethodMarkerPseudoInst* methodMarker = NULL;
        // ignoring instructions that have no effect and saving method markers to correct them during optimizations
        while (next == NULL || next->getKind() == Inst::Kind_MethodEndPseudoInst || next->getMnemonic() == Mnemonic_JMP)
        {
            if (next == NULL)
            {
                currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode();
                if (currNode->getKind() == Node::Kind_Exit)
                    return Changed_Nothing;
                next = (Inst*) currNode->getFirstInst();
            }
            else
            {
                if (next->getKind() == Inst::Kind_MethodEndPseudoInst)
                {
                    //max 1 saved method marker
                    if (methodMarkerOccur)
                    {
                        return Changed_Nothing;
                    }
                    methodMarker = (MethodMarkerPseudoInst*)next;
                    methodMarkerOccur = true;
                }
                next = next->getNextInst();
            }
        }

        Inst *next2 = next->getNextInst();

        bool step1 = true;
        currNode = inst->getNode();
        while (currNode != next->getNode())
        {
            currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode();
            if (currNode->getInDegree()!=1)
            {
                step1 = false;
                break;
            }
        }

        // step1:
        // ------------------------------------------
        // MOV opnd, 0                  MOV opnd2, 0
        // SETcc opnd           ->      SETcc opnd2
        // MOV opnd2, opnd
        // ------------------------------------------
        // nb: applicable if opnd will not be used further
        if (step1 && prev!= NULL && prev->getMnemonic() == Mnemonic_MOV &&
            next!= NULL && next->getMnemonic() == Mnemonic_MOV)
        {
            Opnd *prevopnd1, *prevopnd2, *nextopnd1, *nextopnd2, *setopnd;
            if (prev->getKind() == Inst::Kind_CopyPseudoInst)
            {
                prevopnd1 = prev->getOpnd(0);
                prevopnd2 = prev->getOpnd(1);
            }
            else
            {
                Inst::Opnds prevuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds prevdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                prevopnd1 = prev->getOpnd(prevdefs.begin());
                prevopnd2 = prev->getOpnd(prevuses.begin());
            }
            if (next->getKind() == Inst::Kind_CopyPseudoInst)
            {
                nextopnd1 = next->getOpnd(0);
                nextopnd2 = next->getOpnd(1);
            }
            else
            {
                Inst::Opnds nextuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds nextdefs(next, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                nextopnd1 = next->getOpnd(nextdefs.begin());
                nextopnd2 = next->getOpnd(nextuses.begin());
            }
            Inst::Opnds setdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
            setopnd = inst->getOpnd(setdefs.begin());

            if (isReg(nextopnd1) &&
                prevopnd1->getId() == setopnd->getId() &&
                setopnd->getId() == nextopnd2->getId() &&
                isImm(prevopnd2) && prevopnd2->getImmValue() == 0
                )
            {
                BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
                irManager->updateLivenessInfo();
                irManager->getLiveAtExit(next->getNode(), ls);
                for (Inst* i = (Inst*)next->getNode()->getLastInst(); i!=next; i = i->getPrevInst()) {
                    irManager->updateLiveness(i, ls);
                }
                bool opndNotUsed = !ls.getBit(setopnd->getId());
                if (opndNotUsed)
                {
                    if (nextopnd1->getRegName() != RegName_Null &&
                        Constraint::getAliasRegName(nextopnd1->getRegName(), OpndSize_8) == RegName_Null)
                    {
                        nextopnd1->assignRegName(setopnd->getRegName());
                    }
                    irManager->newInst(Mnemonic_MOV, nextopnd1, prevopnd2)->insertBefore(inst);
                    irManager->newInst(mn, nextopnd1)->insertBefore(inst);
                    prev->unlink();
                    inst->unlink();
                    next->unlink();
                    return Changed_Node;
                }
            }
        }

        // step2:
        // --------------------------------------------------------------
        // MOV opnd, 0                  Jcc smwh                Jcc smwh
        // SETcc opnd           ->      BB1:            v       BB1:
        // CMP opnd, 0                  ...
        // Jcc smwh                     CMP opnd, 0
        // BB1:                         Jcc smwh
        // --------------------------------------------------------------
        // nb: applicable if opnd will not be used further
        // nb: conditions of new jumps are calculated from conditions of old jump and set instructions
	    if (prev!= NULL && prev->getMnemonic() == Mnemonic_MOV &&
            next!= NULL && (next->getMnemonic() == Mnemonic_CMP || next->getMnemonic() == Mnemonic_TEST) &&
            next2!= NULL && (next2->getMnemonic() == Mnemonic_JG || next2->getMnemonic() == Mnemonic_JE || next2->getMnemonic() == Mnemonic_JNE) )
	    {
            Opnd* movopnd1;
            Opnd* movopnd2;
            if (prev->getKind() == Inst::Kind_CopyPseudoInst)
            {
                movopnd1 = prev->getOpnd(0);
                movopnd2 = prev->getOpnd(1);
            }
            else
            {
                Inst::Opnds movuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds movdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                movopnd1 = prev->getOpnd(movdefs.begin());
                movopnd2 = prev->getOpnd(movuses.begin());
            }
            Inst::Opnds cmpuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
            Opnd* cmpopnd1 = next->getOpnd(cmpuses.begin());
            Opnd* cmpopnd2 = next->getOpnd(cmpuses.next(cmpuses.begin()));

            if (
                isImm(movopnd2) && movopnd2->getImmValue() == 0 &&
                movopnd1->getId() == cmpopnd1->getId() &&
                //case CMP:
                (next->getMnemonic() != Mnemonic_CMP || (isImm(cmpopnd2) && cmpopnd2->getImmValue() == 0)) &&
                //case TEST:
                (next->getMnemonic() != Mnemonic_TEST || cmpopnd1->getId() == cmpopnd2->getId())
                )
            {
                BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
                irManager->updateLivenessInfo();
                irManager->getLiveAtExit(next2->getNode(), ls);
                bool opndNotUsed = !ls.getBit(movopnd1->getId());
                if (opndNotUsed)
                {
                    BranchInst* br = (BranchInst*) next2;

                    Mnemonic newjumpmn = Mnemonic_JZ;
                    if (next2->getMnemonic() == Mnemonic_JE)
                    {
                        switch (mn)
                        {
                        case Mnemonic_SETG:
                            newjumpmn = Mnemonic_JLE; break;
                        case Mnemonic_SETE:
                            newjumpmn = Mnemonic_JNE; break;
                        case Mnemonic_SETL:
                            newjumpmn = Mnemonic_JGE; break;
                        case Mnemonic_SETNE:
                            newjumpmn = Mnemonic_JE; break;
                        default:
                            assert(0); break;
                        }
                    }
                    else
                    {
                        switch (mn)
                        {
                        case Mnemonic_SETG:
                            newjumpmn = Mnemonic_JG; break;
                        case Mnemonic_SETE:
                            newjumpmn = Mnemonic_JE; break;
                        case Mnemonic_SETL:
                            newjumpmn = Mnemonic_JL; break;
                        case Mnemonic_SETNE:
                            newjumpmn = Mnemonic_JNE; break;
                        default:
                            assert(0); break;
                        }
                    }

                    if (inst->getNode()->getId() != next->getNode()->getId())
                    {
                        ControlFlowGraph* cfg = irManager->getFlowGraph();
                        cfg->removeEdge(inst->getNode()->getOutEdge(Edge::Kind_Unconditional));

                        double trueEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_True)->getEdgeProb();
                        double falseEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_False)->getEdgeProb();
                        cfg->addEdge(inst->getNode(), br->getTrueTarget(), trueEdgeProb);
                        cfg->addEdge(inst->getNode(), br->getFalseTarget(), falseEdgeProb);
                        irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(inst);
                        if (methodMarkerOccur)
                        {
                            inst->getNode()->appendInst(irManager->newMethodEndPseudoInst(methodMarker->getMethodDesc()));
                        }
		                prev->unlink();
		                inst->unlink();
                        cfg->purgeUnreachableNodes();
                    }
                    else
                    {
                        irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(next2);
                        prev->unlink();
		                inst->unlink();
		                next->unlink();
                        next2->unlink();
                    }
		            return Changed_Node;
                }// endif opndNotUsed
            }
        }
    }
	return Changed_Nothing;
}