OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [Var.cpp] - Rev 48

Compare with Previous | Blame | View Log

// ============================================================================
//        __
//   \\__/ o\    (C) 2017-2018  Robert Finch, Waterloo
//    \  __ /    All rights reserved.
//     \/_//     robfinch<remove>@finitron.ca
//       ||
//
// CC64 - 'C' derived language compiler
//  - 64 bit CPU
//
// This source file is free software: you can redistribute it and/or modify 
// it under the terms of the GNU Lesser General Public License as published 
// by the Free Software Foundation, either version 3 of the License, or     
// (at your option) any later version.                                      
//                                                                          
// This source file is distributed in the hope that it will be useful,      
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
// GNU General Public License for more details.                             
//                                                                          
// You should have received a copy of the GNU General Public License        
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
//                                                                          
// ============================================================================
//
#include "stdafx.h"
 
// This class is currently only used by the CreateForest() function.
// It maintains a stack for tree traversal.
 
class WorkList
{
	int ndx;
	BasicBlock *p[10000];
public:
	WorkList() { ndx = 0; };
	void push(BasicBlock *q) {
		if (ndx < 9999) {
			p[ndx] = q;
			ndx++;
		}
	};
	BasicBlock *pop() {
		ndx--;
		return p[ndx];
	};
	bool IsEmpty() {
		return (ndx==0);
	};
};
 
WorkList wl;
Tree *tree;
int Var::nvar;
 
Var *Var::MakeNew()
{
	Var *p;
 
	p = (Var *)allocx(sizeof(Var));
	p->forest = CSet::MakeNew();
	p->visited = CSet::MakeNew();
	nvar++;
	return (p);
}
 
// Live ranges are represented as tree structures.
// Since there could be multiple live ranges (trees) for any given variable
// the group of ranges (or trees) is called a forest.
/*
void Var::CreateForest()
{
	Edge *ep;
	BasicBlock *p, *b;
	CSet *pushSet;
 
	pushSet = CSet::MakeNew();
	treeno = 0;
	tree = Tree::MakeNew();
	tree->next = trees;
	tree->num = treeno;
	treeno++;
	trees = tree;
	wl.push(LastBlock);
	pushSet->clear();
	while (!wl.IsEmpty()) {
		b = wl.pop();
		if (b->LiveOut->isMember(num)) {
			tree->tree->add(b->num);
			for (ep = b->ihead; ep; ep = ep->next) {
				//if (ep->backedge)
				//	continue;
				p = ep->src;
				if (p) {
//					if (p->LiveOut->isMember(num)) {
//						tree->tree->add(p->num);
						if (!pushSet->isMember(p->num)) {
							wl.push(p);
							pushSet->add(p->num);
						}
//					}
				}
			}
			/*
			for (ep = b->ohead; ep; ep = ep->next) {
				//if (!ep->backedge)
				//	continue;
				p = ep->dst;
				if (p) {
					if (p->LiveOut->isMember(num)) {
						tree->tree->add(p->num);
						if (!pushSet->isMember(p->num)) {
							wl.push(p);
							pushSet->add(p->num);
						}
					}
				}
			}
			*/
			/*
			if (b->prev) {
				if (b->prev->LiveOut->isMember(num)) {
					tree->tree->add(b->prev->num);
				}
				else {
					tree = Tree::MakeNew();
					tree->next = trees;
					tree->num = treeno;
					treeno++;
					trees = tree;
				}
				wl.push(b->prev);
			}
			*/
/*
		}
		else {
			tree = Tree::MakeNew();
			tree->next = trees;
			tree->num = treeno;
			treeno++;
			trees = tree;
			for (ep = b->ihead; ep; ep = ep->next) {
				p = ep->src;
				if (p) {
					if (!pushSet->isMember(p->num)) {
						wl.push(p);
						pushSet->add(p->num);
					}
				}
			}
			//if (b->prev)
			//	wl.push(b->prev);
		}
	}
}
*/
 
