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

Subversion Repositories thor

[/] [thor/] [trunk/] [FT64v5/] [software/] [CC64/] [source/] [CSETable.cpp] - Rev 59

Go to most recent revision | 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"
 
void CSETable::Assign(CSETable *t)
{
	memcpy(this, t, sizeof(CSETable));
}
 
static int CSECmp(const void *a, const void *b)
{
	CSE *csp1, *csp2;
	int aa, bb;
 
	csp1 = (CSE *)a;
	csp2 = (CSE *)b;
	aa = csp1->OptimizationDesireability();
	bb = csp2->OptimizationDesireability();
	if (aa < bb)
		return (1);
	else if (aa == bb)
		return (0);
	else
		return (-1);
}
 
 
void CSETable::Sort(int(*cmp)(const void *a, const void *b))
{
	qsort(table, (size_t)csendx, sizeof(CSE), cmp);
}
 
// InsertNodeIntoCSEList will enter a reference to an expression node into the
// common expression table. duse is a flag indicating whether or not
// this reference will be dereferenced.
 
CSE *CSETable::InsertNode(ENODE *node, int duse)
{
	CSE *csp;
 
	if ((csp = Search(node)) == nullptr) {   /* add to tree */
		if (csendx > 499)
			throw new C64PException(ERR_CSETABLE, 0x01);
		csp = &table[csendx];
		csendx++;
		if (loop_active > 1) {
			csp->uses = (loop_active - 1) * 5;
			csp->duses = (duse != 0) * ((loop_active - 1) * 5);
		}
		else {
			csp->uses = 1;
			csp->duses = (duse != 0);
		}
		csp->exp = node->Clone();
		csp->voidf = 0;
		csp->reg = 0;
		csp->isfp = csp->exp->IsFloatType();
		return (csp);
	}
	if (loop_active < 2) {
		(csp->uses)++;
		if (duse)
			(csp->duses)++;
	}
	else {
		(csp->uses) += ((loop_active - 1) * 5);
		if (duse)
			(csp->duses) += ((loop_active - 1) * 5);
	}
	return (csp);
}
 
//
// SearchCSEList will search the common expression table for an entry
// that matches the node passed and return a pointer to it.
//
CSE *CSETable::Search(ENODE *node)
{
	int cnt;
 
	for (cnt = 0; cnt < csendx; cnt++) {
		if (ENODE::IsEqual(node, table[cnt].exp))
			return (&table[cnt]);
	}
	return ((CSE *)nullptr);
}
 
// voidauto2 searches the entire CSE table for auto dereferenced node which
// point to the passed node. There might be more than one LValue that matches.
// voidauto will void an auto dereference node which points to
// the same auto constant as node.
//
int CSETable::voidauto2(ENODE *node)
{
	int uses;
	bool voided;
	int cnt;
 
	uses = 0;
	voided = false;
	for (cnt = 0; cnt < csendx; cnt++) {
		if (IsLValue(table[cnt].exp) && ENODE::IsEqual(node, table[cnt].exp->p[0])) {
			table[cnt].voidf = 1;
			voided = true;
			uses += table[cnt].uses;
		}
	}
	return (voided ? uses : -1);
}
 
// Make multiple passes over the CSE table in order to use
// up all temporary registers. Allocates on the progressively
// less desirable.
 
int CSETable::AllocateGPRegisters()
{
	CSE *csp;
	bool alloc;
	int pass;
	int reg;
 
	reg = regFirstRegvar;
	for (pass = 0; pass < 4; pass++) {
		for (csp = First(); csp; csp = Next()) {
			if (csp->OptimizationDesireability() != 0) {
				if (!csp->voidf && csp->reg == -1) {
					if (csp->exp->etype != bt_vector && !csp->isfp) {
						switch (pass)
						{
						case 0:
						case 1:
						case 2:	alloc = (csp->OptimizationDesireability() >= 4) && reg < regLastRegvar; break;
						case 3: alloc = (csp->OptimizationDesireability() >= 4) && reg < regLastRegvar; break;
						}
						if (alloc)
							csp->reg = reg++;
						else
							csp->reg = -1;
					}
				}
			}
		}
	}
	return (reg);
}
 
