|
|
1.1 root 1: /* @(#) cost.c: 1.5 3/9/84 */
2:
3: # include "mfile2.h"
4:
5: # ifndef CSTORE
6: # define CSTORE(q) 2
7: # endif
8: # ifndef CLOAD
9: # define CLOAD(q) 2
10: # endif
11: # ifndef CCTEST
12: # define CCTEST(q) 1
13: # endif
14: # ifndef DFLT_STRATEGY
15: # define DFLT_STRATEGY LTOR|RTOL
16: # endif
17:
18: /* enough regs so there is always a free pair */
19: # define HREG ((1+NRGS)/2+1)
20:
21: #define LSAVED 30
22: /* stores costs of leaves costed so far */
23: static struct leaf {
24: int op;
25: int type;
26: int cst[NCOSTS];
27: } leafcosts[LSAVED], *leaf_ptr=leafcosts, *recost_leaf=0;
28: /* used to identify subtrees */
29: # define NSUBTREES 10
30: int nsubtree;
31: NODE *subtree[NSUBTREES];
32: int subgoal[NSUBTREES];
33:
34: int strbc[NCOSTS]; /* the strategy done by bcost */
35: SHAPE * lshbc[NCOSTS]; /* left-hand shape */
36: SHAPE * rshbc[NCOSTS]; /* right-hand shape */
37:
38: commute( p ) NODE *p; {
39: /* commute p in place */
40: register NODE *q;
41: #ifndef NODBG
42: if(odebug) printf("commute: .=%u l=%u r=%u\n",p,p->in.left,p->in.right);
43: #endif
44: q = p->in.left;
45: p->in.left = p->in.right;
46: p->in.right = q;
47: }
48:
49: # ifndef NODBG
50: # define GETS(x,y) if( e2debug>1) printf( " x gets %d\n", y );
51: # define GETSN(x,y) if( e2debug>1) printf( " cst[%d] gets %d\n", x, y );
52: # else
53: # define GETS(x,y)
54: # define GETSN(x,y)
55: # endif
56:
57: bcost( p, q )
58: register NODE *p;
59: register OPTAB *q;
60: {
61: /* return the basic costs of matching q against tree p */
62: /* sha is set previously by match with a list of legal left
63: /* and right shapes */
64: /* bcost updates strbc, lshbc, and rshbc to reflect the
65: /* strategy, left shape, and right shape, that minimizes the cost
66: /* for q on p */
67:
68: /* j has its address taken, so it can't be in a reg */
69: int j;
70: int o, cc, c, s, tc, ttc, n, nn, lnn, lregs, rregs, cs, res;
71: int il, ir; /* index into left and right address shapes */
72: int lsubtree;
73: NODE *l, *r;
74: register NODE *pp;
75: register ix;
76: SHAPE *sl, *sr;
77:
78: o = p->tn.op;
79:
80: /* look for the simple cases with register counts */
81: n = (q->needs&NCOUNT);
82: if( (q->needs&NPAIR) && n<HREG ) n = HREG;
83:
84: /* set up the left and right descendents */
85: l = getlo( p, o );
86: r = getro( p, o );
87: /*
88: * If the operator table entry does not have a left shape,
89: * but it does have a right shape, then this
90: * table entry is for leaves ONLY, referenced to p, not to r
91: */
92: if( q->rshape && !q->lshape)
93: r = p;
94:
95: res = q->rewrite;
96:
97: /* determine the code generation strategy */
98:
99: if( o == COMOP ) cerror( "COMOP in bcost" );
100:
101: s = LTOR; /* default strategy */
102:
103: if( optype(o) == BITYPE ) {
104:
105: switch( o ) {
106:
107: case CALL:
108: case STCALL:
109: case FORTCALL:
110: # ifndef LTORARGS
111: case CM: /* function arguments */
112: # endif
113: s = RTOL;
114: break;
115:
116: default:
117: # ifdef STACK
118: if( asgop(o) ) s = RTOL;
119: else s = LTOR;
120: # else
121: s = DFLT_STRATEGY;
122: # endif
123: break;
124: }
125: }
126:
127: # ifndef NODBG
128: if(e2debug) {
129: printf("bcost(%d(%s),%d(%s),%x), s = ",
130: p-node, opst[o], q->stinline, opst[q->op], sha[0] );
131: pstrat(s);
132: printf( "\n" );
133: printf( "\tneeds=%d%s%s\n", n,
134: (q->needs&LSHARE)?", LSHARE":"",
135: (q->needs&RSHARE)?", RSHARE":"" );
136: printf( "\tshape table: (%d %d %d ... )(%d %d %d ... )\n",
137: sha[0][0]-shapes, sha[0][1]-shapes, sha[0][2]-shapes,
138: sha[1][0]-shapes, sha[1][1]-shapes, sha[1][2]-shapes
139: );
140: }
141: # endif
142:
143: /* triple loop:
144: /* double loop over the left and right sides */
145: /* single loop over the number of regs available */
146:
147: for( il=0; (sl = sha[0][il]) || il==0; ++il ) {
148: lregs = lsubtree = nsubtree = 0;
149: c = q->cost;
150: lnn = n;
151: if( sl ) {
152: /* list the left subtrees */
153: findsub( l, sl );
154: if( l->tn.op==REG && sl->op==REG && asgop(q->op)
155: && !asgop(o) ) {
156:
157: /* in an expression such as a+b, where a is */
158: /* a register var, copy a to a scratch reg */
159: /* before using += to do the add */
160: /* this test causes that copy, by suggesting */
161: /* that the lhs is a subtree, even though it
162: /* matches the template exactly */
163:
164: subtree[nsubtree] = l;
165: subgoal[nsubtree] = NRGS;
166: ++nsubtree;
167: }
168: lsubtree = nsubtree;
169:
170: /* account for the cost of the shape */
171: c += q->lcount * sl->sc;
172:
173: /* count lhs register usage */
174: for( lregs=ix=0; ix<lsubtree; ++ix ) {
175: if( subgoal[ix] == NRGS ) {
176: lregs += szty(subtree[ix]->tn.type);
177: }
178: }
179: if( !(q->needs&LSHARE) ) lnn += lregs;
180: }
181:
182: # ifndef NODBG
183: if( e2debug ) {
184: printf( "\tbcost left shape: sl=%d(%s), cost=%d\n",
185: sl-shapes, sl?opst[sl->op]:"?", c );
186: printf( "\t%d left subtrees\n", nsubtree );
187: for( j=0; j<nsubtree; ++j ) {
188: printf( "\t\tsubtree %d, goal %d\n",
189: subtree[j]-node, subgoal[j] );
190: }
191: }
192: # endif
193:
194: for( ir=0; (sr = sha[1][ir]) || ir==0; ++ir ) {
195: ttc = c;
196: nsubtree = lsubtree;
197: if( sr ) {
198: ttc += q->rcount * sr->sc;
199: findsub( r, sr );
200: }
201: # ifndef NODBG
202: if( e2debug ) {
203: printf( "\tbcost rt. shp: sr=%d(%s), cost=%d\n",
204: sr-shapes, sr?opst[sr->op]:"?", ttc );
205: printf( "\t%d right subtrees\n",
206: nsubtree-lsubtree );
207: for( j=lsubtree; j<nsubtree; ++j ) {
208: printf( "\t\tsubtree %d, goal %d\n",
209: subtree[j]-node, subgoal[j] );
210: }
211: }
212: # endif
213:
214: /* figure out the minimum number of regs. possible */
215: for( rregs=0,ix=lsubtree; ix<nsubtree; ++ix ) {
216: if( subgoal[ix] == NRGS ) {
217: rregs += szty(subtree[ix]->tn.type);
218: }
219: }
220:
221: nn = lnn;
222: if( q->needs & RSHARE ) nn -= rregs;
223: if( nn < lregs ) nn = lregs;
224: nn += rregs;
225:
226: # ifndef NODBG
227: if( e2debug ) {
228: printf( "%d left, %d right regs, need >= %d\n",
229: lregs, rregs, nn );
230: }
231: # endif
232:
233: for( j=NRGS; j>=nn; --j ) {
234: # ifndef NODBG
235: if( e2debug ) {
236: printf( "\t*** j = %d ***\n", j );
237: }
238: # endif
239: /* exact match: don't fool around */
240: if( nsubtree==0 ) {
241: cc = ttc;
242: cs = LTOR;
243: goto distribute;
244: }
245: /* general case: grub around */
246: /* LTOR means ascending, RTOL means descending*/
247:
248: cc = INFINITY;
249: if( s<OR ){ /* do it left to right */
250: int j1 = j;
251: tc = ttc;
252: for( ix=0; ix<nsubtree; ++ix ) {
253: pp = subtree[ix];
254: if( subgoal[ix] == NRGS ){
255: /* shouldn't happen */
256: if( j1<0 ) tc=INFINITY;
257: else tc+=pp->tn.cst[j1];
258: j1 -= szty(pp->tn.type);
259: }
260: else tc +=
261: pp->tn.cst[subgoal[ix]];
262: }
263: cc = tc;
264: cs = LTOR;
265: }
266: if( s&RTOL ){ /* do it right to left */
267: int j1 = j;
268: tc = ttc;
269: for( ix=nsubtree-1; ix>=0; --ix ) {
270: pp = subtree[ix];
271: if( subgoal[ix] == NRGS ){
272: /* shouldn't happen */
273: if( j1<0 ) tc=INFINITY;
274: else tc+=pp->tn.cst[j1];
275: j1 -= szty(pp->tn.type);
276: }
277: else tc +=
278: pp->tn.cst[subgoal[ix]];
279: }
280: if( tc < cc ){
281: cc = tc;
282: cs = RTOL;
283: }
284: }
285: if( cc >= INFINITY ) break; /* done */
286:
287: /* now, cc is the minmal cost with j regs */
288: /* update the various cost measures */
289: /* everything affects CEFF */
290: distribute:
291: # ifndef NODBG
292: if( e2debug ) {
293: printf( "\tdistribute %d\n", cc );
294: }
295: # endif
296: if( cc < p->tn.cst[CEFF] ) {
297: GETS(EFF,cc);
298: p->tn.cst[CEFF] = cc;
299: strbc[CEFF] = cs;
300: lshbc[CEFF] = sl;
301: rshbc[CEFF] = sr;
302: }
303: /* for EFF, only do with NRGS */
304: if( p->tn.goal == CEFF ) break;
305: if( res == RNULL || res == RNOP ){
306: /* affects only CEFF */
307: cerror( "RNULL/RNOP error" );
308: }
309:
310: if( (p->tn.goal==CCC) && (res&RESCC) ) {
311: /* CC's set */
312: if( cc < p->tn.cst[CCC] ) {
313: GETS(CC,cc);
314: p->tn.cst[CCC] = cc;
315: strbc[CCC] = cs;
316: lshbc[CCC] = sl;
317: rshbc[CCC] = sr;
318: }
319: }
320:
321:
322: /* now, the register cost */
323: tc = cc;
324: if( (res&RLEFT) && sl->op != REG ){
325: cc += CLOAD(q);
326: }
327: else if( (res&RRIGHT) && sr->op != REG ){
328: cc += CLOAD(q);
329: }
330: if( cc < p->tn.cst[j] ) {
331: GETSN(j,cc);
332: p->tn.cst[j] = cc;
333: strbc[j] = cs;
334: lshbc[j] = sl;
335: rshbc[j] = sr;
336: }
337:
338: /* for CC's, only do w. NRGS */
339: if( p->tn.goal == CCC ) break;
340:
341: if( j != NRGS ) continue;
342:
343: /* record if lhs is actually a temp */
344: /* need only do for NRGS */
345:
346: if( tempok(p) && tc < p->tn.cst[CTEMP] ) {
347: GETS(TEMP,tc);
348: p->tn.cst[CTEMP] = tc;
349: strbc[CTEMP] = cs;
350: lshbc[CTEMP] = sl;
351: rshbc[CTEMP] = sr;
352: }
353: }
354: }
355: }
356:
357: /* now, some global cleanup */
358: /* some things are worth updating only once per template */
359:
360: if( p->tn.goal == CEFF ) return; /* done */
361:
362: /* set Condition Codes by testing a register */
363: if( p->tn.goal == CCC ) {
364: tc = p->tn.cst[NRGS]+CCTEST(q);
365: if( tc < p->tn.cst[CCC] ) {
366: GETS(CC,tc);
367: p->tn.cst[CCC] = tc;
368: strbc[CCC] = strbc[NRGS];
369: lshbc[CCC] = lshbc[NRGS];
370: rshbc[CCC] = rshbc[NRGS];
371: }
372: return;
373: }
374:
375: /* put into TEMP by putting into REG, then storing */
376: /* if the lhs type is OK and we have an assignment op, don't
377: /* need to store: just use the result from EFF */
378:
379: if( asgop(o) && o!=INCR && o!= DECR && lhsok( l ) &&
380: p->tn.type == l->tn.type ) {
381: cc = p->tn.cst[CEFF];
382: if( cc < p->tn.cst[CTEMP] ) {
383: GETS(CTEMP,cc);
384: p->tn.cst[CTEMP] = cc;
385: strbc[CTEMP] = strbc[CEFF];
386: lshbc[CTEMP] = lshbc[CEFF];
387: rshbc[CTEMP] = rshbc[CEFF];
388: }
389: }
390: tc = p->tn.cst[NRGS] + CSTORE(q);
391:
392: if( tc < p->tn.cst[CTEMP] ) {
393: GETS(TEMP,tc);
394: p->tn.cst[CTEMP] = tc;
395: strbc[CTEMP] = strbc[NRGS];
396: lshbc[CTEMP] = lshbc[NRGS];
397: rshbc[CTEMP] = rshbc[NRGS];
398: }
399:
400: /* compute with few regs by storing, then loading */
401:
402: tc = p->tn.cst[CTEMP] + CLOAD(q);
403:
404: for( j=1; j<NRGS; ++j ) {
405: if( tc < p->tn.cst[j] ) {
406: p->tn.cst[j] = tc;
407: GETSN(j,tc);
408: strbc[j] = strbc[CTEMP] | STORE;
409: lshbc[j] = lshbc[CTEMP];
410: rshbc[j] = rshbc[CTEMP];
411: }
412: }
413: }
414:
415: lhsok( p )
416: NODE *p;
417: {
418: /* p appears on the lhs of an assignment op */
419: /* is it an OK substitute for a TEMP? */
420:
421: switch( p->tn.op ) {
422:
423: case NAME:
424: case VAUTO:
425: case VPARAM:
426: case TEMP:
427: case REG:
428: return( 1 );
429:
430: }
431: return( 0 );
432: }
433:
434: shpr(sp) register SHAPE *sp; {
435: if (!sp) return;
436: if( sp->op < 0 || sp->op > DSIZE ) cerror( "shape op %d\n", sp->op );
437: printf(" %s", opst[sp->op]);
438: shpr(sp->sl);
439: shpr(sp->sr);
440: }
441:
442: pstrat( s ) {
443: /* print a nice version of the strategy s */
444: register i, flag;
445: static char *stratnames[] = {
446: "STORE",
447: "LTOR",
448: "RTOL",
449: 0 };
450: flag = 0;
451: for( i=0; stratnames[i]; ++i ){
452: if( s & (1<<i) ) {
453: if( flag ) putchar( '|' );
454: printf( "%s", stratnames[i] );
455: flag = 1;
456: }
457: }
458: if( !flag ) printf( "0" );
459: }
460:
461: insout( p, i )
462: NODE *p;
463: {
464: OPTAB *q;
465: int c, o, j;
466:
467: /* generate the actual instructions */
468: /* if the cost is infinite, try rewriting */
469:
470: c = p->in.cst[i];
471: o = p->tn.op;
472:
473: #ifndef NODBG
474: if( odebug>1 ) printf( "insout(%d,%d), cost %d\n", p-node,i,c );
475: #endif
476: if( c >= INFINITY ){
477: cerror( "missing table entry, op %s", opst[p->tn.op] );
478: }
479:
480: /* handle COMOP specially */
481: if( o == COMOP ) {
482: q = match( p, (OPTAB *)0 ); /* had better match */
483: if( !q ) cerror( "COMOP match fails" );
484: bprt( p, q, i );
485: return;
486: }
487:
488: /* want to force bcost to do some work */
489: /* this is because the strbc, etc., arrays, set by bcost, are used
490: /* by bprt */
491:
492: for( j=0; j<NCOSTS; ++j ) ++p->in.cst[j];
493: for( q=0; q = match( p, q ); ){
494: if( i != CEFF ) {
495: if( q->rewrite & RLEFT ) restrip( sha[0] );
496: if( q->rewrite & RRIGHT ) restrip( sha[1] );
497: }
498: bcost( p, q );
499: if( p->tn.cst[i] == c ) { /* we have found it */
500: if( strbc[i]&STORE ) bprt( p, q, CTEMP );
501: else bprt( p, q, i );
502: return;
503: }
504: }
505:
506: /* commuting must be in order here */
507: /* if fast flag is on, we can only fail, but it's ok to try */
508:
509: if( o != PLUS && o != MUL && o != AND && o != OR && o != ER ) {
510: e2print( p );
511: cerror( "commute??, op[%d] == %s", o, opst[o] );
512: }
513: commute( p ); /* this is the payoff; don't need to commute back */
514: for( q=0; q = match( p, q ); ){
515: if( i != CEFF ) {
516: if( q->rewrite & RLEFT ) restrip( sha[0] );
517: if( q->rewrite & RRIGHT ) restrip( sha[1] );
518: }
519: bcost( p, q );
520: if( p->tn.cst[i] == c ) { /* we found it */
521: bprt( p, q, i );
522: return;
523: }
524: }
525:
526: cerror( "insout returns without a match" );
527: /* NOTREACHED */
528:
529: }
530:
531: bprt( p, q, i )
532: NODE *p;
533: OPTAB *q;
534: {
535: /* this routine is called to print out the actual instructions */
536: /* it is called with a tree node p, a template q, and a goal i */
537: /* bprt calls bcost, and then captures the left and right shapes */
538: /* it then uses findsub to determine the preconditions and goals */
539: /* a local copy of this information must be made, since bprt can be
540: /* called recursively */
541: /* then, bprt calls insout to output the instructions that establish
542: /* the preconditions. Finally, it can output its own instruction */
543:
544: int j, j1, s, o, k;
545: NODE *l, *r;
546: SHAPE *ls, *rs;
547: int nn;
548: int mygoal[NSUBTREES];
549: NODE *mysubs[NSUBTREES];
550:
551: /* sets j as well */
552: if( i < NRGS ) j = i;
553: else j = NRGS;
554: l = getl( p );
555: r = getr( p );
556: if (q->rshape && !q->lshape)
557: r = p;
558: s = strbc[i];
559: ls = lshbc[i];
560: rs = rshbc[i];
561: o = p->tn.op;
562: # ifndef NODBG
563: if( odebug>1 ) {
564: printf( " matches %d, ls = %d(%s), rs = %d(%s), s= ",
565: q->stinline, ls-shapes, ls?opst[ls->op]:"SHNL",
566: rs-shapes, rs?opst[rs->op]:"SHNL" );
567: pstrat( s );
568: printf( "\n" );
569: }
570: # endif
571:
572: /* handle COMOP differently; this has more to do with the register
573: /* allocation than the ordering */
574:
575: if( o == COMOP ) {
576: insout( l, CEFF );
577: insout( r, i );
578: goto generate;
579: }
580:
581: nsubtree = 0;
582: if(rs && (s&RTOL) ) findsub( r, rs );
583: if( ls ) {
584: findsub( l, ls );
585: if( l->tn.op==REG && ls->op==REG && asgop(q->op) &&
586: !asgop(o) ) {
587: /* we must arrange to copy a reg variable on the lhs
588: /* of a binary op, in some cases (cf. bcost) */
589: subtree[nsubtree] = l;
590: subgoal[nsubtree] = NRGS;
591: ++nsubtree;
592: }
593: }
594: if(rs && (s<OR) ) findsub( r, rs );
595: nn = nsubtree;
596:
597: /* make a local copy */
598: for( k=0; k<nn; ++k ) {
599: mygoal[k] = subgoal[k];
600: mysubs[k] = subtree[k];
601: }
602:
603: # ifndef NODBG
604: if( odebug>1 ) { /* subtree matches are: */
605: printf( "\t\t%d matches\n", nn );
606: for( k=0; k<nn; ++k ) {
607: printf( "\t\tnode %d, goal %d\n",mysubs[k]-node,
608: mygoal[k] );
609: }
610: }
611: # endif
612:
613: /* do the subtrees */
614: /* someday, rewrite the temps right here and now */
615:
616: j1 = j;
617: for( k=0; k<nn; ++k ) {
618: # ifndef NODBG
619: if( odebug>2 )
620: printf( "\t\tcalling insout(%d,%d)\n", mysubs[k]-node,
621: j1 );
622: # endif
623: if( mygoal[k] == NRGS ) {
624: insout( mysubs[k], j1 );
625: j1 -= szty( mysubs[k]->tn.type );
626: }
627: else {
628: insout( mysubs[k], mygoal[k] );
629: }
630: }
631: /* put onto the instruction string the info about the instruction */
632: generate:
633: if( nins >= NINS ) cerror( "too many instructions generated" );
634: inst[nins].p = p;
635: inst[nins].q = q;
636: inst[nins].goal = i;
637: /* a special case: REG op= xxx, should be done as early as possible */
638: if( asgop(o) && p->in.left->tn.op == REG && o != INCR && o != DECR
639: && i!=CEFF && i!=CCC && !istreg(p->in.left->tn.rval)){
640: /* "istreg" guards against rewriting returns, switches, etc. */
641: inst[nins].goal = CTEMP;
642: }
643: ++nins;
644: }
645:
646: findsub( p, s )
647: NODE *p;
648: SHAPE *s;
649: {
650: /* account for the costs of matching the shape s with the tree j */
651:
652: if( !s )
653: return;
654:
655: # ifndef NODBG
656: if( e2debug>1 ) {
657: printf( "\t\tfindsub( %d, %d )\n", p-node, s-shapes );
658: }
659: # endif
660:
661: switch( s->op ) {
662:
663: case TEMP:
664: /* leave j unchanged */
665: if( p->tn.op == TEMP ) return;
666: subtree[nsubtree] = p;
667: subgoal[nsubtree] = CTEMP;
668: ++nsubtree;
669: return;
670:
671: case FREE:
672: subtree[nsubtree] = p;
673: subgoal[nsubtree] = CEFF;
674: ++nsubtree;
675: return;
676:
677: case CCODES:
678: subtree[nsubtree] = p;
679: subgoal[nsubtree] = CCC;
680: ++nsubtree;
681: return;
682:
683: case REG:
684: if( p->tn.op == REG ) return; /* exact match */
685:
686: /* in general, look beneath */
687: /* also, look here if a REG and rcst is 1 */
688:
689: subtree[nsubtree] = p;
690: subgoal[nsubtree] = NRGS;
691: ++nsubtree;
692: return;
693: }
694:
695: if( s->op == p->tn.op ) {
696:
697: /* look at subtrees */
698: if( s->sl ) findsub( getl(p), s->sl );
699: if( s->sr ) findsub( getr(p), s->sr );
700: return;
701: }
702: }
703:
704: costs( p ) register NODE *p; {
705: register OPTAB *q;
706: int i, o, ty;
707: register *pc;
708:
709: /* compute the costs for p */
710: /* the goal is either NRGS (into a reg. or temp), CCC, or CEFF */
711:
712: /* in a stack machine, this will probably look very different.
713: /* it is possible that seting szty() to be 0 will deal with the
714: /* stack machine problems; if not, we will need to put some special
715: /* code in here under control of ifdef STACK
716: /* the stack machine issue is that the "register" use on the left does
717: /* not limit the computations on the right, and conversely */
718: again:
719: ty = optype( o = p->tn.op );
720: if (ty == LTYPE && get_leaf(p) ) return(0);
721: pc = p->in.cst;
722: for( i=0; i<NCOSTS; ++i ) {
723: pc[i] = INFINITY;
724: strbc[i] = 0;
725: lshbc[i] = rshbc[i] = (SHAPE *)0;
726: }
727:
728: # ifndef NODBG
729: if( udebug ) {
730: printf( "costs( %d, %d ), op = %s\n", p-node,
731: p->tn.goal, opst[o] );
732: }
733: # endif
734:
735: if( ty != LTYPE ) if( costs( p->in.left ) ) return(1);
736: if( ty == BITYPE ) if( costs( p->in.right ) ) return(1);
737:
738: pc = p->in.cst;
739:
740: /* now, compute the costs based on matches */
741: /* handle COMOP specially */
742: if( o == COMOP ) {
743: int cc = p->in.left->in.cst[CEFF];
744: for( i=NRGS; i<NCOSTS; ++i ) {
745: pc[i] = cc + p->in.right->in.cst[i];
746: if( pc[i] > INFINITY ) pc[i] = INFINITY;
747: }
748: return(0);
749: }
750:
751: for( q=0; q = match(p,q); ){
752: if( p->tn.goal != CEFF ) {
753: if( q->rewrite & RLEFT ) restrip( sha[0] );
754: if( q->rewrite & RRIGHT ) restrip( sha[1] );
755: }
756: bcost( p, q );
757: # ifndef NODBG
758: if( udebug ) {
759: printf( "bcost( %d, %d )\n", p-node, q->stinline);
760: e222print( 1, p, "T" );
761: }
762: # endif
763: }
764:
765: #ifndef NOCOMMUTE
766: /* don't commute if we are trying to be fast */
767: if( !fast && (o==PLUS||o==MUL||o==AND||o==OR||o==ER) ){
768: # ifndef NODBG
769: if( udebug ) {
770: printf( "COMMUTE %d *******\n", p-node );
771: }
772: # endif
773: commute( p );
774: for( q=0; q = match(p,q); ){
775: if( p->tn.goal != CEFF ) {
776: if( q->rewrite & RLEFT ) restrip( sha[0] );
777: if( q->rewrite & RRIGHT ) restrip( sha[1] );
778: }
779: bcost( p, q );
780: # ifndef NODBG
781: if( udebug ) {
782: printf( "bcost( %d, %d )\n", p-node, q->stinline);
783: e222print( 1, p, "T" );
784: }
785: # endif
786: }
787: commute( p );
788: # ifndef NODBG
789: if( udebug ) {
790: printf( "END OF COMMUTE %d *******\n", p-node );
791: }
792: # endif
793: }
794:
795: /* END OF COMMUTE CODE ***** */
796: # endif
797:
798: /* here is a big worry; when do we do this rewriting?
799: /* if we do it too early, we may miss some neat possibilities */
800: /* if we do it too late, we may have miscomputed some earlier things */
801:
802: if( pc[p->tn.goal]>=INFINITY ){
803: if( p->fn.type == TSTRUCT ) return(0);
804: if( optype( o ) == LTYPE ) return( 0 );
805: if( rewass( p ) ) return( 1 ); /* major rewrite */
806: goto again; /* minor rewrite: restart here */
807: }
808: if (ty == LTYPE)
809: save_leaf(p);
810: return( 0 );
811: }
812: static get_leaf(p)
813: register NODE *p;
814: {
815: register struct leaf *lf;
816: /*see if this leaf/type pair is in the tables*/
817: /* multiple flavored ICON's don't save properly */
818: if ( p->tn.op == ICON ) return(0);
819: recost_leaf=0;
820: for (lf=leafcosts;lf < leaf_ptr; lf++){
821: if (lf->op == p->tn.op && lf->type == p->tn.type)
822: {
823: /*if the saved cost was infinite, we will have
824: to recost the leaf anyway*/
825: if (lf->cst[p->tn.goal] >= INFINITY)
826: {
827: recost_leaf = lf;
828: return(0);
829: }
830: /*else, load the costs and leave*/
831: memcpy(p->tn.cst,lf->cst,sizeof(int)*NCOSTS);
832: return(1);
833: }
834: } /*end for*/
835: return(0);
836: } /*end get_leaf*/
837:
838: static save_leaf(p)
839: register NODE *p;
840: {
841: /*save the costs of this leaf for future reference.
842: if recost_leaf is non-zero, it is already in the
843: table*/
844: register struct leaf *lf;
845: if ( p->tn.op == ICON )
846: {
847: /* ICONs have too many flavors to save by op */
848: recost_leaf=0;
849: return;
850: }
851: if ( !recost_leaf && (leaf_ptr >= leafcosts + LSAVED) ) return;
852: lf = recost_leaf ? recost_leaf : leaf_ptr++;
853: lf->op = p->tn.op;
854: lf->type = p->tn.type;
855: memcpy(lf->cst,p->tn.cst,sizeof(int)*NCOSTS);
856: recost_leaf=0;
857: }
858:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.