static char sccsid
[] = "@(#)c22.c 1.9 (Berkeley/CCI) %G%";
* C object code improver-- third part
for (p
=first
.forw
; p
!=0; p
= p
->forw
) {
printf("%d: %d%d %s\n", r
, r1
&0xF, r1
>>4, regs
[r
]+1);
dest(regs
[RT2
],p
->subop
, p
->op
!=CVT
|| r
<0);
p
->op
= MOV
; p
->subop
= LONG
;
if (r1
>=0) savereg(r1
, regs
[RT1
], p
->subop
);
if ((r
= findrand(regs
[RT1
],p
->subop
)) >= 0) {
if (r
== isreg(regs
[RT2
]))
delnode(p
); redunm
++; nchange
++; break;
while(*p
->code
++ != ',');
dest(regs
[RT2
],p
->subop
, 1);
if ((regs
[ACC
][0]) && equstr(regs
[RT2
],regs
[ACC
]+1))
*(short *)(regs
[ACC
]) = 0;
if (r
== r1
&& p
->forw
->op
!=CBR
) {
delnode(p
); redunm
++; nchange
++;
savereg(r1
, regs
[r
]+1, p
->subop
);
savereg(r
, regs
[RT2
], p
->subop
);
savereg(r1
, regs
[RT1
], p
->subop
);
setcon(regs
[RT1
], regs
[RT2
], p
->subop
);
/* .rx,.wx or .rx,.rx,.wx */
dest(lastrand
,p
->subop
, p
->op
!=ADDA
&& p
->op
!=SUBA
);
if(equstr(p
->code
, regs
[ACC
]+1) && p
->subop
==regs
[ACC
][0]) {
savereg(ACC
, p
->code
, p
->subop
);
dest(p
->code
,p
->subop
, 1);
dest(p
->code
,p
->subop
, 1);
if ((regs
[ACC
][0]) && equstr(p
->code
,regs
[ACC
]+1))
*(short *)(regs
[ACC
]) = 0;
if ((r
= isreg(p
->code
)) < 0)
setcon("$0", p
->code
, p
->subop
);
savereg(r
, "$0", p
->subop
);
if(equstr(p
->code
, regs
[ACC
]+1) && p
->subop
==regs
[ACC
][0]) {
savereg(ACC
, p
->code
, p
->subop
);
if(equstr(p
->code
, regs
[ACC
]+1) && p
->subop
==regs
[ACC
][0]) {
p
->op
= NEGF
; p
->pop
= 0; p
->code
= 0;
lastrand
=regs
[RT1
+1]; /* fool repladdr into doing 1 operand */
if (p
->op
==TST
&& equstr(lastrand
, ccloc
+1)
&& ((0xf&(ccloc
[0]>>4))==p
->subop
|| equtype(ccloc
[0],p
->subop
))) {
delnode(p
); nrtst
++; nchange
++; break;
if (p
->op
==PUSH
&& p
->subop
!=LONG
&&
(isreg(lastrand
)>=0 || *lastrand
=='$')) {
if (p
->op
==TST
|| p
->op
==PUSH
)
setcc(lastrand
,p
->subop
);
/* fool repladdr into doing right number of operands */
if (p
->op
==CALLF
|| p
->op
==CALLS
) clearreg();
dest(regs
[RT3
], p
->subop
, 1);
dest(regs
[RT4
], p
->subop
, 0);
dest(regs
[RT4
],QUAD
, 1); /* fourth operand is a quad */
lastrand
=regs
[RT3
]; /* 2 operands can be optimized */
register struct node
*p
, *p1
, *pt
;
for (p
=first
.forw
; p
!=0; p
= p
->forw
)
for (p
=first
.forw
; p
!=0; p
= p1
) {
if (p
->op
== CBR
&& p1
->op
==JBR
&& p
->ref
&& p1
->ref
&& abs(p
->seq
- p
->ref
->seq
) > abs(p1
->seq
- p1
->ref
->seq
)) {
p
->subop
= revbr
[p
->subop
];
pt
= (struct node
*)p1
->code
; p1
->code
= p
->code
; p
->code
= (char *)pt
;
register struct node
*p
, *p1
, *p2
, *p3
;
for (p
= &first
; (p1
= p
->forw
)!=0; p
= p1
) {
if (p
->op
==INC
&& p
->subop
==LONG
) {
if (p1
->op
==LABEL
&& p1
->refc
==1 && p1
->forw
->op
==CMP
&& p1
->forw
->subop
==LONG
&& (p2
=p1
->forw
->forw
)->op
==CBR
&& p2
->subop
==JLE
&& (p3
=p2
->ref
->back
)->op
==JBR
&& p3
->subop
==0 && p3
->ref
==p1
&& p3
->forw
->op
==LABEL
&& p3
->forw
==p2
->ref
) {
/* change INC LAB: CMP to LAB: INC CMP */
p
->back
->forw
=p1
; p1
->back
=p
->back
;
p
->forw
=p1
->forw
; p1
->forw
->back
=p
;
/* adjust beginning value by 1 */
p2
=alloc(sizeof first
); p2
->op
= DEC
; p2
->subop
= LONG
;
p2
->forw
=p3
; p2
->back
=p3
->back
; p3
->back
->forw
=p2
;
p3
->back
=p2
; p2
->code
=p
->code
; p2
->labno
=0;
if (p1
->op
==CMP
&& p1
->subop
==LONG
&&
(p2
=p1
->forw
)->op
==CBR
&& p2
->forw
->op
!=CBR
) {
splitrand(p1
); if (!equstr(p
->code
,regs
[RT1
])) continue;
if ((p2
->subop
==JLE
|| p2
->subop
==JLT
) &&
if (p2
->subop
==JLE
) p
->op
= AOBLEQ
; else p
->op
= AOBLSS
; p
->subop
= 0;
cp2
=regs
[RT1
]; cp1
=regs
[RT2
]; while (*cp2
++= *cp1
++); /* limit */
cp2
=regs
[RT2
]; cp1
=p
->code
; while (*cp2
++= *cp1
++); /* index */
p
->labno
= p2
->labno
; delnode(p2
); delnode(p1
); naob
++;
ispow2(n
) register long n
; {/* -1 -> no; else -> log to base 2 */
if (n
==0 || n
&(n
-1)) return(-1); log
=0;
for (;;) {n
>>= 1; if (n
==0) return(log
); ++log
; if (n
== -1) return(log
);}
register struct node
*p1
, *p2
;
register char *cp1
, *cp2
;
if (p1
->op
!= p2
->op
|| p1
->subop
!= p2
->subop
)
if (p1
->op
== NIL
&& p1
->subop
== 0 && p1
->pop
!= p2
->pop
)
if (p1
->op
!= NIL
&& ord(p1
->op
) < ord(MOV
))
case EROU
: case JSW
: case TEXT
: case DATA
:
case BSS
: case ALIGN
: case WGEN
: case END
:
if (p1
->op
==MOVA
&& p1
->labno
!=p2
->labno
) return(0);
delnode(p
) register struct node
*p
; {
if (p
&& --p
->refc
<= 0) {
while (p
&& p
->op
==LABEL
)
register struct node
**i
;
for (i
=uses
+NREG
; i
>uses
;) *--i
=0;
for (i
=regs
+NREG
+1; i
>regs
;){ **--i
=0; **i
=0; }
conloc
[0] = 0; ccloc
[0] = 0;
/* if any indexing, must be parameter or local */
/* indirection (as in "*-4(fp)") is ok, however */
if ((i
= isreg(s
)) >= 0) {
*(short *)(regs
[i
]) = 0; /* if register destination, that reg is a goner */
if (DOUBLE
==(type
&0xF) || DOUBLE
==((type
>>4)&0xF) || type
==QUAD
)
*(short *)(regs
[i
+1]) = 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 */
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;
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
;
if (p1
=p
->code
) while (*p1
) {
while (*p1
) if (','==(*p2
++= *p1
++)) {--p2
; break;}
while (preg
<(regs
+RT1
+5)) *(*preg
++)=0;
if (0==(want
&= 0xF)) return(1); /* anything satisfies a wildcard want */
hsrc
=have
&0xF; if (0==(hdst
=((have
>>4)&0xF)) || hdst
>=OP2
) hdst
=hsrc
;
return(bitsize
[hdst
]==bitsize
[want
] && bitsize
[hsrc
]==bitsize
[want
]);
return(hsrc
==want
&& hdst
>=want
&& hdst
<QUAD
);
equtype(t1
,t2
) {return(compat(t1
,t2
) && compat(t2
,t1
));}
for (i
= regs
+NREG
; --i
>=regs
;) {
if (**i
&& equstr(*i
+1, as
) && compat(**i
,type
))
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');
register struct node *p, *lp;
for (p=first.forw; p!=0; p = p->forw) {
newcode(p
) struct node
*p
; {
register char *p1
,*p2
,**preg
;
while (*(p1
= *preg
++)) {while (*p2
++= *p1
++); *(p2
-1)=',';}
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
++;
/* conditional branches which are never/always taken */
register struct node
*p1
;
register char *ap1
, *ap2
;
ap1
= findcon(regs
[RT1
], p1
->subop
);
ap2
= findcon(regs
[RT2
], p1
->subop
);
ap1
= findcon(ccloc
+1, ccloc
[0]);
switch (compare(p
->subop
, ap1
, ap2
)) {
case 0: /* branch never taken */
if(p
->forw
->op
!=CBR
&& (p1
->op
==TST
|| p1
->op
==CMP
)) {
case 1: /* branch always taken */
if(nonlab(p
->ref
)->op
!=CBR
&& (p1
->op
==TST
|| p1
->op
==CMP
)) {
/* a jump to a redundant compare (start of a 'for') */
register struct node
*p1
;
register char *ap1
, *ap2
;
if (p1
->op
==TST
|| p1
->op
==CMP
)
ap1
= findcon(regs
[RT1
], p1
->subop
);
ap2
= findcon(regs
[RT2
], p1
->subop
);
if (compare(p1
->subop
, ap1
, ap2
) > 0) {
} 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
;
if ((r
= isreg(p
)) >= 0 && compat(regs
[r
][0],type
))
if (equstr(p
, conloc
) && equtype(conloc
[0], type
))
/* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */
register char *cp1
, *cp2
;
register int n1
, n2
, sign
;
if (*cp1
++ != '$' || *cp2
++ != '$')
n1
= 0; sign
=1; if (*cp1
=='-') {++cp1
; sign
= -1;}
while (isdigit(*cp1
)) {n1
*= 10; n1
+= *cp1
++ - '0';}
n2
= 0; sign
=1; if (*cp2
=='-') {++cp2
; sign
= -1;}
while (isdigit(*cp2
)) {n2
*= 10; n2
+= *cp2
++ - '0';}
return((unsigned)n1
< (unsigned)n2
);
return((unsigned)n1
> (unsigned)n2
);
return((unsigned)n1
<= (unsigned)n2
);
return((unsigned)n1
>= (unsigned)n2
);
indexa(p
) register char *p
; {/* 1-> uses [r] addressing mode; 0->doesn't */
while (*p
) if (*p
++=='[') return(1);
{/* 1->simple local, parameter, global, or register; 0->otherwise */
if (*p
=='*' || *p
=='(' || *p
=='$')
if (*--p
==']' || *p
==')' &&
!(*(p
-2)=='f' || fortflg
&& (*--p
=='1' || *p
=='2') && *--p
=='1'))
** Tell if an argument is most likely static.
if (*cp
== '_' || *cp
== 'L')
while (i
++ < MAXAOBDISP
&& ((q
= q
->back
) !=&first
))
while (i
++ < MAXAOBDISP
&& ((q
= q
->forw
) !=0))
struct intleavetab intltab
[] = {
register struct node
*p
, *p1
;
register struct intleavetab
*t
;
for (p
= first
.forw
; p
!=0; p
= p
->forw
){
for (t
=intltab
; t
->op
!= NIL
; t
++){
if (t
->op
== p
->op
&& t
->subop
== p
->subop
){
while ((p1
!= 0) && (p1
->op
!= CBR
) &&
(p1
->subop
== FLOAT
|| p1
->subop
== DOUBLE
||
((p1
->subop
&0xF0)==DOUBLE
<<4) || ((p1
->subop
&0xF)==DOUBLE
)||
((p1
->subop
&0xF0)==FLOAT
<<4) || (p1
->subop
&0xF)==FLOAT
))
if (((r
= isreg(p1
->code
)) >= 0)){
if ((p1
->subop
== DOUBLE
) || ((p
->subop
&0xF0)==DOUBLE
<<4) ||
((p
->subop
&0xF)==DOUBLE
))
else checkreg(p1
,p1
->code
);
if (!(sideeffect(p
, p1
)))
p1
->back
->forw
= p1
->forw
;
p1
->forw
->back
= p1
->back
;
JBR
, CBR
, JMP
, LABEL
, DLABEL
, EROU
, JSW
, TST
, CMP
, BIT
,
CALLF
, CALLS
, CASE
, AOBLEQ
, AOBLSS
, CMPF
, CMPF2
, TSTF
, MOVBLK
, MFPR
,
MTPR
, PROBE
, MOVO
, TEXT
, DATA
, BSS
, ALIGN
, END
, LGEN
, SET
,
if (p1
->op
== NIL
) return(1); /* special instructions */
for (t
= termop
; *t
!=NIL
; t
++){
if (*t
== p1
->op
) return(1);
if ((p1
->forw
!= NULL
) && (p1
->forw
->op
== CBR
))
if (uses
[r
] && r
>= 0 ) return(1);
if ((p1
->op
== EDIV
) && (r
= isreg(regs
[RT3
]) >= 0) &&
for (q
= p1
->back
; q
!=p
; q
=q
->back
)
if ((p1
->op
== PUSH
|| p1
->op
== PUSHA
) &&
(q
->op
== PUSHD
|| q
->op
== PUSH
|| q
->op
== PUSHA
))
return(1); /* keep args in order */
if (((i
= strlen(q
->code
)) >= 5 && /* cvdl -(sp); pushl r0*/
(strcmp(q
->code
+i
-5,"-(sp)") == 0 )) ||
(strcmp(lastrand
,"-(sp)") == 0)) return(1);
if (equstr(q
->code
, lastrand
))
if (q
->op
== STF
|| q
->op
== CVFL
|| q
->op
== CVLF
)
if (equstr(q
->code
, regs
[RT1
])) return(1);
if (has3ops(p1
) || p1
->op
== EMUL
|| p1
->op
== EDIV
)
if (equstr(q
->code
, regs
[RT2
]))
/* handle the case std -56(fp) pushl -60(fp) pushl
if ((p1
->forw
!= NULL
) && (q
->op
== STF
) &&
if (!strncmp(q
->code
,p1
->forw
->code
,strlen(q
->code
)))
do if (*s
=='(' || *s
=='[') {/* get register number */
cp2
= ++s
; while (*++s
!=')' && *s
!=']'); t
= *s
; *s
=0;
if ((r
=isreg(cp2
)) >= 0) {