#include "c.h"
//#define DOPRINTF
#ifndef DOPRINTF
#define PrintRegister(a)
#define PrintTemporary(a)
#endif
extern void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
static int maxdepth,hasDangerousOp;
typedef struct tagSymbolList SymbolList;

struct tagSymbolList {
	struct tagSymbolList *Next;
	Symbol sym;
};

SymbolList *SymbolsHead;

typedef struct tagAssignmentSymbolList {
	struct tagAssignmentSymbolList *Next;
	SymbolList *lhs;
	SymbolList *rhs;
	Node node;
} AssignmentDescriptor;

AssignmentDescriptor *AssignmentsList;

typedef struct tagLexicalBlock {
	struct tagLexicalBlock *Next;
	struct tagLexicalBlock *Down;
	struct tagLexicalBlock *Up;
	Code cp;
} LexicalBlock;

Code CurrentLexicalBlock;
typedef struct tagbasicCodeBlock {
	struct tagbasicCodeBlock *Next;
	int Label;
	int NrOfSuccessors;
	int *Successors;
	int NrOfPredecessors;
	int *Predecessors;
	AssignmentDescriptor *DefUse;
	SymbolList *Symbols;
	Coordinate src;
	LexicalBlock *lexicalblock;
	unsigned EndsWithJump:1;
	unsigned hasCalls:1;
	unsigned hasBlockMove:1;
	unsigned hasMul:1;
	unsigned hasDivision;
} basicCodeBlock;

Symbol equated (Symbol);


SymbolList *AssignedSymbols;
#ifdef DOPRINTF
#define Printf2(a,b) printf(a,b)
#define Printf3(a,b,c) printf(a,b,c)
#else
#define Printf2(a,b)
#define Printf3(a,b,c)
#endif

SymbolList *AddSymbolToSymbolList(SymbolList **sl,Symbol s)
{
	SymbolList *newsl;

//	if (s->generated || s->temporary) return *sl;
	if (s) {
		NEW0(newsl,FUNC);
		newsl->Next = *sl;
		*sl = newsl;
		newsl->sym = s;
		return newsl;
	}
	return *sl;
}

AssignmentDescriptor *AddAssignment(SymbolList *l,SymbolList *sl,Node n)
{
	AssignmentDescriptor *ad;

	NEW0(ad,FUNC);
	ad->lhs = l;
	ad->rhs = sl;
	ad->node = n;
	ad->Next = AssignmentsList;
	AssignmentsList = ad;
	return(ad);
}
static void treedump(Node p,int level)
{
	printf( "%s(", IR->x._opname[p->op]);
	if (IR->x._arity[p->op] == 0 && p->syms[0])
		printf( "%s", p->syms[0]->name);
	else if (IR->x._arity[p->op] == 1)
		treedump(p->kids[0],level+1);
	else if (IR->x._arity[p->op] == 2) {
		treedump(p->kids[0],level+1);
		printf( ", ");
		treedump(p->kids[1],level+1);
	}
	printf( ")");
}

extern void GenBlockDebugInfo(Code cp);
static void     fixup1(Node p);

basicCodeBlock StartBlock;
static int unsafe;
#define MAXSUCCESORS 500
static int successorsTable[MAXSUCCESORS];
static int succIdx,currentLabel,endswithjump,hasCalls;
static basicCodeBlock *RootBlock,*lastBlock;
static Node BlockNodes;
#define MAXALIAS 200
#define MAXJUMPNODES 4096
typedef struct tagAlias {
	unsigned short label;
	unsigned short alias;
	Node plabel;
} alias,*Alias;
static Node JumpNodeTable[MAXJUMPNODES];
static int JumpNodeIndex;

static Alias AliasTable;
static int AliasTableSize;
static int aliasIndex;
static void ClearAliasTable(void)
{
	if (AliasTableSize == 0)
		return;
	memset(AliasTable,0,AliasTableSize*sizeof(alias));
}

