Beispiel #1
0
void LoopReductor::processWorkSpace(otawa::WorkSpace *fw) {

	int idx = 0;

	const CFGCollection *orig_coll = INVOLVED_CFGS(fw);
	if (reduce_loops) {

		for (CFGCollection::Iterator cfg(*orig_coll); cfg; cfg++) {
			VirtualCFG *vcfg = new VirtualCFG(false);
			if (ENTRY_CFG(fw) == *cfg)
				ENTRY_CFG(fw) = vcfg;
			vcfgvec.add(vcfg);
			INDEX(vcfg) = INDEX(cfg);
			LABEL(vcfg) = LABEL(cfg);
			ENTRY(vcfg->entry()) = vcfg;

		}

		int i = 0;
		for (CFGCollection::Iterator cfg(*orig_coll); cfg; cfg++, i++) {
			VirtualCFG *vcfg = vcfgvec.get(i);

			idx = 0;
			INDEX(vcfg->entry()) = idx;
			vcfg->addBB(vcfg->entry());
			idx++;

			reduce(vcfg, cfg);

			INDEX(vcfg->exit()) = idx;
			vcfg->addBB(vcfg->exit());

			/* Renum basic blocks */
			idx = 0;
			for (CFG::BBIterator bb(vcfg); bb; bb++) {
				INDEX(bb) = idx;
				idx++;
			}
		}

	INVOLVED_CFGS(fw) = NULL;
	} else {
		for (CFGCollection::Iterator cfg(*orig_coll); cfg; cfg++) {

			Vector<BasicBlock*> *ancestors = new Vector<BasicBlock*>();

			for (CFG::BBIterator bb(cfg); bb; bb++) {
				IN_LOOPS(bb) = new dfa::BitSet(cfg->countBB());
			}

			/* Do the Depth-First Search, compute the ancestors sets, and mark loop headers */
			depthFirstSearch(cfg->entry(), ancestors);
			delete ancestors;
		}

	}

}
Beispiel #2
0
	CacheListener(WorkSpace *ws, Problem& prob, int set, Identifier<typename P::Domain *>& id)
	: _prob(prob), _set(set), _id(id) {
		const CFGCollection *col = INVOLVED_CFGS(ws);
		for(int i = 0; i < col->count();  i++)
			for (CFG::BBIterator bb(col->get(i)); bb; bb++)
				prob.init(_id(bb)[_set], prob.bottom());
	}