void Var::GrowTree(Tree *t, BasicBlock *b)
{
	Edge *ep;
	BasicBlock *p;
 
	for (ep = b->ihead; ep; ep = ep->next) {
//		if (!ep->backedge) {
			p = ep->src;
			if (!visited->isMember(p->num)) {
				visited->add(p->num);
				if (p->LiveOut->isMember(num)) {
					if (t==nullptr) {
						t = Tree::MakeNew();
						::forest.PlantTree(t);
						trees.PlantTree(t);
						trees.map[num] = t->num;
						::forest.map[num] = t->num;
						t->var = num;
						t->lattice = b->depth;
					}
					t->blocks->add(p->num);
					t->lattice = max(t->lattice, p->depth);
					forest->add(p->num);
					GrowTree(t, p);
				}
				else
					GrowTree(nullptr, p);
			}
//		}
	}
	for (ep = b->ohead; ep; ep = ep->next) {
//		if (ep->backedge) {
			p = ep->src;
			if (!visited->isMember(p->num)) {
				visited->add(p->num);
				if (p->LiveOut->isMember(num)) {
					if (t==nullptr) {
						t = Tree::MakeNew();
						::forest.PlantTree(t);
						trees.PlantTree(t);
						trees.map[num] = t->num;
						::forest.map[num] = t->num;
						t->lattice = b->depth;
						t->var = num;
					}
					t->blocks->add(p->num);
					t->lattice = max(t->lattice, p->depth);
					forest->add(p->num);
					GrowTree(t, p);
				}
				else {
					GrowTree(nullptr, p);
				}
			}
//		}
	}
}
 
void Var::CreateForest()
{
	BasicBlock *b, *p;
	Edge *ep;
	Tree *t;
	char buf[2000];
 
	b = currentFn->LastBlock;
	visited->add(b->num);
	// First see if a tree starts right at the last basic block.
	if (b->LiveOut->isMember(num)) {
		t = Tree::MakeNew();
		::forest.PlantTree(t);
		trees.PlantTree(t);
		trees.map[num] = t->num;
		::forest.map[num] = t->num;
		t->var = num;
		t->lattice = b->depth;
		t->blocks->add(b->num);
		forest->add(b->num);
		GrowTree(t, b);
	}
	//else
	{
	// Next check all the input edges to the last block that
	// haven't yet been visited for additional trees.
	for (ep = b->ihead; ep; ep = ep->next) {
//		if (!ep->backedge) {
			p = ep->src;
			if (!visited->isMember(p->num)) {
				visited->add(p->num);
				if (p->LiveOut->isMember(num)) {
					t = Tree::MakeNew();
					::forest.PlantTree(t);
					trees.PlantTree(t);
					trees.map[num] = t->num;
					::forest.map[num] = t->num;
					t->var = num;
					t->lattice = p->depth;
					t->blocks->add(p->num);
					forest->add(p->num);
					GrowTree(t, p);
				}
				else {
					GrowTree(nullptr, p);
				}
			}
//		}
	}
	for (ep = b->ohead; ep; ep = ep->next) {
//		if (ep->backedge) {
			p = ep->src;
			if (!visited->isMember(p->num)) {
				visited->add(p->num);
				if (p->LiveOut->isMember(num)) {
					t = Tree::MakeNew();
					::forest.PlantTree(t);
					trees.PlantTree(t);
					trees.map[num] = t->num;
					::forest.map[num] = t->num;
					t->var = num;
					t->lattice = p->depth;
					t->blocks->add(p->num);
					forest->add(p->num);
					GrowTree(t, p);
				}
				else {
					GrowTree(nullptr, p);
				}
			}
//		}
	}
	}
	// Next try moving through the previous basic blocks, there may not be edges
	// to them.
	for (p = b->prev; p; p = p->prev)
	{
		if (!visited->isMember(p->num)) {
			visited->add(p->num);
			if (p->LiveOut->isMember(num)) {
				t = Tree::MakeNew();
				::forest.PlantTree(t);
				trees.PlantTree(t);
				trees.map[num] = t->num;
				::forest.map[num] = t->num;
				t->var = num;
				t->lattice = p->depth;
				t->blocks->add(p->num);
				forest->add(p->num);
				GrowTree(t, p);
			}
			else {
				GrowTree(nullptr, p);
			}
		}
	}
	dfs.printf("Visited r%d: ", num);
	visited->sprint(buf, sizeof(buf));
	dfs.printf(buf);
	dfs.printf("\n");
}
 
void Var::CreateForests()
{
	Var *v;
 
	Tree::treeno = 0;
	::forest.treecount = 0;
	for (v = currentFn->varlist; v; v = v->next) {
		v->visited->clear();
		v->forest->clear();
		v->CreateForest();
	}
}
 
// Find variable info or create if not found.
 
