optim.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 845 行 · 第 1/2 页
C
845 行
s2->prev->next = s1; else firstslot = s1; s1->prev = s2->prev; s2->prev = s1; }else { s1->prev = lastslot; lastslot->next = s1; lastslot = s1; }s1->next = s2;++numslots;}/* * deletes the specified slot from the code buffer */delslot (sl)Slotp sl;{removeslot (sl);if (sl->ctlinfo) free ((charptr) sl->ctlinfo);frexpr (sl->expr);free ((charptr) sl);numslots--;}/* * inserts a slot before the specified slot; if given NULL, it is * inserted at the end of the buffer */Slotp optinsert (type,p,l,c,currslot)int type;expptr p;int l;int *c;Slotp currslot;{Slotp savelast,new;savelast = lastslot;if (currslot) lastslot = currslot->prev;new = optbuff (type,p,l,c);new->next = currslot;if (currslot) currslot->prev = new;new->lineno = -1; /* who knows what the line number should be ??!! */if (currslot) lastslot = savelast;return (new);}/* * buffers the FRTEMP slots which have been waiting */frtempbuff (){chainp ht;register Slotp sp;for (ht = holdtemps; ht; ht = ht->nextp) { sp = newslot(); /* this slot actually belongs to some previous source line */ sp->lineno = sp->lineno - 1; sp->type = SKFRTEMP; sp->expr = (expptr) ht->datap; sp->label = 0; sp->ctlinfo = NULL; }holdtemps = NULL;}/* * puts the given information into a slot at the end of the code buffer */Slotp optbuff (type,p,l,c)int type;expptr p;int l;int *c;{register Slotp sp;if (debugflag[1]) { fprintf (diagfile,"-----optbuff-----"); showslottype (type); showexpr (p,0); fprintf (diagfile,"\n"); }p = expand (p);sp = newslot();sp->type = type;sp->expr = p;sp->label = l;sp->ctlinfo = NULL;switch (type) { case SKCMGOTO: sp->ctlinfo = (int*) cplabarr (l, (struct Labelblock**) c); break; case SKARIF: sp->ctlinfo = (int*) cplabarr (3, (struct Labelblock**) c); break; case SKDOHEAD: case SKENDDO: sp->ctlinfo = (int*) cpframe ((struct Ctlframe*) c); break; default: break; }frtempbuff ();return (sp);}/* * expands the given expression, if possible (e.g., concat, min, max, etc.); * also frees temporaries when they are indicated as being the last use */#define APPEND(z) \ res = res->exprblock.rightp = mkexpr (OPCOMMA, z, newtemp)LOCAL expptr expand (p)tagptr p;{Addrp t;expptr q;expptr buffmnmx(), buffpower();if (!p) return (ENULL);switch (p->tag) { case TEXPR: switch (p->exprblock.opcode) { case OPASSIGN: /* handle a = b // c */ if (p->exprblock.vtype != TYCHAR) goto standard; q = p->exprblock.rightp; if (!(q->tag == TEXPR && q->exprblock.opcode == OPCONCAT)) goto standard; t = (Addrp) expand(p->exprblock.leftp); frexpr(p->exprblock.vleng); free( (charptr) p ); p = (tagptr) q; goto cat; case OPCONCAT: t = mktemp (TYCHAR, ICON(lencat(p))); cat: q = (expptr) cpexpr (p->exprblock.vleng); buffcat (cpexpr(t),p); frexpr (t->vleng); t->vleng = q; p = (tagptr) t; break; case OPMIN: case OPMAX: p = (tagptr) buffmnmx (p); break; case OPPOWER: p = (tagptr) buffpower (p); break; default: standard: p->exprblock.leftp = expand (p->exprblock.leftp); if (p->exprblock.rightp) p->exprblock.rightp = expand (p->exprblock.rightp); break; } break; case TLIST: { chainp t; for (t = p->listblock.listp; t; t = t->nextp) t->datap = (tagptr) expand (t->datap); } break; case TTEMP: if (p->tempblock.istemp) frtemp(p); break; case TADDR: p->addrblock.memoffset = expand( p->addrblock.memoffset ); break; default: break; }return ((expptr) p);}/* * local version of routine putcat in putpcc.c, called by expand */LOCAL buffcat(lhs, rhs)register Addrp lhs;register expptr rhs;{int n;Addrp lp, cp;n = ncat(rhs);lp = (Addrp) mkaltmpn(n, TYLENG, PNULL);cp = (Addrp) mkaltmpn(n, TYADDR, PNULL);n = 0;buffct1(rhs, lp, cp, &n);optbuff (SKCALL, call4(TYSUBR, "s_cat", lhs, cp, lp, mkconv(TYLONG, ICON(n))), 0, 0);}/* * local version of routine putct1 in putpcc.c, called by expand */LOCAL buffct1(q, lp, cp, ip)register expptr q;register Addrp lp, cp;int *ip;{int i;Addrp lp1, cp1;if(q->tag==TEXPR && q->exprblock.opcode==OPCONCAT) { buffct1(q->exprblock.leftp, lp, cp, ip); buffct1(q->exprblock.rightp, lp, cp, ip); frexpr(q->exprblock.vleng); free( (charptr) q ); }else { i = (*ip)++; lp1 = (Addrp) cpexpr(lp); lp1->memoffset = mkexpr(OPPLUS,lp1->memoffset, ICON(i*SZLENG)); cp1 = (Addrp) cpexpr(cp); cp1->memoffset = mkexpr(OPPLUS, cp1->memoffset, ICON(i*SZADDR)); optbuff (SKEQ, (mkexpr(OPASSIGN, lp1, cpexpr(q->headblock.vleng))), 0,0); optbuff (SKEQ, (mkexpr(OPASSIGN, cp1, addrof(expand (q)))), 0, 0); }}/* * local version of routine putmnmx in putpcc.c, called by expand */LOCAL expptr buffmnmx(p)register expptr p;{int op, type;expptr qp;chainp p0, p1;Addrp sp, tp;Addrp newtemp;expptr result, res;if(p->tag != TEXPR) badtag("buffmnmx", p->tag);type = p->exprblock.vtype;op = (p->exprblock.opcode==OPMIN ? OPLT : OPGT );qp = expand(p->exprblock.leftp);if(qp->tag != TLIST) badtag("buffmnmx list", qp->tag);p0 = qp->listblock.listp;free( (charptr) qp );free( (charptr) p );sp = mktemp(type, PNULL);tp = mktemp(type, PNULL);qp = mkexpr(OPCOLON, cpexpr(tp), cpexpr(sp));qp = mkexpr(OPQUEST, mkexpr(op, cpexpr(tp),cpexpr(sp)), qp);qp = fixexpr(qp);newtemp = mktemp (type,PNULL);result = res = mkexpr (OPCOMMA, mkexpr( OPASSIGN, cpexpr(sp), p0->datap ), cpexpr(newtemp));for(p1 = p0->nextp ; p1 ; p1 = p1->nextp) { APPEND (mkexpr( OPASSIGN, cpexpr(tp), p1->datap )); if(p1->nextp) APPEND (mkexpr (OPASSIGN, cpexpr(sp), cpexpr(qp)) ); else APPEND (mkexpr (OPASSIGN, cpexpr(newtemp), qp)); }frtemp(sp);frtemp(tp);frtemp(newtemp);frchain( &p0 );return (result);}/* * Called by expand() to eliminate exponentiations to integer constants. */LOCAL expptr buffpower( p ) expptr p;{ expptr base; Addrp newtemp; expptr storetemp = ENULL; expptr powtree(); expptr result; ftnint exp; if ( ! ISICON( p->exprblock.rightp ) ) fatal( "buffpower: bad non-integer exponent" ); base = expand(p->exprblock.leftp); exp = p->exprblock.rightp->constblock.const.ci; if ( exp < 2 ) fatal( "buffpower: bad exponent less than 2" ); if ( exp > 64 ) { /* * Let's be reasonable, here... Let putpower() do the job. */ p->exprblock.leftp = base; return ( p ); } /* * If the base is not a simple variable, evaluate it and copy the * result into a temporary. */ if ( ! (base->tag == TADDR && ISCONST( base->addrblock.memoffset )) ) { newtemp = mktemp( base->headblock.vtype, PNULL ); storetemp = mkexpr( OPASSIGN, cpexpr( (expptr) newtemp ), cpexpr( base ) ); base = (expptr) newtemp; } result = powtree( base, exp ); if ( storetemp != ENULL ) result = mkexpr( OPCOMMA, storetemp, result ); frexpr( p ); return ( result );}/* * powtree( base, exp ) -- Create a tree of multiplications which computes * base ** exp. The tree is built so that CSE will compact it if * possible. The routine works by creating subtrees that compute * exponents which are powers of two, then multiplying these * together to get the result; this gives a log2( exp ) tree depth * and lots of subexpressions which can be eliminated. */LOCAL expptr powtree( base, exp ) expptr base; register ftnint exp;{ register expptr r = ENULL, r1; register int i; for ( i = 0; exp; ++i, exp >>= 1 ) if ( exp & 1 ) if ( i == 0 ) r = (expptr) cpexpr( base ); else { r1 = powtree( base, 1 << (i - 1) ); r1 = mkexpr( OPSTAR, r1, cpexpr( r1 ) ); r = (r ? mkexpr( OPSTAR, r1, r ) : r1); } return ( r );}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?