static void AddLabelAlias(int label,Node plabel)
{
	Alias a;

	if (AliasTable == NULL) {
		AliasTable = (Alias)malloc(MAXALIAS * sizeof(alias));
		memset(AliasTable,0,MAXALIAS *sizeof(alias));
		AliasTableSize = MAXALIAS;
	}
	if (aliasIndex >= AliasTableSize) {
		AliasTable = (Alias)realloc(AliasTable,(AliasTableSize+MAXALIAS)*sizeof(alias));
		memset(AliasTable+AliasTableSize,0,MAXALIAS*sizeof(alias));
		AliasTableSize += MAXALIAS;
	}
	a = &AliasTable[aliasIndex];
	aliasIndex++;
	a->alias = plabel->syms[0]->u.l.label;
	a->label = label;
	a->plabel = plabel;
}

static void AddJumpNode(Node p)
{
	if (JumpNodeIndex >= MAXJUMPNODES) {
		printf("Overflow in jump node table");
		return;
	}
	JumpNodeTable[JumpNodeIndex] = p;
	JumpNodeIndex++;
}
#ifdef DOPRINTF
void PrintRegister(Node p)
{
	if (p->syms[RX] && p->x.registered) {
		Printf2("%s ",p->syms[RX]->x.name);
	}
}
static void PrintTemporary(Symbol s)
{
	if (s->computed) {				
		if (s->scope == GLOBAL)
			Printf2("global ",0);
		else if( s->sclass == STATIC)
			Printf2("static ",0);
		else if (s->sclass == EXTERN)
			Printf2("extern ",0);
		else {
			Printf2("local ",0);
		}
		Printf2("%s ",s->x.name);
		if (s->x.ArraySymbol)
			Printf2("%s ",s->x.ArraySymbol->name);
	}
	else
		Printf2("%s ",s->name);
}
#endif
static void FinishBlock(void)
{
	basicCodeBlock *rvp;

	NEW0(rvp,FUNC);
	if (RootBlock == NULL) {
		RootBlock = rvp;
	}
	else {
		lastBlock->Next = rvp;
	}
	lastBlock = rvp;
	rvp->NrOfSuccessors = succIdx;
	if (succIdx) {
		rvp->Successors = allocate(succIdx * sizeof(int),FUNC);
		memcpy(rvp->Successors,successorsTable,succIdx*sizeof(int));
	}
	rvp->src = src;
	rvp->Label = currentLabel;
	rvp->EndsWithJump = endswithjump;
	rvp->hasCalls = hasCalls;
	rvp->DefUse = AssignmentsList;
	AssignmentsList = NULL;
	rvp->Symbols = SymbolsHead;
	SymbolsHead = NULL;
	hasCalls = endswithjump = succIdx = 0;
}