Var *Var::Find(int num)
{
	Var *vp;
 
	for (vp = currentFn->varlist; vp; vp = vp->next) {
		if (vp->num == num)
			break;
	}
	if (vp==nullptr) {
		vp = Var::MakeNew();
		vp->cnum = nvar-1;
		vp->num = num;
		vp->next = currentFn->varlist;
		currentFn->varlist = vp;
	}
	return (vp);
}
 
// Find variable info, but don't create
 
Var *Var::Find2(int num)
{
	Var *vp;
	Tree *t;
 
	for (vp = currentFn->varlist; vp; vp = vp->next) {
		//t = ::forest.trees[num];
		//if (t == nullptr)
		//	return (nullptr);
		if (vp->num == num)//map.newnums[num])
			return(vp);
	}
	return (nullptr);
}
 
 
// Find by machine register. Not used after renumbering.
 
Var *Var::FindByMac(int num)
{
	Var *vp;
 
	for (vp = currentFn->varlist; vp; vp = vp->next) {
		if (vp->num == num)
			return(vp);
	}
	return (nullptr);
}
 
Var *Var::FindByTreeno(int tn)
{
	Var *vp;
	Tree *t;
	int nn;
 
	for (vp = currentFn->varlist; vp; vp = vp->next) {
		for (nn = 0; nn < vp->trees.treecount; nn++) {
			t = vp->trees.trees[nn];
			if (t->treeno == tn)
				return (vp);
		}
	}
	return (nullptr);
}
 
void Var::Renumber(int num, int nnum)
{
	Var *vp;
 
	for (vp = currentFn->varlist; vp; vp = vp->next) {
		if (vp->num == num) {
			vp->num = -nnum;
		}
	}
}
 
void Var::RenumberNeg()
{
	Var *vp;
 
	for (vp = currentFn->varlist; vp; vp = vp->next) {
		vp->num = -vp->num;
	}
}
 
Var *Var::FindByCnum(int num)
{
	Var *vp;
 
	for (vp = currentFn->varlist; vp; vp = vp->next) {
		if (vp->cnum == num)
			return(vp);
	}
	return (nullptr);
}
 
CSet *Var::Find3(int reg, int blocknum)
{
	Var *v;
	Tree *t;
	int n;
 
	v = Find2(reg);
	// Find the tree with the basic block
	for (n = 0; n < v->trees.treecount; n++) {
		t = v->trees.trees[n];
		if (t->blocks->isMember(blocknum)) {
			return (t->blocks);
		}
	}
	// else error:
	return (nullptr);
}
 
 
// Find a specific tree that reg is associated with given
// the basic block number.
 
int Var::FindTreeno(int reg, int blocknum)
{
	Var *v;
	Tree *t;
	int n, m;
 
	// Find the associated variable
	v = Find2(reg);
	if (v == nullptr)
		return (-1);
 
	// Find the tree with the basic block. The individual trees in a given
	// var should be disjoint. Only one tree will contain the block.
	for (m = n = 0; n < v->trees.treecount; n++) {
		t = v->trees.trees[n];
		if (t->blocks->isMember(blocknum))
			return(t->num);
	}
	return (-1);
}
 
 
// Copy trees from one var to another.
 
void Var::Transplant(Var *v)
{
	int nn;
 
	for (nn = 0; nn < v->trees.treecount; nn++) {
		if (trees.treecount < 500) {
			trees.trees[trees.treecount] = v->trees.trees[nn];
			trees.treecount++;
		}
		else
			throw new C64PException(ERR_TOOMANY_TREES,1);
	}
}
 
 
// Coalescing currently doesn't make use of the interference graph.
// This algorithm is slow (n^2).
 