int CSETable::AllocateFPRegisters()
{
	CSE *csp;
	bool alloc;
	int pass;
	int reg;
 
	reg = regFirstRegvar;
	for (pass = 0; pass < 4; pass++) {
		for (csp = First(); csp; csp = Next()) {
			if (csp->OptimizationDesireability() != 0) {
				if (!csp->voidf && csp->reg == -1) {
					if (csp->isfp) {
						switch (pass)
						{
						case 0:
						case 1:
						case 2:	alloc = (csp->OptimizationDesireability() >= 4) && reg < regLastRegvar; break;
						case 3: alloc = (csp->OptimizationDesireability() >= 4) && reg < regLastRegvar; break;
							//    					if(( csp->duses > csp->uses / (8 << nn)) && reg < regLastRegvar )	// <- address register assignments
						}
						if (alloc)
							csp->reg = reg++;
						else
							csp->reg = -1;
					}
				}
			}
		}
	}
	return (reg);
}
 
int CSETable::AllocateVectorRegisters()
{
	int nn, vreg;
	CSE *csp;
	bool alloc;
 
	vreg = regFirstRegvar;
	for (nn = 0; nn < 4; nn++) {
		for (csp = First(); csp; csp = Next()) {
			if (csp->exp) {
				if (csp->exp->etype == bt_vector && csp->reg == -1 && vreg < regLastRegvar) {
					switch (nn) {
					case 0:
					case 1:
					case 2: alloc = (csp->OptimizationDesireability() >= 4 - nn)
						&& (csp->duses > csp->uses / (8 << nn));
						break;
					case 3:	alloc = (!csp->voidf) && (csp->uses > 3);
						break;
					}
					if (alloc)
						csp->reg = vreg++;
					else
						csp->reg = -1;
				}
			}
		}
	}
	return (vreg);
}
 
void CSETable::InitializeTempRegs()
{
	Operand *ap, *ap2, *ap3;
	CSE *csp;
	ENODE *exptr;
	int size;
 
	for (csp = First(); csp; csp = Next()) {
		if (csp->reg != -1)
		{               // see if preload needed
			exptr = csp->exp;
			if (1 || !IsLValue(exptr) || (exptr->p[0]->i > 0))
			{
				initstack();
				{
					ap = GenerateExpression(exptr, F_REG | F_IMMED | F_MEM | F_FPREG, sizeOfWord);
					ap2 = csp->isfp ? makefpreg(csp->reg) : makereg(csp->reg);
					if (csp->isfp)
						ap2->type = ap->type;
					ap2->isPtr = ap->isPtr;
					if (ap->mode == am_imm) {
						if (ap2->mode == am_fpreg) {
							ap3 = GetTempRegister();
							GenLdi(ap3, ap);
							GenerateDiadic(op_mov, 0, ap2, ap3);
							ReleaseTempReg(ap3);
						}
						else
							GenLdi(ap2, ap);
					}
					else if (ap->mode == am_reg)
						GenerateDiadic(op_mov, 0, ap2, ap);
					else {
						size = GetNaturalSize(exptr);
						ap->isUnsigned = exptr->isUnsigned;
						GenLoad(ap2, ap, size, size);
					}
				}
				ReleaseTempReg(ap);
			}
		}
	}
 
}
 
void CSETable::GenerateRegMask(CSE *csp, uint64_t *mask, uint64_t *rmask)
{
	if (csp->reg != -1)
	{
		*rmask = *rmask | (1LL << (63 - csp->reg));
		*mask = *mask | (1LL << csp->reg);
	}
}
 
// ----------------------------------------------------------------------------
// AllocateRegisterVars will allocate registers for the expressions that have
// a high enough desirability.
// ----------------------------------------------------------------------------
 
