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); } } }
void VARIABLE_IS_NOT_USED remove_inedge(int i) { remove_edgev(inedge(i)); }
void EdgeCAT2Builder::processLBlockSet(otawa::CFG *cfg, LBlockSet *lbset, const hard::Cache *cache) { unsigned int line = lbset->line(); /*static double moypr = 0; static double moy = 0;*/ /* Use the results to set the categorization */ for (LBlockSet::Iterator lblock(*lbset); lblock; lblock++) { if ((lblock->id() == 0) || (lblock->id() == lbset->count() - 1)) continue; Vector<MUSTProblem::Domain*> &mustVec = *CACHE_EDGE_ACS_MUST(lblock); Vector<PERSProblem::Domain*> &persVec = *CACHE_EDGE_ACS_PERS(lblock); CATEGORY_EDGE(lblock) = new Vector<category_t>(); CATEGORY_EDGE_HEADER(lblock) = new Vector<BasicBlock*>(); BasicBlock::InIterator inedge(lblock->bb()); for (int i = 0; i < mustVec.length(); i++) { MUSTProblem::Domain *must = mustVec[i]; PERSProblem::Domain *pers = NULL; if (firstmiss_level != FML_NONE) { pers = persVec[i]; /* enter/leave context if in-edge enters or exits loops */ if (LOOP_EXIT_EDGE(inedge)) { /* find loop header of inner-most exited loop */ BasicBlock *header = inedge->source(); if (!LOOP_HEADER(header)) header = ENCLOSING_LOOP_HEADER(header); ASSERT(header && LOOP_HEADER(header)); /* now leave contexts for each loop between header and LOOP_EXIT_EDGE(inedge) (included) */ pers->leaveContext(); while (header != LOOP_EXIT_EDGE(inedge)) { pers->leaveContext(); header = ENCLOSING_LOOP_HEADER(header); ASSERT(header); } } if (LOOP_HEADER(lblock->bb()) && !BACK_EDGE(inedge)) { /* an entry edge may not enter more than one loop */ pers->enterContext(); } } BasicBlock *header = NULL; category_t cat = NOT_CLASSIFIED; BasicBlock *cat_header = NULL; if (must->contains(lblock->cacheblock())) { cat = ALWAYS_HIT; } else if (firstmiss_level != FML_NONE) { if (Dominance::isLoopHeader(lblock->bb())) header = lblock->bb(); else header = ENCLOSING_LOOP_HEADER(lblock->bb()); int bound; bool perfect_firstmiss = true; bound = 0; if ((pers->length() > 1) && (firstmiss_level == FML_INNER)) bound = pers->length() - 1; cat_header = NULL; for (int k = pers->length() - 1 ; (k >= bound) && (header != NULL); k--) { if (pers->isPersistent(lblock->cacheblock(), k)) { cat = FIRST_MISS; cat_header = header; } else perfect_firstmiss = false; header = ENCLOSING_LOOP_HEADER(header); } if ((firstmiss_level == FML_OUTER) && (perfect_firstmiss == false)) cat = ALWAYS_MISS; } /* of category condition test */ CATEGORY_EDGE(lblock)->add(cat); CATEGORY_EDGE_HEADER(lblock)->add(cat_header); inedge++; } } }
/** * 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); }