bool Var::Coalesce2()
{
	int reg1, reg2;
	Var *v1, *v2, *v3;
	Var *p, *q;
	Tree *t, *u;
	bool foundSameTree;
	bool improved;
	int nn, mm;
 
	improved = false;
	for (p = currentFn->varlist; p; p = p->next) {
		for (q = currentFn->varlist; q; q = q->next) {
			if (p == q)
				continue;
			reg1 = p->num;
			reg2 = q->num;
			// Registers used as register parameters cannot be coalesced.
			if ((reg1 >= regFirstArg && reg1 <= regLastArg)
				|| (reg2 >= regFirstArg && reg2 <= regLastArg))
				continue;
			// Coalesce the live ranges of the two variables into a single
			// range.
			//dfs.printf("Testing coalescence of live range r%d with ", reg1);
			//dfs.printf("r%d \n", reg2);
			//if (p->num)
				v1 = Var::Find2(p->num);
			//else
			//	v1 = p;
			//if (q->num)
				v2 = Var::Find2(q->num);
			//else
			//	v2 = q;
			if (v1 == nullptr || v2 == nullptr)
				continue;
			if (v1->trees.treecount == 0 || v2->trees.treecount == 0)
				continue;
 
			// Live ranges cannot be coalesced unless they are disjoint.
			if (!v1->forest->isDisjoint(*v2->forest)) {
				//dfs.printf("Live ranges overlap - no coalescence possible\n");
				continue;
			}
 
			dfs.printf("Coalescing live range r%d with ", reg1);
			dfs.printf("r%d \n", reg2);
			improved = true;
			//if (v1->trees.treecount == 0) {
			//	v3 = v1;
			//	v1 = v2;
			//	v2 = v3;
			//}
 
			v1->Transplant(v2);
			v1->forest->add(v2->forest);
/*
			for (nn = 0; nn < v2->trees.treecount; nn++) {
				t = v2->trees.trees[nn];
				foundSameTree = false;
				for (mm = 0; mm < v1->trees.treecount; mm++) {
					u = v1->trees.trees[mm];
					if (t->blocks->NumMember() >= u->blocks->NumMember()) {
						if (t->blocks->isSubset(*u->blocks)) {
							u->blocks->add(t->blocks);
							v1->forest->add(t->blocks);
							foundSameTree = true;
							break;
						}
					}
					else {
						if (u->blocks->isSubset(*t->blocks)) {
							foundSameTree = true;
							t->blocks->add(u->blocks);
							v2->forest->add(u->blocks);
							break;
						}
					}
				}
 
				if (!foundSameTree) {
					//t->next = v1->trees;
					//v1->trees = t;
					v1->Transplant(v2);
					v1->forest->add(v2->forest);
				}
 
			}
*/
			v2->trees.treecount = 0;
			v2->forest->clear();
			//v2->num = v1->num;
			//v2->Transplant(v1);
			//v2->forest->add(v1->forest);
		}
	}
	return (improved);
}
 
int Var::PathCompress(int reg, int blocknum, int *tr)
{
	Var *v;
	Tree *t;
	int n;
 
	*tr = -1;
	v = Find2(reg);
	if (v == nullptr) {
		*tr = -1;
		return (-1);
	}
	// Find the tree with the basic block
	for (n = 0; n < v->trees.treecount; n++) {
		t = v->trees.trees[n];
		if (t->blocks->isMember(blocknum)) {
			break;
		}
	}
	if (n < v->trees.treecount) {
		*tr = t->num;
		t->blocks->resetPtr();
		// The root of the tree is the lowest block number
		return (t->blocks->nextMember());
	}
	// else error: path not found
	return (-1);
}
 
void Var::DumpForests(int n)
{
	Var *vp;
	Tree *rg;
	int nn;
	char buf[2000];
 
	dfs.printf("<VarForests>%d\n", n);
	for (vp = currentFn->varlist; vp; vp = vp->next) {
		dfs.printf("Var%d:", vp->num);
		if (vp->trees.treecount > 0)
			dfs.printf(" %d trees\n", vp->trees.treecount);
		else
			dfs.printf(" no trees\n");
		for (nn = 0; nn < vp->trees.treecount; nn++) {
			dfs.printf("<Tree>%d ", vp->trees.trees[nn]->num);
			dfs.printf("Color:%d ", vp->trees.trees[nn]->color);
			rg = vp->trees.trees[nn];
			if (!rg->blocks->isEmpty()) {
				rg->blocks->sprint(buf, sizeof(buf));
				dfs.printf(buf);
				dfs.printf("</Tree>\n");
			}
		}
		dfs.printf("<Forest>");
		vp->forest->sprint(buf, sizeof(buf));
		dfs.printf(buf);
		dfs.printf("</Forest>\n");
	}
	dfs.printf("</VarForests>\n");
}
 
 
Var *Var::GetVarToSpill(CSet *exc)
{
	Var *vp;
	int tn, vn;
	int nn, mm;
 
	for (vp = currentFn->varlist; vp; vp = vp->next) {
		if (vp != this && vp->num > 2 && vp->num <= 17 && !exc->isMember(vp->num)) {
			tn = ::forest.map[this->num];
			vn = ::forest.map[vp->num];
			nn = min(tn, vn);
			mm = max(tn, vn);
			if (!iGraph.DoesInterfere(nn, mm)) {
				return (vp);
			}
		}
	}
	// error: no register could be spilled.
	return (nullptr);
}
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.