Beispiel #3
0
void CATBuilder::cleanup(WorkSpace *ws) {
	static cstring cat_names[] = {
			"INV",
			"AH",
			"FH",
			"FM",
			"AM",
			"NC"
	};

	if(!logFor(LOG_BB))
		return;

	const CFGCollection *cfgs = INVOLVED_CFGS(ws);
	ASSERT(cfgs);
	for(int i = 0; i < cfgs->count(); i++)
		for(CFG::BBIterator bb(cfgs->get(i)); bb; bb++) {
			cerr << "\tBB " << bb->number() << " (" << bb->address() << ")\n";
			Pair<int, BlockAccess *> ab = DATA_BLOCKS(bb);
			for(int j = 0; j < ab.fst; j++) {
				BlockAccess& b = ab.snd[j];
				cerr << "\t\t" << b << " -> " << cat_names[dcache::CATEGORY(b)] << io::endl;
			}
		}
}
Beispiel #4
0
void BBCleaner::clean(void) {
	const CFGCollection *coll = INVOLVED_CFGS(ws);
	ASSERT(coll);
	for(CFGCollection::Iterator cfg(coll); cfg; cfg++)
		for(CFG::BBIterator bb(cfg); bb; bb++)
			clean(ws, cfg, bb);
}
Beispiel #5
0
void CFGProcessor::processWorkSpace(WorkSpace *fw) {

	// Get the CFG collection
	const CFGCollection *cfgs = INVOLVED_CFGS(fw);
	ASSERT(cfgs);

	// Visit CFG
	int count = 0;
	for(CFGCollection::Iterator cfg(cfgs); cfg; cfg++) {
		if(logFor(LOG_CFG))
			log << "\tprocess CFG " << cfg->label() << io::endl;
		_cfg = cfg;
		processCFG(fw, cfg);
		count++;
	}
	
	// Record stats
	if(recordsStats())
		PROCESSED_CFG(stats) = count;	
}
void BBSize::processWorkSpace(WorkSpace* ws)
{
	const CFGCollection* cfgs = INVOLVED_CFGS(ws);
	ASSERT(cfgs);

	int totalSize = 0;
	int totalNum = 0;

	int totalMax = 0;

	for(CFGCollection::Iterator cfg(cfgs); cfg; cfg++)
	{
		int cfgSize = 0;
		int cfgNum = 0;

		int cfgMax = 0;

		for(CFG::BBIterator bb(cfg); bb; bb++)
		{
			if(bb->size() > 0)
			{
				cfgSize += bb->size();
				cfgNum++;
				totalSize += bb->size();
				totalNum++;

				if(bb->size() > cfgMax)
					cfgMax = bb->size();
				if(bb->size() > totalMax)
					totalMax = bb->size();
			}
		}

		elm::cout << "CFG " << cfg->label() << " avg " << ((float)cfgSize/(float)cfgNum) << " max " << cfgMax << elm::io::endl;
	}

	elm::cout << "PROG avg " << ((float)totalSize/(float)totalNum) << " max " << totalMax << elm::io::endl;
}
Beispiel #7
0
void CATBuilder::cleanup(WorkSpace *ws) {
	static cstring cat_names[] = {
		"INV",
		"AH",
		"FH",
		"PE",
		"AM",
		"NC"
	};

	if(!logFor(LOG_BB))
		return;

	int stats[cache::NOT_CLASSIFIED + 1], total  = 0;
	array::set(stats, NOT_CLASSIFIED + 1, 0);

	const CFGCollection *cfgs = INVOLVED_CFGS(ws);
	ASSERT(cfgs);
	for(int i = 0; i < cfgs->count(); i++)
		for(CFG::BBIterator bb(cfgs->get(i)); bb; bb++) {
			cerr << "\tBB " << bb->number() << " (" << bb->address() << ")\n";
			Pair<int, BlockAccess *> ab = DATA_BLOCKS(bb);
			for(int j = 0; j < ab.fst; j++) {
				BlockAccess& b = ab.snd[j];
				cerr << "\t\t" << b << " -> " << cat_names[dcache::CATEGORY(b)] << io::endl;
				stats[dcache::CATEGORY(b)]++;
				total++;
			}
		}
	if(logFor(LOG_FUN)) {
		for(int i = cache::ALWAYS_HIT; i <= cache::NOT_CLASSIFIED; i++)
			cerr << cat_names[i] << "   : " << io::fmt(stats[i]).width(5).right()
				 << " (" << io::fmt(double(stats[i] * 100) / total).width(5, 2).right() << "%)\n";
		cerr << "total: " << total << io::endl;
	}
}
Beispiel #8
0
void LoopUnroller::processWorkSpace(otawa::WorkSpace *fw) {
	int cfgidx = 0;
	const CFGCollection *orig_coll = INVOLVED_CFGS(fw);

	// Create the new VCFG collection first, so that it will be available when we do the loop unrolling
	for (CFGCollection::Iterator cfg(*orig_coll); cfg; cfg++, cfgidx++) {
		VirtualCFG *vcfg = new VirtualCFG(false);
		coll->add(vcfg);
		INDEX(vcfg) = cfgidx;
		vcfg->addBB(vcfg->entry());
	}


	cfgidx = 0;
	for (CFGCollection::Iterator vcfg(*coll), cfg(*orig_coll); vcfg; vcfg++, cfg++) {
		ASSERT(INDEX(vcfg) == INDEX(cfg));
		LABEL(vcfg) = cfg->label();
		INDEX(vcfg->entry()) = 0;


		idx = 1;
//		if (isVerbose()) {
			cout << "Processing CFG: " << cfg->label() << "\n";
		//}

		/* !!GRUIK!! Ca serait bien d'avoir une classe VCFGCollection */
		VirtualCFG *casted_vcfg = static_cast<otawa::VirtualCFG*>((otawa::CFG*)vcfg);

		unroll((otawa::CFG*) cfg, 0, casted_vcfg);
		if (ENTRY_CFG(fw) == cfg)
			ENTRY_CFG(fw) = vcfg;

		casted_vcfg->addBB(vcfg->exit());
		INDEX(vcfg->exit()) = idx;
	}
}
Beispiel #9
0
void CATBuilder::processLBlockSet(WorkSpace *ws, const BlockCollection& coll, const hard::Cache *cache) {
	if(coll.count() == 0)
		return;

	// prepare problem
	int line = coll.cacheSet();
	MUSTPERS prob(&coll, ws, cache);
	MUSTPERS::Domain dom = prob.bottom();
	acs_stack_t empty_stack;
	if(logFor(LOG_FUN))
		log << "\tSET " << line << io::endl;

	const CFGCollection *cfgs = INVOLVED_CFGS(ws);
	ASSERT(cfgs);
	for(int i = 0; i < cfgs->count(); i++) {
		if(logFor(LOG_BB))
			log << "\t\tCFG " << cfgs->get(i) << io::endl;

		for(CFG::BBIterator bb(cfgs->get(i)); bb; bb++) {
			if(logFor(LOG_BB))
				log << "\t\t\t" << *bb << io::endl;

			// get the input domain
			acs_table_t *ins = MUST_ACS(bb);
			prob.setMust(dom, *ins->get(line));
			acs_table_t *pers = PERS_ACS(bb);
			bool has_pers = pers;
			if(!has_pers)
				prob.emptyPers(dom);
			else {
				acs_stack_t *stack;
				acs_stack_table_t *stack_table = LEVEL_PERS_ACS(bb);
				if(stack_table)
					stack = &stack_table->item(line);
				else
					stack = &empty_stack;
				prob.setPers(dom, *pers->get(line), *stack);
			}

			// explore the adresses
			Pair<int, BlockAccess *> ab = DATA_BLOCKS(bb);
			for(int j = 0; j < ab.fst; j++) {
				BlockAccess& b = ab.snd[j];
				if(b.kind() != BlockAccess::BLOCK) {
					CATEGORY(b) = cache::NOT_CLASSIFIED;
					prob.ageAll(dom);
				}
				else if(b.block().set() == line) {

					// initialization
					bool done = false;
					CATEGORY(b) = cache::NOT_CLASSIFIED;
					ACS *may = 0;
					if(MAY_ACS(bb) != 0)
						may = MAY_ACS(bb)->get(line);

					// in MUST ?
					if(dom.getMust().contains(b.block().index()))
						CATEGORY(b) = cache::ALWAYS_HIT;

					// persistent ?
					else if(has_pers) {

						// find the initial header
						BasicBlock *header;
						if (LOOP_HEADER(bb))
							header = bb;
					  	else
					  		header = ENCLOSING_LOOP_HEADER(bb);

						// look in the different levels
						for(int k = dom.getPers().length() - 1; k >= 0 && header; k--) {
							if(dom.getPers().isPersistent(b.block().index(), k)) {
								CATEGORY(b) = cache::FIRST_MISS;
								CATEGORY_HEADER(b) = header;
								done = true;
								break;
							}
							header = ENCLOSING_LOOP_HEADER(header);
						}
					}

					// out of MAY ?
					if(!done && may && !may->contains(b.block().index()))
						CATEGORY(b) = cache::ALWAYS_MISS;

					// update state
					prob.inject(dom, b.block().index());
				}
			}
		}
	}
}
Beispiel #10
0
/**
 * Trigger associated with CFG. For each CFG, perform a call to
 * @ref cleanupCFG() that may be customized by a subclass.
 */
