void LoopReductor::reduce(VirtualCFG *vcfg, CFG *cfg) { HashTable<BasicBlock*,BasicBlock*> map; map.put(cfg->entry(), vcfg->entry()); map.put(cfg->exit(),vcfg->exit()); idx = 1; /* duplicate the basic blocks */ for (CFG::BBIterator bb(cfg); bb; bb++) { if (!bb->isEnd()) { BasicBlock *vbb = new VirtualBasicBlock(*bb); INDEX(vbb) = idx; idx++; map.put(bb, vbb); vcfg->addBB(vbb); } } INDEX(vcfg->exit()) = idx; idx++; /* connect edges */ for (CFG::BBIterator bb(cfg); bb; bb++) { for (BasicBlock::OutIterator edge(bb); edge; edge++) { if (edge->kind() == Edge::CALL) { BasicBlock *vsource = map.get(edge->source(), NULL); CFG *vcalled = vcfgvec.get(INDEX(edge->calledCFG())); ASSERT(vsource && vcalled); Edge *vedge = new Edge(vsource, vcalled->entry(), Edge::CALL); CALLED_CFG(vedge) = vcalled; } else { BasicBlock *vsource = map.get(edge->source(), NULL); BasicBlock *vtarget = map.get(edge->target(), NULL); ASSERT(vsource && vtarget); new Edge(vsource, vtarget, edge->kind()); } } } Vector<BasicBlock*> *ancestors = new Vector<BasicBlock*>(); for (CFG::BBIterator bb(vcfg); bb; bb++) { IN_LOOPS(bb) = new dfa::BitSet(vcfg->countBB()); } /* Do the Depth-First Search, compute the ancestors sets, and mark loop headers */ depthFirstSearch(vcfg->entry(), ancestors); /* Collect all loop headers in a bitset */ /* for (CFG::BBIterator bb(vcfg); bb; bb++) if (LOOP_HEADER(bb)) { realhdr.add(bb->number()); } */ /* HashTable<int, BasicBlock*> hdrmap; Vector<BasicBlock*> dups; */ bool done = false; while (!done) { done = true; for (CFG::BBIterator bb(vcfg); bb; bb++) { Vector<Edge*> toDel; BasicBlock *duplicate = NULL; for (BasicBlock::InIterator edge(bb); edge; edge++) { /* compute loops entered by the edge */ dfa::BitSet enteredLoops(**IN_LOOPS(bb)); enteredLoops.remove(**IN_LOOPS(edge->source())); /* The edge is a regular entry if it enters one loop, and edge->target() == loop header */ if (!((enteredLoops.count() == 0) || ((enteredLoops.count() == 1) && (enteredLoops.contains(bb->number()))))) { if (!duplicate) { duplicate = new VirtualBasicBlock(bb); ASSERT(DUPLICATE_OF(bb) == NULL); DUPLICATE_OF(bb) = duplicate; INDEX(duplicate) = idx; idx++; vcfg->addBB(duplicate); IN_LOOPS(duplicate) = new dfa::BitSet(**IN_LOOPS(edge->source())); for (BasicBlock::OutIterator outedge(bb); outedge; outedge++) { if (DUPLICATE_OF(outedge->target())) { new Edge(duplicate, DUPLICATE_OF(outedge->target()), outedge->kind()); } else { new Edge(duplicate, outedge->target(), outedge->kind()); } } } done = false; new Edge(edge->source(), duplicate, edge->kind()); toDel.add(edge); } } for (Vector<Edge*>::Iterator edge(toDel); edge; edge++) delete *edge; } } delete ancestors; }
void LoopUnroller::unroll(otawa::CFG *cfg, BasicBlock *header, VirtualCFG *vcfg) { VectorQueue<BasicBlock*> workList; VectorQueue<BasicBlock*> loopList; VectorQueue<BasicBlock*> virtualCallList; genstruct::Vector<BasicBlock*> doneList; typedef genstruct::Vector<Pair<VirtualBasicBlock*, Edge::kind_t> > BackEdgePairVector; BackEdgePairVector backEdges; bool dont_unroll = false; BasicBlock *unrolled_from; int start; /* Avoid unrolling loops with LOOP_COUNT of 0, since it would create a LOOP_COUNT of -1 for the non-unrolled part of the loop*/ /* if (header && (ipet::LOOP_COUNT(header) == 0)) { dont_unroll = true; } */ //if (header) dont_unroll = true; start = dont_unroll ? 1 : 0; for (int i = start; ((i < 2) && header) || (i < 1); i++) { doneList.clear(); ASSERT(workList.isEmpty()); ASSERT(loopList.isEmpty()); ASSERT(doneList.isEmpty()); workList.put(header ? header : cfg->entry()); doneList.add(header ? header : cfg->entry()); genstruct::Vector<BasicBlock*> bbs; while (!workList.isEmpty()) { BasicBlock *current = workList.get(); if (LOOP_HEADER(current) && (current != header)) { /* we enter another loop */ loopList.put(current); /* add exit edges destinations to the worklist */ for (genstruct::Vector<Edge*>::Iterator exitedge(**EXIT_LIST(current)); exitedge; exitedge++) { if (!doneList.contains(exitedge->target())) { workList.put(exitedge->target()); doneList.add(exitedge->target()); } } } else { VirtualBasicBlock *new_bb = 0; if ((!current->isEntry()) && (!current->isExit())) { /* Duplicate the current basic block */ new_bb = new VirtualBasicBlock(current); new_bb->removeAllProp(&ENCLOSING_LOOP_HEADER); new_bb->removeAllProp(&EXIT_LIST); new_bb->removeAllProp(&REVERSE_DOM); new_bb->removeAllProp(&LOOP_EXIT_EDGE); new_bb->removeAllProp(&LOOP_HEADER); new_bb->removeAllProp(&ENTRY); /* Remember the call block so we can correct its destination when we have processed it */ if (VIRTUAL_RETURN_BLOCK(new_bb)) virtualCallList.put(new_bb); if ((current == header) && (!dont_unroll)) { if (i == 0) { unrolled_from = new_bb; } else { UNROLLED_FROM(new_bb) = unrolled_from; } } /* if (ipet::LOOP_COUNT(new_bb) != -1) { if (i == 0) { new_bb->removeAllProp(&ipet::LOOP_COUNT); } else { int old_count = ipet::LOOP_COUNT(new_bb); new_bb->removeAllProp(&ipet::LOOP_COUNT); ipet::LOOP_COUNT(new_bb) = old_count - (1 - start); ASSERT(ipet::LOOP_COUNT(new_bb) >= 0); } } */ INDEX(new_bb) = idx; idx++; vcfg->addBB(new_bb); bbs.add(current); map.put(current, new_bb); } /* add successors which are in loop (including possible sub-loop headers) */ for (BasicBlock::OutIterator outedge(current); outedge; outedge++) { if (outedge->target() == cfg->exit()) continue; if (outedge->kind() == Edge::CALL) continue; if (ENCLOSING_LOOP_HEADER(outedge->target()) == header) { // cout << "Test for add: " << outedge->target()->number() << "\n"; if (!doneList.contains(outedge->target())) { workList.put(outedge->target()); doneList.add(outedge->target()); } } if (LOOP_EXIT_EDGE(outedge)) { ASSERT(new_bb); /* Connect exit edge */ VirtualBasicBlock *vdst = map.get(outedge->target()); new Edge(new_bb, vdst, outedge->kind()); } } } } while (!virtualCallList.isEmpty()) { BasicBlock *vcall = virtualCallList.get(); BasicBlock *vreturn = map.get(VIRTUAL_RETURN_BLOCK(vcall), 0); ASSERT(vreturn != 0); VIRTUAL_RETURN_BLOCK(vcall) = vreturn; } while (!loopList.isEmpty()) { BasicBlock *loop = loopList.get(); unroll(cfg, loop, vcfg); } /* Connect the internal edges for the current loop */ for (genstruct::Vector<BasicBlock*>::Iterator bb(bbs); bb; bb++) { for (BasicBlock::OutIterator outedge(bb); outedge; outedge++) { if (LOOP_EXIT_EDGE(outedge)) continue; if (LOOP_HEADER(outedge->target()) && (outedge->target() != header)) continue; if (outedge->target() == cfg->exit()) continue; VirtualBasicBlock *vsrc = map.get(*bb, 0); VirtualBasicBlock *vdst = map.get(outedge->target(), 0); if (outedge->kind() == Edge::CALL) { CFG *called_cfg = outedge->calledCFG(); int called_idx = INDEX(called_cfg); CFG *called_vcfg = coll->get(called_idx); Edge *vedge = new Edge(vsrc, called_vcfg->entry(), Edge::CALL); CALLED_BY(called_vcfg).add(vedge); ENTRY(called_vcfg->entry()) = called_vcfg; CALLED_CFG(outedge) = called_vcfg; /* XXX: ??!? */ } else if ((outedge->target() != header) || ((i == 1) /* XXX && !dont_unroll XXX*/ )) { new Edge(vsrc, vdst, outedge->kind()); } else { backEdges.add(pair(vsrc, outedge->kind())); } } } if (i == start) { /* Connect virtual entry edges */ if (header) { for (BasicBlock::InIterator inedge(header); inedge; inedge++) { if (Dominance::dominates(header, inedge->source())) continue; /* skip back edges */ if (inedge->source() == cfg->entry()) continue; VirtualBasicBlock *vsrc = map.get(inedge->source()); VirtualBasicBlock *vdst = map.get(header); new Edge(vsrc, vdst, inedge->kind()); } } } else { /* Connect virtual backedges from the first to the other iterations */ for (BackEdgePairVector::Iterator iter(backEdges); iter; iter++) { VirtualBasicBlock *vdst = map.get(header); new Edge((*iter).fst, vdst, (*iter).snd); } } } if (!header) { /* add main entry edges */ for (BasicBlock::OutIterator outedge(cfg->entry()); outedge; outedge++) { VirtualBasicBlock *vdst = map.get(outedge->target()); new Edge(vcfg->entry(), vdst, Edge::VIRTUAL_CALL); } /* add main exit edges */ for (BasicBlock::InIterator inedge(cfg->exit()); inedge; inedge++) { VirtualBasicBlock *vsrc = map.get(inedge->source()); new Edge(vsrc, vcfg->exit(), Edge::VIRTUAL_RETURN); } } }
graphchi_edge<EdgeDataType> * random_outedge() { if (this->outc == 0) return NULL; return outedge((int) (std::abs(random()) % this->outc)); }
void VARIABLE_IS_NOT_USED remove_outedge(int i) { remove_edgev(outedge(i)); }
/** * Returns ith edge of a vertex, ignoring * edge direction. */ graphchi_edge<EdgeDataType> * edge(int i) { if (i < this->inc) return inedge(i); else return outedge(i - this->inc); }