# /* * C object code improver-- second part */ #include "c2h.c" rmove() { register struct node *p; register char *cp; register int r; int r1, flt; for (p=first.forw; p!=0; p = p->forw) { if (debug) { for (r=0; r<2*NREG; r++) if (regs[r][0]) printf("%d: %s\n", r, regs[r]); printf("-\n"); } flt = 0; switch (p->op) { case MOVF: case MOVFO: case MOVOF: flt = NREG; case MOV: if (p->subop==BYTE) goto badmov; dualop(p); if ((r = findrand(regs[RT1], flt)) >= 0) { if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR) { p->forw->back = p->back; p->back->forw = p->forw; redunm++; continue; } } repladdr(p, 0, flt); r = isreg(regs[RT1]); r1 = isreg(regs[RT2]); dest(regs[RT2], flt); if (r >= 0) if (r1 >= 0) savereg(r1+flt, regs[r+flt]); else savereg(r+flt, regs[RT2]); else if (r1 >= 0) savereg(r1+flt, regs[RT1]); else setcon(regs[RT1], regs[RT2]); source(regs[RT1]); setcc(regs[RT2]); continue; case ADDF: case SUBF: case DIVF: case MULF: flt = NREG; case ADD: case SUB: case BIC: case BIS: case MUL: case DIV: case ASH: badmov: dualop(p); repladdr(p, 0, flt); source(regs[RT1]); dest(regs[RT2], flt); if (p->op==DIV && (r = isreg(regs[RT2])>=0)) regs[r+1][0] = 0; ccloc[0] = 0; continue; case CLRF: case NEGF: flt = NREG; case CLR: case COM: case INC: case DEC: case NEG: case ASR: case ASL: case SXT: singop(p); dest(regs[RT1], flt); if (p->op==CLR && flt==0) if ((r = isreg(regs[RT1])) >= 0) savereg(r, "$0"); else setcon("$0", regs[RT1]); setcc(regs[RT1]); continue; case TSTF: flt = NREG; case TST: singop(p); repladdr(p, 0, flt); source(regs[RT1]); if (equstr(regs[RT1], ccloc)) { p->back->forw = p->forw; p->forw->back = p->back; p = p->back; nrtst++; nchange++; } continue; case CMPF: flt = NREG; case CMP: case BIT: dualop(p); source(regs[RT1]); source(regs[RT2]); repladdr(p, 1, flt); ccloc[0] = 0; continue; case CBR: case CFCC: ccloc[0] = 0; continue; case JBR: redunbr(p); default: clearreg(); } } } jumpsw() { register struct node *p, *p1; register t; int nj; t = 0; nj = 0; for (p=first.forw; p!=0; p = p->forw) p->refc = ++t; for (p=first.forw; p!=0; p = p1) { p1 = p->forw; if (p->op == CBR && p1->op==JBR && p->ref && p1->ref && abs(p->refc - p->ref->refc) > abs(p1->refc - p1->ref->refc)) { p->subop = revbr[p->subop]; t = p1->ref; p1->ref = p->ref; p->ref = t; t = p1->labno; p1->labno = p->labno; p->labno = t; nrevbr++; nj++; } } return(nj); } addsob() { register struct node *p, *p1; for (p = &first; (p1 = p->forw)!=0; p = p1) { if (p->op==DEC && isreg(p->code)>=0 && p1->combop==(CBR|JNE<<8)) { if (p->refc < p1->ref->refc) continue; if (p->refc - p1->ref->refc > 50) continue; p->labno = p1->labno; p->combop = SOB; p1->forw->back = p; p->forw = p1->forw; nsob++; } } } abs(x) { return(x<0? -x: x); } equop(ap1, p2) struct node *ap1, *p2; { register char *cp1, *cp2; register struct node *p1; p1 = ap1; if (p1->combop != p2->combop) return(0); if (p1->op>0 && p1->opcode; 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); } decref(ap) { register struct node *p; p = ap; if (--p->refc <= 0) { nrlab++; p->back->forw = p->forw; p->forw->back = p->back; } } nonlab(ap) struct node *ap; { register struct node *p; p = ap; while (p && p->op==LABEL) p = p->forw; return(p); } alloc(an) { register int n; register char *p; n = an; n++; n =& ~01; if (lasta+n >= lastr) { if (sbrk(2000) == -1) { write(2, "Optimizer: out of space\n", 14); exit(1); } lastr =+ 2000; } p = lasta; lasta =+ n; return(p); } clearreg() { register int i; for (i=0; i<2*NREG; i++) regs[i][0] = '\0'; conloc[0] = 0; ccloc[0] = 0; } savereg(ai, as) char *as; { register char *p, *s, *sp; sp = p = regs[ai]; s = as; if (source(s)) return; while (*p++ = *s) { if (s[0]=='(' && s[1]=='r' && s[2]<'5') { *sp = 0; return; } if (*s++ == ',') break; } *--p = '\0'; } dest(as, flt) char *as; { register char *s; register int i; s = as; if ((i = isreg(s)) >= 0) regs[i+flt][0] = 0; while ((i = findrand(s, flt)) >= 0) regs[i][0] = 0; while (*s) { if ((*s=='(' && (*(s+1)!='r' || *(s+2)!='5')) || *s++=='*') { for (i=flt; icode; p2 = regs[RT1]; while (*p2++ = *p1++); regs[RT2][0] = 0; } dualop(ap) struct node *ap; { register char *p1, *p2; register struct node *p; p = ap; p1 = p->code; p2 = regs[RT1]; while (*p1 && *p1!=',') *p2++ = *p1++; *p2++ = 0; p2 = regs[RT2]; *p2 = 0; if (*p1++ !=',') return; while (*p2++ = *p1++); } findrand(as, flt) char *as; { register int i; for (i = flt; i='0' && s[1]<='4' && s[2]==0) return(s[1]-'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(); lp = p; } } source(ap) char *ap; { register char *p1, *p2; p1 = ap; p2 = p1; if (*p1==0) return(0); while (*p2++); if (*p1=='-' && *(p1+1)=='(' || *p1=='*' && *(p1+1)=='-' && *(p1+2)=='(' || *(p2-2)=='+') { while (*p1 && *p1++!='r'); if (*p1>='0' && *p1<='4') regs[*p1 - '0'][0] = 0; return(1); } return(0); } repladdr(p, f, flt) struct node *p; { register r; int r1; register char *p1, *p2; static char rt1[50], rt2[50]; if (f) r1 = findrand(regs[RT2], flt); else r1 = -1; r = findrand(regs[RT1], flt); if (r1 >= NREG) r1 =- NREG; if (r >= NREG) r =- NREG; if (r>=0 || r1>=0) { p2 = regs[RT1]; for (p1 = rt1; *p1++ = *p2++;); if (regs[RT2][0]) { p1 = rt2; *p1++ = ','; for (p2 = regs[RT2]; *p1++ = *p2++;); } else rt2[0] = 0; if (r>=0) { rt1[0] = 'r'; rt1[1] = r + '0'; rt1[2] = 0; nsaddr++; } if (r1>=0) { rt2[1] = 'r'; rt2[2] = r1 + '0'; rt2[3] = 0; nsaddr++; } p->code = copy(rt1, rt2); } } movedat() { register struct node *p1, *p2; struct node *p3; register seg; struct node data; struct node *datp; if (first.forw == 0) return; datp = &data; for (p1 = first.forw; p1!=0; p1 = p1->forw) { if (p1->op == DATA) { p2 = p1->forw; while (p2 && p2->op!=TEXT) p2 = p2->forw; if (p2==0) break; p3 = p1->back; p1->back->forw = p2->forw; p2->forw->back = p3; p2->forw = 0; datp->forw = p1; p1->back = datp; p1 = p3; datp = p2; } } if (data.forw) { datp->forw = first.forw; first.forw->back = datp; data.forw->back = &first; first.forw = data.forw; } seg = -1; for (p1 = first.forw; p1!=0; p1 = p1->forw) { if (p1->op==TEXT||p1->op==DATA||p1->op==BSS) { if (p1->op == seg || p1->forw&&p1->forw->op==seg) { p1->back->forw = p1->forw; p1->forw->back = p1->back; p1 = p1->back; continue; } seg = p1->op; } } } redunbr(ap) struct node *ap; { register struct node *p, *p1; register char *ap1; char *ap2; if ((p1 = p->ref) == 0) return; p1 = nonlab(p1); if (p1->op==TST) { singop(p1); savereg(RT2, "$0"); } else if (p1->op==CMP) dualop(p1); else return; if (p1->forw->op!=CBR) return; ap1 = findcon(RT1); ap2 = findcon(RT2); p1 = p1->forw; if (compare(p1->subop, ap1, ap2)) { nredunj++; nchange++; decref(p->ref); p->ref = p1->ref; p->labno = p1->labno; p->ref->refc++; } } findcon(i) { register char *p; register r; p = regs[i]; if (*p=='$') return(p); if ((r = isreg(p)) >= 0) return(regs[r]); if (equstr(p, conloc)) return(conval); return(p); } compare(op, acp1, acp2) char *acp1, *acp2; { register char *cp1, *cp2; register n1; int n2; struct { int i;}; cp1 = acp1; cp2 = acp2; if (*cp1++ != '$' || *cp2++ != '$') return(0); n1 = 0; while (*cp2 >= '0' && *cp2 <= '7') { n1 =<< 3; n1 =+ *cp2++ - '0'; } n2 = n1; n1 = 0; while (*cp1 >= '0' && *cp1 <= '7') { n1 =<< 3; n1 =+ *cp1++ - '0'; } if (*cp1=='+') cp1++; if (*cp2=='+') cp2++; do { if (*cp1++ != *cp2) return(0); } while (*cp2++); cp1 = n1; cp2 = n2; switch(op) { case JEQ: return(cp1 == cp2); case JNE: return(cp1 != cp2); case JLE: return(cp1.i <= cp2.i); case JGE: return(cp1.i >= cp2.i); case JLT: return(cp1.i < cp2.i); case JGT: return(cp1.i > cp2.i); case JLO: return(cp1 < cp2); case JHI: return(cp1 > cp2); case JLOS: return(cp1 <= cp2); case JHIS: return(cp1 >= cp2); } return(0); } setcon(ar1, ar2) char *ar1, *ar2; { register char *cl, *cv, *p; cl = ar2; cv = ar1; if (*cv != '$') return; if (!natural(cl)) return; p = conloc; while (*p++ = *cl++); p = conval; while (*p++ = *cv++); } equstr(ap1, ap2) char *ap1, *ap2; { char *p1, *p2; p1 = ap1; p2 = ap2; do { if (*p1++ != *p2) return(0); } while (*p2++); return(1); } setcc(ap) char *ap; { register char *p, *p1; p = ap; if (!natural(p)) { ccloc[0] = 0; return; } p1 = ccloc; while (*p1++ = *p++); } natural(ap) char *ap; { register char *p; p = ap; if (*p=='*' || *p=='(' || *p=='-'&&*(p+1)=='(') return(0); while (*p++); p--; if (*--p == '+' || *p ==')' && *--p != '5') return(0); return(1); }