static int FindSymbols(Node p,int level)
{
	Node kid;
	int skip,op,result=0;
	Symbol s;
	Symbol n;
	AssignmentDescriptor *ad;

	if (p == NULL) return 0;
	if (p->x.analyzed) return 0;
	p->x.analyzed = 1;
	if (level > maxdepth) maxdepth = level;
	op = generic(p->op);
	if (op != LABEL && BlockNodes == NULL)
		BlockNodes = p;
	switch (op) {
	case LABEL:
		if (p->syms[0]->ref == 0.0) {
			Printf2("Label _$%s not used",p->syms[0]->name);
			p->syms[0]->u.l.label = 0;
			return 1;
		}
		if (p->syms[0]->u.l.label == cfunc->u.f.label)
			Printf2("_functionExit:",0);
		else Printf2("_$%d:",p->syms[0]->u.l.label);
		if (BlockNodes == NULL) {
			Printf2("Label _$%d empty",currentLabel);
			AddLabelAlias(currentLabel,p);
			result = 1;
		}
		else FinishBlock();
		currentLabel = p->syms[0]->u.l.label;
		BlockNodes = NULL;
		break;
	case JUMP:
		Printf2("%s ","goto");
		if (p->kids[0] && p->kids[0]->syms[0]) {
			n = equated(p->kids[0]->syms[0]);
			if (n->u.l.label == cfunc->u.f.label)
				Printf2(" _functionExit",0);
			else Printf2(" _$%d ",n->u.l.label);
			if (succIdx >= MAXSUCCESORS) {
				printf("Overflow in number of successors\n");
			}
			else {
				successorsTable[succIdx] = n->u.l.label;
				succIdx++;
			}
			AddJumpNode(p);
		}
		endswithjump = 1;
		break;
	case EQ:
	case LE:
	case NE:
	case LT:
	case GE:
	case GT:
		Printf2("if (",0);
		FindSymbols(p->kids[0],level+1);
		FindSymbols(p->kids[1],level+1);
		Printf2("%s ) goto ",opname(p->op));
		if (p->syms[0]) {
			n = equated(p->syms[0]);
			Printf2("_$%d ",n->u.l.label);
			if (succIdx >= MAXSUCCESORS) {
				printf("Overflow in number of successors\n");
			}
			else {
				successorsTable[succIdx] = n->u.l.label;
				succIdx++;
			}
		}
		AddJumpNode(p);
		p->x.unsafe = unsafe;
		return result;
	case ASGN:
		if (p->op == ASGNB) {
			unsafe = 1;
			hasDangerousOp = 1;
			p->x.unsafe = 1;
		}
		kid = p->kids[0];
		skip = 0;
		if (generic(kid->op) == AND) {
			kid = p->kids[1];
			skip = 1;
		}
		s = kid->syms[0];
		if (isaddrop(kid->op)) {
			SymbolsHead = AddSymbolToSymbolList(&SymbolsHead,s);
			ad = AddAssignment(SymbolsHead,NULL,p);
			SymbolsHead = NULL;
			PrintTemporary(s);

			Printf2("= ",0);
			FindSymbols(kid->kids[0],level+2);
			if (!skip)
				FindSymbols(p->kids[1],level+1);
			ad->rhs = SymbolsHead;
			SymbolsHead = NULL;
			return 0;
		}
		else if (generic(kid->op) == INDIR) {
			FindSymbols(p->kids[0],level+1);
			SymbolsHead = AddSymbolToSymbolList(&SymbolsHead,s);
			ad = AddAssignment(SymbolsHead,NULL,p);
			SymbolsHead = NULL;

			Printf2("= ",0);
			FindSymbols(p->kids[1],level+1);
			Printf2("Assignment through pointer ",0);
			ad->rhs = SymbolsHead;
			SymbolsHead = NULL;
			return 0;
		}
		else if (kid->op == ADDP ||
			kid->op == SUB) {
			Printf2("Array/struct ",0);
			{
				SymbolsHead = AddSymbolToSymbolList(&SymbolsHead,s);
				ad = AddAssignment(SymbolsHead,NULL,p);
				SymbolsHead = NULL;
				FindSymbols(p->kids[0],level+1);
				Printf2("= ",0);
				FindSymbols(p->kids[1],level+1);
			}
			ad->rhs = SymbolsHead;
			SymbolsHead = NULL;
			return 0;
		}
		SymbolsHead = AddSymbolToSymbolList(&SymbolsHead,s);
		ad = AddAssignment(SymbolsHead,NULL,p);
		SymbolsHead = NULL;
		FindSymbols(p->kids[0],level+1);
		FindSymbols(p->kids[1],level+1);
		ad->rhs = SymbolsHead;
		SymbolsHead = NULL;
		break;
	case AND:
		return 0;
	case CALL:
		if (p->x.intrinsic == 0) {
			hasCalls = 1;
			unsafe = 1;
			p->x.unsafe = 1;
		}
		if (p->kids[0]->syms[0]) {
			Printf2("%s() ",p->kids[0]->syms[0]->name);
			return 0;
		}
		else {
			FindSymbols(p->kids[0],level+1);
			FindSymbols(p->kids[1],level+1);
		}
		break;
	case CNST:
		if (p->syms[0]->addressed == 0) {
			if (p->syms[0]->type == inttype) {
				Printf2("%s ",p->syms[0]->name);
			}
			else Printf2("constant %s ",p->syms[0]->name);
			return 0;
		}
		else 
			Printf2("static data %s\n",p->syms[0]->name);
		break;
	case ARG:
		if (p->x.intrinsicArg == 0) {
			unsafe = 1;
			p->x.unsafe = 1;
		}
		FindSymbols(p->kids[0],level+1);
		FindSymbols(p->kids[1],level+1);
		Printf2("PUSH",0);
		PrintRegister(p);
		if (p->op == ARGB) {
			hasDangerousOp = 1;
			unsafe = 1;
			p->x.unsafe = 1;
		}
		return 0;
	case LOAD:
	case INDIR:
		Printf2("%s ",opname(p->op));
		PrintRegister(p);
		FindSymbols(p->kids[0],level+1);
		FindSymbols(p->kids[1],level+1);
		p->x.unsafe = unsafe;
		return 0;
    case ADDRG:
    case ADDRF:
    case ADDRL:
#ifdef DOPRINTF
		if (p->syms[0]->isconstant) {
			if (p->syms[0]->x.ArraySymbol)
				Printf2("Table %s ",p->syms[0]->x.ArraySymbol->name);
			else
				Printf2("static data _$%s ",p->syms[0]->name);
		}
		else if (p->syms[0]->name[0] >= '0' &&
			p->syms[0]->name[0] <= '9') {
			PrintTemporary(p->syms[0]);
		}
		else
			Printf2("%s ",p->syms[0]->name);
		PrintRegister(p);
#endif
		SymbolsHead = AddSymbolToSymbolList(&SymbolsHead,p->syms[0]);
		p->x.unsafe = unsafe;
		return 0;
	default:
		if (op == DIV || op == RSH || op == LSH | op == MOD) {
			if (p->op != DIVD) {
				unsafe = 1;
				if (p->op == DIVI || p->op == MODI)
					hasDangerousOp = 1;
				p->x.unsafe = 1;
				p->kids[0]->x.unsafe = 1;
				p->kids[1]->x.unsafe = 1;
			}
		}
		FindSymbols(p->kids[0],level+1);
		FindSymbols(p->kids[1],level+1);

	}
	Printf2("%s ",opname(p->op));
	PrintRegister(p);
	p->x.unsafe = unsafe;
	return result;
}
static int SymbolSortFn(const void *f1, const void *f2)
{
	Symbol s1, s2;
	s1 = *(Symbol *) f1;
	s2 = *(Symbol *) f2;
	if (s1->ref > s2->ref)
		return (-1);
	else if (s1->ref < s2->ref)
		return (1);
	else
		return (0);
}

