Esempio n. 1
0
static LoopUnrollInfo* prepareUnrollInfo(MemoryManager& mm, LoopTree* lt, BranchInst* branchInst) {

    if (Log::isEnabled()) {
        Log::out()<<"==Checking loop exit:"; branchInst->print(Log::out()); Log::out()<<std::endl;
    }

    //traverse loop and track all modifications
    Node* node = branchInst->getNode();
    LoopNode* loopHeader = lt->getLoopNode(node, false);
    Opnd* opnd1 = branchInst->getSrc(0);
    Opnd* opnd2 = branchInst->getNumSrcOperands()==1?NULL:branchInst->getSrc(1);
    
    if (opnd2==NULL) {
        assert(branchInst->getComparisonModifier() == Cmp_Zero || branchInst->getComparisonModifier() == Cmp_NonZero);
        assert(opnd1->getType()->isObject());
        if (Log::isEnabled()) {
            Log::out()<<"----Unsupported comparison modifier."<<std::endl;
        }
        return NULL;
    }
    
    if (!opnd1->getType()->isInteger() || opnd1->getType()->isInt8()
        || !opnd2->getType()->isInteger() || opnd2->getType()->isInt8()) 
    {
        if (Log::isEnabled()) {
            Log::out()<<"----Unsupported opnd types."<<std::endl;
        }
        return NULL;        //IMPROVE: longs and floating types are not supported
    }

    InstStack defStack(mm);

    Log::out()<<"----Analyzing opnd1 id="<<opnd1->getId()<<std::endl;
    OpndLoopInfo opndInfo1 = processOpnd(loopHeader, lt, defStack, opnd1);
    assert(defStack.empty());
    
    Log::out()<<"----Analyzing opnd2 id="<<opnd2->getId()<<std::endl;
    OpndLoopInfo opndInfo2 = processOpnd(loopHeader, lt, defStack, opnd2);
    assert(defStack.empty());

    if(Log::isEnabled()) {
        Log::out()<<"----Result: opndId1="<<opnd1->getId()<<" type=";opndInfo1.print(Log::out());
        Log::out()<<", opndId2="<<opnd2->getId()<<" type=";opndInfo2.print(Log::out());Log::out()<<std::endl;
    }

    //default values -> this item will not be unrolled unless all constraints are OK
    LoopUnrollInfo* info = new (mm) LoopUnrollInfo();
    info->header = loopHeader->getHeader();
    info->branchInst = branchInst;
    info->branchTargetIsExit = !loopHeader->inLoop(branchInst->getTargetLabel()->getNode());
    info->doUnroll = false;

    if (opndInfo1.isCounter() && (opndInfo2.isDOL() || opndInfo2.isLDConst())) {
        info->doUnroll = true;
        info->branchLimitOpndPos=1;
        info->increment = opndInfo1.getIncrement();
    } else  if (opndInfo2.isCounter() && (opndInfo1.isDOL() || opndInfo1.isLDConst())) {
        info->doUnroll = true;
        info->branchLimitOpndPos=0;
        info->increment = opndInfo2.getIncrement();
    } 
    return info;
}
Esempio n. 2
0
void LoopUnrollPass::_run(IRManager& irm) {
    const UnrollFlags& flags = ((LoopUnrollAction*)getAction())->getFlags();
    
    OptPass::computeDominatorsAndLoops(irm);
    ControlFlowGraph& cfg = irm.getFlowGraph();
    LoopTree* lt = cfg.getLoopTree();
    if (!lt->hasLoops()) {
        return;
    }
    
    MemoryManager mm("loopUnrollMM");
    UnrollInfos loopsToUnroll(mm);
    findLoopsToUnroll(mm, irm, loopsToUnroll, flags);
    if (loopsToUnroll.empty()) {
        if (Log::isEnabled()) Log::out() << "No candidates found to unroll"<<std::endl;
        return;
    }
    if (Log::isEnabled()) {
        Log::out()<<"Loops to unroll before filtering:"<<std::endl;
        for (UnrollInfos::const_iterator it = loopsToUnroll.begin(), end = loopsToUnroll.end();it!=end; ++it) {
            const LoopUnrollInfo* info = *it;
            info->print(Log::out()); Log::out()<<std::endl;
        }
    }
    bool hasProfile =  cfg.hasEdgeProfile();
    //filter out that can't be unrolled, calculate BodyA and BodyB
    BitSet bodyANodes(mm, cfg.getMaxNodeId()), bodyBNodes(mm, cfg.getMaxNodeId());
    for (UnrollInfos::iterator it = loopsToUnroll.begin(), end = loopsToUnroll.end();it!=end; ++it) {
        LoopUnrollInfo* info = *it;
        if (info == NULL) {
            continue;
        }
        if (!info->doUnroll) {
            *it=NULL;
            continue;
        }
        Node* header=info->header;
        LoopNode* loopHeader = lt->getLoopNode(header, false);
        assert(loopHeader->getHeader() == header);

        Node* checkNode = info->branchInst->getNode();
        bodyANodes.clear();
        bodyBNodes.clear();
        calculateReachableNodesInLoop(loopHeader, loopHeader->getHeader(), checkNode, bodyANodes);
        calculateReachableNodesInLoop(loopHeader, checkNode, NULL, bodyBNodes);
        bodyANodes.intersectWith(bodyBNodes);
        bool checkNodeIsJunctionPoint = bodyANodes.isEmpty();
        if (!checkNodeIsJunctionPoint) {
            if (Log::isEnabled()) {
                Log::out()<<"Check node is not a junction point -> removing from the list: branch inst id=I"<<info->branchInst->getId()<<std::endl;
            }
            *it=NULL;
            continue;
        }
        //check if branch semantic is OK
        ComparisonModifier cmpMod = info->branchInst->getModifier().getComparisonModifier();
        if (cmpMod!=Cmp_GT && cmpMod!=Cmp_GTE && cmpMod!=Cmp_GT_Un && cmpMod!=Cmp_GTE_Un) {
            if (Log::isEnabled()) {
                Log::out()<<"Branch is not a range comparison -> removing from the list: branch inst id=I"<<info->branchInst->getId()<<std::endl;
            }
            *it=NULL;
            continue;
        }

        //check config settings
        bool failed = false;
        int nodesInLoop = (int)loopHeader->getNodesInLoop().size();
        const char* reason = "unknown";
        if (nodesInLoop > flags.largeLoopSize) {
            reason = "loop is too large";
            failed = true;
        } else if (hasProfile) {
            int headHotness = (int)(header->getExecCount()*100.0  / cfg.getEntryNode()->getExecCount());
            int minHeaderHotness= nodesInLoop <= flags.smallLoopSize ? flags.smallLoopHotness :
                nodesInLoop <= flags.mediumLoopSize ? flags.mediumLoopHotness : flags.largeLoopHotness;
            info->unrollCount = nodesInLoop <= flags.smallLoopSize ? flags.smallLoopUnrollCount :
                nodesInLoop <= flags.mediumLoopSize? flags.mediumLoopUnrollCount: flags.largeLoopUnrollCount;
            failed = headHotness < minHeaderHotness || info->unrollCount < 1;
            if (failed) {
                reason = "loop is too cold";
            }
        }
        if (failed) {
            if (Log::isEnabled()) {
                Log::out()<<"Loop does not match unroll configuration ("<<reason<<") -> removing from the list: branch inst id=I"<<info->branchInst->getId()<<std::endl;
            }
            *it=NULL;
        }
    }    
    //filter out loops with multiple exits 
    for (UnrollInfos::iterator it1 = loopsToUnroll.begin(), end = loopsToUnroll.end();it1!=end; ++it1) {
        const LoopUnrollInfo* info1 = *it1;
        if (info1== NULL) {
            continue;
        }
        Node* header=info1->header;
        for (UnrollInfos::iterator it2 = it1+1; it2!=end; ++it2) {
            const LoopUnrollInfo* info2 = *it2;
            if (info2!=NULL && header==info2->header) {
                if (Log::isEnabled()) {
                    Log::out() << "Found multiple exits:"; FlowGraph::printLabel(Log::out(), header);Log::out()<<std::endl;
                }
                if (hasProfile)  {
                    Node* check1 = info1->branchInst->getNode();
                    Node* check2 = info2->branchInst->getNode();
                    if (check1->getExecCount() > check2->getExecCount()) {
                        *it2 = NULL;
                    } else {
                        *it1 = NULL;
                    }
                } else { // random selection
                    *it2=NULL;
                }
            }
        }
    }    
    loopsToUnroll.erase(std::remove(loopsToUnroll.begin(), loopsToUnroll.end(), (LoopUnrollInfo*)NULL), loopsToUnroll.end());
    if (loopsToUnroll.empty()) {
        if (Log::isEnabled()) Log::out() << "--------No candidates to unroll left after filtering"<<std::endl;
        return;
    }
    
    //dessa CFG before unrolling -> need to duplicate regions and we can do it on dessa form only today
    {
        SSABuilder::deconvertSSA(&cfg, irm.getOpndManager());
        irm.setInSsa(false);
    }

    if (Log::isEnabled()) {
        Log::out()<<"--------Loops to unroll after filtering : n="<<loopsToUnroll.size()<<std::endl;
            for (UnrollInfos::const_iterator it = loopsToUnroll.begin(), end = loopsToUnroll.end();it!=end; ++it) {
                const LoopUnrollInfo* info = *it;
                info->print(Log::out()); Log::out()<<std::endl;
            }
    }

    for (UnrollInfos::const_iterator it = loopsToUnroll.begin(), end = loopsToUnroll.end();it!=end; ++it) {
        const LoopUnrollInfo* info = *it;
        doUnroll(mm, irm, info, flags);
    }
};