|
|
Power 6/32 Unix version 1.2b
/*
* C object code improver-- third part
*/
#include "c2.h"
#include <stdio.h>
#include <ctype.h>
#define NUSE 6
struct node *uses[NUSE]; /* for backwards flow analysis */
char *lastrand; /* last operand of instruction */
char *findcon();
ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */
register int log;
if (n==0 || n&(n-1)) return(-1); log=0;
for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);}
}
equop(p1, p2)
register struct node *p1, *p2;
{
register char *cp1, *cp2;
if (p1->op != p2->op || p1->subop != p2->subop)
return(0);
if (p1->op>0 && p1->op<MOV)
return(0);
if (p1->op==MOVA && p1->labno!=p2->labno) return(0);
cp1 = p1->code;
cp2 = p2->code;
if (cp1==0 && cp2==0)
return(1);
if (cp1==0 || cp2==0)
return(0);
while (*cp1 == *cp2++)
if (*cp1++ == 0)
return(1);
return(0);
}
delnode(p) register struct node *p; {
p->back->forw = p->forw;
p->forw->back = p->back;
}
decref(p)
register struct node *p;
{
if (p && --p->refc <= 0) {
nrlab++; nchange++;
delnode(p);
}
}
struct node *
nonlab(ap)
struct node *ap;
{
register struct node *p;
p = ap;
while (p && p->op==LABEL)
p = p->forw;
return(p);
}
clearuse() {
register struct node **i;
for (i=uses+NUSE; i>uses;) *--i=0;
}
clearreg() {
register char **i;
for (i=regs+NREG; i>regs;){ **--i=0; **i=0; }
conloc[0] = 0; ccloc[0] = 0;
}
savereg(ai, s, type)
register char *s;
{
register char *p, *sp;
sp = p = regs[ai];
/* if any indexing, must be parameter or local */
/* indirection (as in "*-4(fp)") is ok, however */
*p++ = type;
while (*p++ = *s)
if (*s=='[' || *s++=='(' && *s!='f') {*sp = 0; return;}
}
dest(s,type, ccflg)
register char *s;
{
register int i;
if ((i = isreg(s)) >= 0) {
*(short *)(regs[i]) = 0; /* if register destination, that reg is a goner */
}
for (i=NREG; --i>=0;)
if (regs[i][1]=='*' && equstr(s, regs[i]+2))
*(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */
while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */
*(short *)(regs[i]) = 0;
if (!natural(s)) {/* wild store, everything except constants vanishes */
for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0;
conloc[0] = 0; ccloc[0] = 0;
} else if(ccflg)setcc(s,type); /* natural destinations set condition codes */
}
splitrand(p) struct node *p; {
/* separate operands at commas, set up 'regs' and 'lastrand' */
register char *p1, *p2; register char **preg;
preg=regs+RT1;
if (p1=p->code) while (*p1) {
lastrand=p2= *preg++;
while (*p1) if (','==(*p2++= *p1++)) {--p2; break;}
*p2=0;
}
while (preg<(regs+RT1+5)) *(*preg++)=0;
}
compat(have, want) {
register int hsrc, hdst;
if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */
hsrc=have&0xF; if (0==(hdst=((have>>4)&0xF)) || hdst>=OP2) hdst=hsrc;
if (want>=QUAD) return(hdst==want && hsrc==want);
return(hsrc==want && hdst>=want && hdst<QUAD);
}
equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));}
findrand(as, type)
char *as;
{
register char **i;
for (i = regs+NREG; --i>=regs;) {
if (**i && equstr(*i+1, as) && compat(**i,type))
return(i-regs);
}
return(-1);
}
isreg(s)
register char *s;
{
if (*s++!='r' || !isdigit(*s++)) return(-1);
if (*s==0) return(*--s-'0');
if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0');
return(-1);
}
/*
check()
{
register struct node *p, *lp;
lp = &first;
for (p=first.forw; p!=0; p = p->forw) {
if (p->back != lp)
abort(-1);
lp = p;
}
}
*/
newcode(p) struct node *p; {
register char *p1,*p2,**preg;
preg=regs+RT1; p2=line;
while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';}
*--p2=0;
p->code=copy(line);
}
repladdr(p)
struct node *p;
{
register r;
register char *p1;
register char **preg;
register int nrepl;
preg=regs+RT1; nrepl=0;
while (lastrand!=(p1= *preg++))
if (0<=(r=findrand(p1,p->subop))) {
*p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0;
nchange++; nrepl++; nsaddr++;
}
if (nrepl) newcode(p);
}
/* conditional branches which are never/always taken */
reduncbr(p)
register struct node *p;
{
register struct node *p1;
register char *ap1, *ap2;
p1 = p->back;
if (p1->op==CMP) {
splitrand(p1);
ap1 = findcon(regs[RT1], p1->subop);
ap2 = findcon(regs[RT2], p1->subop);
} else {
if(!ccloc[0])
return;
ap1 = findcon(ccloc+1, ccloc[0]);
ap2 = "$0";
}
switch (compare(p->subop, ap1, ap2)) {
case 0: /* branch never taken */
delnode(p);
nredunj++;
nchange++;
decref(p->ref);
if(p->forw->op!=CBR && (p1->op==TST || p1->op==CMP)) {
delnode(p1);
nrtst++;
}
break;
case 1: /* branch always taken */
p->op = JBR;
p->subop = 0;
p->pop = 0;
nchange++;
}
}
/* a jump to a redundant compare (start of a 'for') */
redunbr(p)
register struct node *p;
{
register struct node *p1;
register char *ap1, *ap2;
if ((p1 = p->ref) == 0)
return;
p1 = nonlab(p1);
if (p1->op==TST || p1->op==CMP)
splitrand(p1);
else
return;
if (p1->forw->op==CBR) {
ap1 = findcon(regs[RT1], p1->subop);
if (p1->op==TST)
ap2 = "$0";
else
ap2 = findcon(regs[RT2], p1->subop);
p1 = p1->forw;
if (compare(p1->subop, ap1, ap2) > 0) {
nredunj++;
nchange++;
decref(p->ref);
p->ref = p1->ref;
p->labno = p1->labno;
#ifdef COPYCODE
if (p->labno == 0)
p->code = p1->code;
if (p->ref)
#endif
p->ref->refc++;
}
} else if (p1->op==TST && equstr(regs[RT1],ccloc+1) &&
equtype(ccloc[0],p1->subop)) {
p1=insertl(p1->forw); decref(p->ref); p->ref=p1;
nrtst++; nchange++;
}
}
char *
findcon(p, type)
register char *p;
{
register r;
if (*p=='$')
return(p);
if ((r = isreg(p)) >= 0 && compat(regs[r][0],type))
return(regs[r]+1);
if (equstr(p, conloc))
return(conval+1);
return(p);
}
/* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */
compare(op, acp1, acp2)
char *acp1, *acp2;
{
register char *cp1, *cp2;
register n1, n2, sign;
cp1 = acp1;
cp2 = acp2;
if (*cp1++ != '$' || *cp2++ != '$')
return(-1);
n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;}
while (isdigit(*cp1)) {n1 *= 10; n1 += *cp1++ - '0';}
n1 *= sign;
n2 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;}
while (isdigit(*cp2)) {n2 *= 10; n2 += *cp2++ - '0';}
n2 *= sign;
if (*cp1=='+')
cp1++;
if (*cp2=='+')
cp2++;
do {
if (*cp1++ != *cp2)
return(-1);
} while (*cp2++);
switch(op) {
case JEQ:
return(n1 == n2);
case JNE:
return(n1 != n2);
case JLE:
return(n1 <= n2);
case JGE:
return(n1 >= n2);
case JLT:
return(n1 < n2);
case JGT:
return(n1 > n2);
case JLO:
return((unsigned)n1 < (unsigned)n2);
case JHI:
return((unsigned)n1 > (unsigned)n2);
case JLOS:
return((unsigned)n1 <= (unsigned)n2);
case JHIS:
return((unsigned)n1 >= (unsigned)n2);
}
return(-1);
}
setcon(cv, cl, type)
register char *cv, *cl;
{
register char *p;
if (*cv != '$')
return;
if (!natural(cl))
return;
p = conloc;
while (*p++ = *cl++);
p = conval;
*p++ = type;
while (*p++ = *cv++);
}
equstr(p1, p2)
register char *p1, *p2;
{
do {
if (*p1++ != *p2)
return(0);
} while (*p2++);
return(1);
}
setcc(ap,type)
char *ap;
{
register char *p, *p1;
p = ap;
if (!natural(p)) {
ccloc[0] = 0;
return;
}
p1 = ccloc;
*p1++ = type;
while (*p1++ = *p++);
}
indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */
while (*p) if (*p++=='[') return(1);
return(0);
}
natural(p)
register char *p;
{/* 1->simple local, parameter, global, or register; 0->otherwise */
if (*p=='*' || *p=='(' || *p=='$')
return(0);
while (*p++);
p--;
if (*--p==']' || *p==')' && *(p-2)!='f')
return(0);
return(1);
}
/*
** Tell if an argument is most likely static.
*/
isstatic(cp)
register char *cp;
{
if (*cp == '_' || *cp == 'L' || (*cp++ == 'v' && *cp == '.'))
return (1);
return (0);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.