static Symbol RegisterVars[5];
static int maxRegisterVars;
void SetupRegisterVariables(void)
{
	int nrOfSym,i,k,l;
	Symbol *FunctionLocals,n;

	SetRegistersMasks();
	maxRegisterVars = 0;
	if (vmask[0] == 0)
		return;
	nrOfSym = 0;
	if (cfunc->u.f.callee) {
		Printf2("Function arguments:\n",0);
		i = 0;
		while (cfunc->u.f.callee[i]) {
			n = cfunc->u.f.callee[i];
			Printf3("[%2d] %s ",i,n->name);
			if (n->addressed) Printf2("addressed ",0);
//			printf("%s Usage %f\n",n->name,n->ref);
			i++;
			nrOfSym++;
		}
	}
	FunctionLocals = FunctionInfo.cp->u.block.locals;
	if (FunctionLocals) {
		Printf2("Local variables:\n",0);
		i = 0;
		while (FunctionLocals[i]) {
			n = FunctionLocals[i];
			Printf3("[%2d] %s ",i,n->name);
			if (n->addressed) Printf2("addressed ",0);
//			printf("%s Usage %f\n",n->name,n->ref);
			i++;
			nrOfSym++;
		}

	}
	if (nrOfSym) {
//		printf("Function %s:\n",cfunc->name);
		FunctionLocals = (Symbol *)allocate((1+nrOfSym)*sizeof(Symbol),FUNC);
		memset(FunctionLocals,0,(1+nrOfSym)*sizeof(Symbol));
		k = 0;
#if 1
		if (cfunc->u.f.callee) {
			i = 0;
			while (cfunc->u.f.callee[i]) {
				n = cfunc->u.f.callee[i];
				if (n->addressed == 0 && 
					n->type->size == 4 &&
					isscalar(n->type) && 
					unqual(n->type)->op > DOUBLE) {
					FunctionLocals[k++] = n;
				}			
				i++;
			}
		}
#endif
		if (FunctionInfo.cp->u.block.locals) {
			i = 0;
			while (FunctionInfo.cp->u.block.locals[i]) {
				n = FunctionInfo.cp->u.block.locals[i];
				if (n->addressed == 0 && 
					isscalar(n->type) &&
					n->type->size == 4 &&
					unqual(n->type)->op > DOUBLE) {
					FunctionLocals[k++] = n;
				}
				i++;
			}
		}
		if (k) {
			if (k > 1)
				qsort(FunctionLocals,k,sizeof(Symbol),SymbolSortFn);
			Printf2("Best three symbols to register: ",0);
			for (i=0; i<3 && i < k; i++) {
				n = FunctionLocals[i];
				if (n->ref < 2.0) break;
				l = n->sclass;
				n->sclass = REGISTER;
				Printf2("%s ",FunctionLocals[i]->name);
				if (!askregvar(n,rmap[ttob(n->type)])) {
					n->sclass = l;
					break;
				}
				else {
					FunctionInfo.hasRegisterVars = 1;
					RegisterVars[maxRegisterVars++] = n;
//					printf("%s registered\n",n->name);
				}
			}
		}
		Printf2("\n",0);
	}
}

