void SSAPass::_run(IRManager& irm) { OptPass::computeDominators(irm); DominatorTree* dominatorTree = irm.getDominatorTree(); ControlFlowGraph& flowGraph = irm.getFlowGraph(); DomFrontier frontier(irm.getNestedMemoryManager(),*dominatorTree,&flowGraph); SSABuilder ssaBuilder(irm.getOpndManager(),irm.getInstFactory(),frontier,&flowGraph, irm.getOptimizerFlags()); ssaBuilder.convertSSA(irm.getMethodDesc()); irm.setInSsa(true); irm.setSsaUpdated(); }
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); } };
void DeSSAPass::_run(IRManager& irm) { SSABuilder::deconvertSSA(&irm.getFlowGraph(),irm.getOpndManager()); irm.setInSsa(false); }