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