void CFGProcessor::doCleanUp(void) {
	const CFGCollection *coll = INVOLVED_CFGS(workspace());
	for(int i = 0; i < coll->count(); i++)
		cleanupCFG(workspace(), coll->get(i));
}
Beispiel #11
0
void Builder::processLBlockSet(WorkSpace *fw, otawa::ccg::LBlockSet *lbset) {
	ASSERT(fw);
	ASSERT(lbset);
	const hard::Cache *cache = hard::CACHE_CONFIGURATION(fw)->instCache();

	// Create the CCG
	Collection *ccgs = Graph::GRAPHS(fw);
	if(!ccgs) {
		ccgs = new Collection(cache->rowCount());
		fw->addProp(new DeletableProperty<Collection *>(Graph::GRAPHS, ccgs));
	}
	Graph *ccg = new Graph;
	ccgs->ccgs[lbset->line()] = ccg;

	// Initialization
	for(LBlockSet::Iterator lblock(*lbset); lblock; lblock++) {
		Node *node = new Node(lblock);
		ccg->add(node);
		Graph::NODE(lblock) = node;
	}

	// Run the DFA
	Problem prob(lbset, lbset->count(), cache, fw);
	const CFGCollection *coll = INVOLVED_CFGS(fw);
	dfa::XCFGVisitor<Problem> visitor(*coll, prob);
	dfa::XIterativeDFA<dfa::XCFGVisitor<Problem> > engine(visitor);
	engine.process();

	// Add the annotations from the DFA result
	for (CFGCollection::Iterator cfg(coll); cfg; cfg++) {
		for (CFG::BBIterator block(*cfg); block; block++) {
			dfa::XCFGVisitor<Problem>::key_t pair(*cfg, *block);
			dfa::BitSet *bitset = engine.in(pair);
			block->addProp(new DeletableProperty<dfa::BitSet *>(IN, new dfa::BitSet(*bitset)));
		}
	}

	// Detecting the non conflict state of each lblock
	BasicBlock *BB;
	LBlock *line;
	int length = lbset->count();
	for(LBlockSet::Iterator lbloc(*lbset); lbloc; lbloc++)
		if(lbloc->id() != 0 && lbloc->id() != length - 1) {
			BB = lbloc->bb();
			dfa::BitSet *inid = IN(BB);
			for(dfa::BitSet::Iterator bit(*inid); bit; bit++)
				line = lbset->lblock(*bit);
				if(cache->block(line->address()) == cache->block(lbloc->address())
					&& BB != line->bb())
					NON_CONFLICT(lbloc) = true;

		}

	// Building the ccg edges using DFA
	length = lbset->count();
	address_t adinst;
	LBlock *aux;

	for (CFGCollection::Iterator cfg(coll); cfg; cfg++) {
		for (CFG::BBIterator bb(*cfg); bb; bb++) {
			if ((cfg != ENTRY_CFG(fw)) || (!bb->isEntry() && !bb->isExit())) {
				dfa::BitSet *info = IN(bb);
				ASSERT(info);
				bool test = false;
				bool visit;
				for(BasicBlock::InstIter inst(bb); inst; inst++) {
					visit = false;
					adinst = inst->address();
					for (LBlockSet::Iterator lbloc(*lbset); lbloc; lbloc++){
						address_t address = lbloc->address();
						// the first lblock in the BB it's a conflict
						if(adinst == address && !test && bb == lbloc->bb()) {
							for (int i = 0; i< length; i++)
								if (info->contains(i)) {
									LBlock *lblock = lbset->lblock(i);
									Node *node = Graph::NODE(lblock);
									new Edge (node, Graph::NODE(lbloc));
								}
							aux = lbloc;
							test = true;
							visit = true;
							break;
						}

						if(adinst == address && !visit && bb == lbloc->bb()) {
							new Edge(Graph::NODE(aux), Graph::NODE(lbloc));
							aux = lbloc;
							break;
						}
					}
				}
			}
		}
	}

	// build edge to LBlock end
	BasicBlock *exit = ENTRY_CFG(fw)->exit();
	LBlock *end = lbset->lblock(length-1);
	dfa::BitSet *info = IN(exit);
	for (int i = 0; i< length; i++)
		if (info->contains(i)) {
			LBlock *ccgnode1 = lbset->lblock(i);
			new Edge(Graph::NODE(ccgnode1), Graph::NODE(end));
		}

	// Build edge from 'S' till 'end'
	LBlock *s = lbset->lblock(0);
	new Edge(Graph::NODE(s), Graph::NODE(end));

	// Cleanup the DFA annotations
	for (CFGCollection::Iterator cfg(coll); cfg; cfg++)
		for (CFG::BBIterator block(cfg); block; block++)
			block->removeProp(&IN);
}
Beispiel #12
0
void LoopUnroller::cleanup(WorkSpace *ws) {
	INVOLVED_CFGS(ws) = coll;
	ENTRY_CFG(ws) = coll->get(0);
}