Example #1
0
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;
}
Example #2
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);
		}
	}

}
 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);
 }