void SaturateUnsafe(Node p)
{
	if (p == NULL) return;
	p->x.unsafe = 1;
	p->x.dangerousChildren = 1;
	SaturateUnsafe(p->kids[0]);
	SaturateUnsafe(p->kids[1]);
}

void ReplaceReg(Node p,Symbol oldreg,Symbol newreg)
{
	if (p == NULL) return;
	if (p->syms[2] && p->syms[2]->x.name == oldreg->x.name)
		p->syms[2] = newreg;
	ReplaceReg(p->kids[0],oldreg,newreg);
	ReplaceReg(p->kids[1],oldreg,newreg);
}

typedef struct {
	Node conditional;
	Node Jump;
	Code cpJump;
}jmpInfo;

#define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b))

int BuildBasicBlocks(void)
{
	int i,l,showline;
	Code cp,previous;
	Node p,last,watchout,forest;
	Symbol n;
	jmpInfo jInfo;
	struct node sentinel;
	int result = 1;

#ifdef DOPRINTF
	char tmpbuf[256];
	int k=0;
	sprintf(tmpbuf,"\nFunction %s",cfunc->name);
	printf("%s ",tmpbuf);
	for (i=0; i<(signed)(75-strlen(tmpbuf));i++)
		printf("-");
	printf("\n");
#endif
	endswithjump = hasCalls = currentLabel = succIdx = 0;
	i = 1;
	showline = 0;
	memset(&StartBlock,0,sizeof(basicCodeBlock));
	memset(&jInfo,0,sizeof(jmpInfo));
	ClearAliasTable();
	BlockNodes = NULL;
	aliasIndex = 0;
	JumpNodeIndex = 0;
	memset(JumpNodeTable,0,sizeof(JumpNodeTable));
	previous = NULL;
	watchout = last = NULL;
	AssignmentsList = NULL;
	SymbolsHead = NULL;
	unsafe = 0;
    for (cp = codehead.next; cp; cp = cp->next) {
        switch (cp->kind) {
		case Defpoint:
            src = cp->u.point.src;
			showline = 1;
			break;
        case Gen:
        case Jump:													 
			watchout = NULL;
        case Label:
			if (cp->kind == Label)
				unsafe = 0;
			if (showline) {
				Printf2("\nLine %d\n",src.y);
				showline = 0;
			}
			forest = cp->u.forest;
			relink(&sentinel, &sentinel);
			for (p = forest; p; p = p->link)
				linearize(p, &sentinel);
			forest = sentinel.x.next;
			assert(forest);
			sentinel.x.next->x.prev = NULL;
			sentinel.x.prev->x.next = NULL;
			for (p=forest;p;p=p->x.next) {
				if (cp->kind == Jump && last && p->x.next == NULL) {
					int op = generic(last->op);
					if (op == EQ || op == LE || op == NE ||
						 op == LT || op == GE || op == GT) {
//						printf("--- %s --- ",p->kids[0]->syms[0]->name);
//						printf("%s\n",last->syms[0]->name);
						jInfo.conditional = last;
						jInfo.cpJump = cp;
						jInfo.Jump = p;
						watchout = last;
					}
				}
				else if (cp->kind == Label && watchout) {
					int op;
					if (p->syms[0]->u.l.label == watchout->syms[0]->u.l.label) {
//						printf("foundit: %d: jump=%d\n",p->syms[0]->u.l.label,
//							last->kids[0]->syms[0]->u.l.label);
						assert(jInfo.cpJump);
						assert(jInfo.cpJump->prev);
						assert(JumpNodeTable[JumpNodeIndex-1] == jInfo.Jump);
						assert(JumpNodeTable[JumpNodeIndex-2] == jInfo.conditional);
						assert(jInfo.cpJump->u.forest->x.next == NULL);
						/* change the sense of the jcc */
						switch (jInfo.conditional->op) {
						case EQI:
							op = NEI;
							break;
						case LEI:
							op = GTI;
							break;
						case LEU:
							op = GTU;
							break;
						case NEI:
							op = EQI;
							break;
						case LTI:
							op = GEI;
							break;
						case LTU:
							op = GEU;
							break;
						case GEI:
							op = LTI;
							break;
						case GEU:
							op = LTU;
							break;
						case GTI:
							op = LEI;
							break;
						case GTU:
							op = LEU;
							break;
						default:
							goto bailout;
						}
						jInfo.conditional->op = op;
						jInfo.conditional->syms[0] = jInfo.Jump->kids[0]->syms[0];
						/* erase the jump */
						jInfo.cpJump->prev->next = jInfo.cpJump->next;
						jInfo.cpJump->next->prev = jInfo.cpJump->prev;
						/* fixup the jump table */
						JumpNodeTable[--JumpNodeIndex] = NULL;
						JumpNodeTable[--JumpNodeIndex] = NULL;
						JumpNodeTable[JumpNodeIndex++] = jInfo.conditional;
						succIdx -= 2; // erase the jump from the successors table
						successorsTable[succIdx] = successorsTable[succIdx+1];
						succIdx++;
						successorsTable[succIdx] = 0;
						endswithjump = 0;
					}
bailout:
					memset(&jInfo,0,sizeof(jmpInfo));
				}
				else watchout = NULL;
#ifdef DOPRINTF
				treedump(p,0);
				printf("\n[%3d] ",k++);
#endif
				maxdepth = 0;
				hasDangerousOp = 0;
				FindSymbols(p,1);
				if (hasDangerousOp) {
					SaturateUnsafe(p);
					unsafe = 1;
				}
#if 0
//				printf("maxdepth=%d\n",maxdepth);
				if (0 && maxdepth > 7 && hasDangerousOp) {
					warning(
"expression too complicated for the optimizer. (depth=%d)\nno optimizations for function %s\n",
					maxdepth,cfunc->name);
					unsafe = 1;
					for (i=0;i<maxRegisterVars;i++) {
						n = RegisterVars[i];
						n->x.name = stringf("%d",n->x.offset);
						n->x.regnode->vbl = NULL;
						n->x.regnode = NULL;
						n->sclass= AUTO;
					}
					result = 0;
					maxRegisterVars = 0;
					goto exitit;
				}
#endif
				p->x.unsafe = unsafe;
//				if (p->op == ASGNI &&
//					p->kids[1]->op == CNSTI) {
//					printf("Int assignment\n");
//				}

				Printf2("\n",0);
				last = p;
			}
			break;
		case Switch:
			l = cp->u.swtch.size;
			if (l + succIdx >= MAXSUCCESORS) {
				printf("Overflow in switch\n");
				l = MAXSUCCESORS - l;
			}
			Printf2("switch size %d \n",cp->u.swtch.size);
			for (i=0; i<l;i++) {
				cp->u.swtch.labels[i]->ref += 1.0;
				n = equated(cp->u.swtch.labels[i]);
				successorsTable[succIdx] = n->u.l.label;
				succIdx++;
			}
			break;

		}
		previous = cp;
	}
	FinishBlock();
	return result;
}
//enum { EAX=0, ECX=1, EDX=2, EBX=3, ESI=6, EDI=7 };
extern Symbol intreg[];
void AnalyzeSecondPass(void)
{
	int i,k,l,ialias,op,lastpoint,z,swapRegs;
	Code cp;
	Node p,last;
	Symbol lab,oldreg[2],newreg[2];
#ifdef DOPRINTF
	basicCodeBlock *rvpB=&StartBlock;
	AssignmentDescriptor *asl;
	SymbolList *rhs;
#endif
	i = 0;
	while (i < aliasIndex) {
		ialias = AliasTable[i].alias;
		lastpoint = i;
		p = AliasTable[i].plabel;
		if (p->x.next || p->x.prev) {
			printf("inner label\n");
		}
		i++;
		while (ialias == AliasTable[i].label) {
			ialias = AliasTable[i].alias;
			i++;
		}
		lab = findlabel(ialias);
		for (k=0; k<JumpNodeIndex;k++) {
			p = JumpNodeTable[k];
			if (p == NULL)
				continue;
			op = generic(p->op);
			if (op == JUMP)
				l = p->kids[0]->syms[0]->u.l.label;
			else
				l = p->syms[0]->u.l.label;
			if (l == 0)
				printf("l == 0?????");
			for (z=lastpoint; z<i;z++) {
				if (l == AliasTable[z].label) {
					if (op == JUMP) {
						p->kids[0]->syms[0]->u.l.equatedto = lab;
						p->kids[0]->syms[0] = lab;
					}
					else {
						p->syms[0]->u.l.equatedto = lab;
						p->syms[0] = lab;
					}
					JumpNodeTable[k] = NULL;
					break;
				}
			}
		}
	}
	for (i=0; i<JumpNodeIndex;i++) {
		if (JumpNodeTable[i]) {
			char *n;
			p = JumpNodeTable[i];
			op = generic(p->op);
			if (op == JUMP) {
				l = p->kids[0]->syms[0]->u.l.label;
				n = p->kids[0]->syms[0]->name;
			}
			else {
				l = p->syms[0]->u.l.label;
				n = p->syms[0]->name;
			}
			if (l == 0) {
				printf("Label _$%s not changed!!!!\n",n);
			}
		}
	}
	swapRegs = 0;
	if (FunctionInfo.leafFunction && FunctionInfo.hasBlockMove == 0) {
		if ((usedmask[0] & (1 << 1)) == 0 &&
			(usedmask[0] & (1 << 7))) {
			/* swap edi with ecx */
			oldreg[0] = intreg[7];
			newreg[0] = intreg[1];
			swapRegs = 1;
			usedmask[0] |= (1 << 1);
			usedmask[0] &= ~(1 << 7);
		}
		/* swap EDI by EAX */
		else if ((usedmask[0] & 1 ) == 0 &&
			(usedmask[0] & (1 << 7))) {
			oldreg[0] = intreg[7];
			newreg[0] = intreg[0];
			swapRegs = 1;
			usedmask[0] |= 1;
			usedmask[0] &= ~(1 << 7);
		}
		if ((usedmask[0] & (1 << 1)) == 0 &&
			(usedmask[0] & (1 << 6))) {
			/* swap esi with ecx */
			oldreg[swapRegs] = intreg[6];
			newreg[swapRegs] = intreg[1];
			swapRegs++;
			usedmask[0] |= (1 << 1);
			usedmask[0] &= ~(1 << 6);
		}
		/* swap ESI by EAX */
		else if ((usedmask[0] & 1 ) == 0 &&
			(usedmask[0] & (1 << 6))) {
			oldreg[swapRegs] = intreg[6];
			newreg[swapRegs] = intreg[0];
			swapRegs++;
			usedmask[0] |= 1;
			usedmask[0] &= ~(1 << 6);
		}
	}
	/*
	Redo the list of nodes to erase the unnecessary labels
	*/
    for (cp = codehead.next; cp; cp = cp->next) {
		// This time follow only Jump/Gen/Label Code nodes
        switch (cp->kind) {
		case Jump:
		case Gen:
		case Label:
			// Follow all the nodes of this forest
			last = NULL;
			for (p=cp->u.forest;p;p=p->x.next) {
				if (generic(p->op) == LABEL) {	// If it is a LABEL node
					// If it has been erased by the loops above
					if (p->syms[0]->u.l.equatedto || p->syms[0]->u.l.label == 0) {
						Printf2("Erasing label %s\n",p->syms[0]->name);
						//If is a middle node unlink it
						if (last) {
							last->x.next = p->x.next;
							if (p->x.next)
								p->x.next->x.prev = last;
						}
						else {
							// This is the first node in the forest
							if (p->x.next) // If there are more nodes
								cp->u.forest = p->x.next; // unlink
							else {
								// No more nodes. Delete the forest
								cp->prev->next = cp->next;
								cp->next->prev = cp->prev;
							}
						}
					}
//					if (p->syms[0]->u.l.equatedto)
//						p->syms[0] = equated(p->syms[0]);
				}
				// Keep the pointer to the last node
				for (i=0; i<swapRegs;i++)
					ReplaceReg(p,oldreg[i],newreg[i]);
				last = p;
			}
			break;
#ifdef DOPRINTF
        case Blockbeg:{
                Symbol         *p = cp->u.block.locals;
				if (*p == NULL) break;
				Printf2("Scope %d:\n",cp->u.block.x.offset);
                for (; *p; p++) {
					Printf2("%s",(*p)->name);
					if (p[1]) Printf2(",",0);
				}
				Printf2("\n",0);
            }
            break;
#endif
		}
	}
#ifdef DOPRINTF
	rvpB = RootBlock;
	printf("\nControl flow analysis\n");
	while (rvpB) {
		printf("Block %d line %d:",rvpB->Label,rvpB->src.y);
		if (rvpB->hasCalls) printf("Has calls ");
		else printf("no calls ");
		if (rvpB->NrOfSuccessors) {
			printf(" %d successors: ",rvpB->NrOfSuccessors);
			for (i=0; i<rvpB->NrOfSuccessors;i++) {
				printf(" %d ",rvpB->Successors[i]);
			}
		}
		if (rvpB->EndsWithJump)
			printf(" end: JUMP");
		printf("\n");
		if (rvpB->NrOfPredecessors) {
			printf("Predecessors %d:",rvpB->NrOfPredecessors);
			for (i=0; i<rvpB->NrOfPredecessors;i++) {
				printf(" %d",rvpB->Predecessors[i]);
			}
			printf("\n");
		}
		else if (rvpB->Label && rvpB->Next) {
//			printf("Block %d has no predecessors?\n",rvpB->Label);
		}
		asl = rvpB->DefUse;
		while (asl) {
			if (asl->lhs) {
				printf(" %s =",asl->lhs->sym->name);
			}
			else
				printf("Uses: ");
			rhs = asl->rhs;
			while (rhs) {
				if (rhs->sym->scope == CONSTANTS)
					printf("constant ");
				printf(" %s",rhs->sym->name);
				rhs = rhs->Next;
			}
			Printf2("\n",0);
			asl = asl->Next;
		}
		if (rvpB->DefUse)
			printf("\n");
		rvpB = rvpB->Next;
	}
	if (aliasIndex) {
		printf("Label alias table\n");
		for (i=0; i<aliasIndex;i++) {
			printf("%d --> %d\n",AliasTable[i].label,AliasTable[i].alias);
		}
	}
#endif
	lastBlock = RootBlock = NULL;
}

