Exemplo n.º 1
0
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);
		}
	}

}
Exemplo n.º 2
0
 void VARIABLE_IS_NOT_USED remove_inedge(int i) {
     remove_edgev(inedge(i));
 }
Exemplo n.º 3
0
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++;
		}
	}
	

}
Exemplo n.º 4
0
 /** 
   * 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);
 }