int CSETable::AllocateRegisterVars()
{
	CSE *csp;
	uint64_t mask, rmask;
	uint64_t fpmask, fprmask;
	uint64_t vmask, vrmask;
 
	mask = 0;
	rmask = 0;
	fpmask = 0;
	fprmask = 0;
	vmask = 0;
	vrmask = 0;
 
	// Sort the CSE table according to desirability of allocating
	// a register.
	if (pass == 1)
		Sort(CSECmp);
 
	// Initialize to no allocated registers
	for (csp = First(); csp; csp = Next())
		csp->reg = -1;
 
	AllocateGPRegisters();
	AllocateFPRegisters();
	AllocateVectorRegisters();
 
	// Generate bit masks of allocated registers
	for (csp = First(); csp; csp = Next()) {
		if (csp->exp) {
			if (csp->exp->IsFloatType())
				GenerateRegMask(csp, &fpmask, &fprmask);
			else if (csp->exp->etype == bt_vector)
				GenerateRegMask(csp, &vrmask, &vmask);
			else
				GenerateRegMask(csp, &mask, &rmask);
		}
		else
			GenerateRegMask(csp, &mask, &rmask);
	}
 
	Dump();
 
	// Push temporaries on the stack.
	SaveRegisterVars(mask, rmask);
	SaveFPRegisterVars(fpmask, fprmask);
 
	save_mask = mask;
	fpsave_mask = fpmask;
 
	InitializeTempRegs();
	return (popcnt(mask));
}
 
/*
*      opt1 is the externally callable optimization routine. it will
*      collect and allocate common subexpressions and substitute the
*      tempref for all occurrances of the expression within the block.
*/
int CSETable::Optimize(Statement *block)
{
	int nn;
 
	//csendx = 0;
	dfs.printf("<CSETable__Optimize>");
	nn = 0;
	if (pass == 1) {
		if (currentFn->csetbl == nullptr) {
			currentFn->csetbl = new CSETable;
		}
		Clear();
	}
	else if (pass == 2) {
		//Assign(currentFn->csetbl);
	}
	dfs.printf("Pass:%d ", pass);
	if (opt_noregs == FALSE) {
		if (pass == 1)
			block->scan();            /* collect expressions */
		nn = AllocateRegisterVars();
		if (pass == 2)
			block->repcse();          /* replace allocated expressions */
	}
	if (pass == 1)
		;// currentFn->csetbl->Assign(pCSETable);
	else if (pass == 2) {
		if (currentFn->csetbl && !currentFn->IsInline) {
			delete currentFn->csetbl;
			currentFn->csetbl = nullptr;
		}
	}
	dfs.printf("</CSETable__Optimize>\n");
	return (nn);
}
 
// Immediate constants have low priority.
// Even though their use might be high, they are given a low priority.
 
void CSETable::Dump()
{
	int nn;
	CSE *csp;
 
	dfs.printf("<CSETable>For %s\n", (char *)currentFn->sym->name->c_str());
	dfs.printf(
		"*The expression must be used three or more times before it will be allocated\n"
		"to a register.\n");
	dfs.printf("N OD Uses DUses Void Reg Sym\n");
	for (nn = 0; nn < csendx; nn++) {
		csp = &table[nn];
		dfs.printf("%d: ", nn);
		dfs.printf("%d   ", csp->OptimizationDesireability());
		dfs.printf("%d   ", csp->uses);
		dfs.printf("%d   ", csp->duses);
		dfs.printf("%d   ", (int)csp->voidf);
		dfs.printf("%d   ", csp->reg);
		if (csp->exp && csp->exp->sym)
			dfs.printf("%s   ", (char *)csp->exp->sym->name->c_str());
		if (csp->exp && csp->exp->sp)
			dfs.printf("%s   ", (char *)((std::string *)(csp->exp->sp))->c_str());
		dfs.printf("\n");
	}
	dfs.printf("</CSETable>\n");
}
 
 

Go to most recent revision | 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.