|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)optim2.c 1.1 86/02/03 Copyr 1985 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: #include "cpass2.h"
10:
11: /*
12: * routines to detect and to deal with doubly-indexed OREGs.
13: * Initially, these were all stolen from the vax code.
14: */
15:
16: base( p )
17: register NODE *p;
18: {
19: register int o = p->in.op;
20: register v,maxoff;
21: register NODE *lp,*rp;
22:
23: if ( BTYPE(p->in.type) == DOUBLE )
24: maxoff = 123;
25: else
26: maxoff = 127;
27: if ( o==REG && isbreg( p->tn.rval ))
28: return( p->tn.rval );
29: lp = p->in.left;
30: rp = p->in.right;
31: if ((o==PLUS || o==MINUS)
32: && lp->in.op==REG && isbreg( lp->tn.rval )
33: && rp->in.op==ICON && rp->in.name[0] == '\0'
34: && (use68020 || (v=rp->tn.lval) <= maxoff && v >= -128)
35: )
36: return( lp->tn.rval );
37: return( -1 );
38: }
39:
40: offset( p, notused )
41: register NODE *p;
42: int notused;
43: {
44: if ( p->in.op==REG ) {
45: if ( p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type) ) {
46: return( p->tn.rval );
47: }
48: if ( p->in.type==SHORT ) {
49: /*
50: * result is: short index flag + xreg
51: */
52: return( (1<<8) + p->tn.rval );
53: }
54: }
55: if (use68020) {
56: /*
57: * test for scaled indexing
58: */
59: int count;
60: NODE *lp = p->in.left;
61: NODE *rp = p->in.right;
62: if ( p->in.op==LS && lp->in.op==REG
63: && (lp->in.type==INT || lp->in.type==UNSIGNED || lp->in.type == SHORT )
64: && (rp->in.op==ICON && rp->in.name[0]=='\0')
65: && (count = rp->tn.lval) >= 0 && count <= 3 ) {
66: int scale = (1 << count);
67: if ( p->in.type == SHORT ) {
68: /*
69: * result is: short index flag + scale factor + xreg
70: */
71: return( (1<<8) + (scale<<4) + lp->tn.rval );
72: }
73: /*
74: * result is: scale factor + xreg
75: */
76: return( (scale<<4) + lp->tn.rval );
77: }
78: }
79: return( -1 );
80: }
81:
82: makeor2( p, basenode, breg, scale_plus_xreg )
83: register NODE *p; /* node to be rewritten */
84: register NODE *basenode; /* base node (usually a ptr) */
85: int breg; /* base register */
86: int scale_plus_xreg; /* scale factor + index register */
87: {
88: register NODE *t; /* from which tn.lval, tn.name are obtained */
89: register int i;
90: NODE *f;
91:
92: register flags;
93: int scale, xreg, shortx, ibit;
94:
95: ibit = 0;
96: shortx= (scale_plus_xreg >> 8) & 1;
97: scale = (scale_plus_xreg >> 4) & 017;
98: xreg = scale_plus_xreg & 017;
99:
100: p->in.op = OREG;
101: f = p->in.left; /* have to free this subtree later */
102:
103: /* init base */
104: switch (basenode->in.op) {
105: case ICON:
106: case REG:
107: case OREG:
108: t = basenode;
109: break;
110:
111: case MINUS:
112: basenode->in.right->tn.lval = -basenode->in.right->tn.lval;
113: case PLUS:
114: t = basenode->in.right;
115: break;
116:
117: case INCR:
118: case ASG MINUS:
119: t = basenode->in.left;
120: break;
121:
122: case UNARY MUL:
123: t = basenode->in.left->in.left;
124: break;
125:
126: default:
127: cerror("illegal makeor2");
128: }
129:
130: p->tn.lval = t->tn.lval;
131: #ifndef FLEXNAMES
132: for(i=0; i<NCHNAM; ++i)
133: p->in.name[i] = t->in.name[i];
134: #else
135: p->in.name = t->in.name;
136: #endif
137:
138: /*
139: * For 68020, R2UPK3 encodes the following data:
140: * int shortx:1; short index
141: * int ibit:1; memory indirect mode (unused)
142: * int scale:4; scale factor (1,2,4,8)
143: * For 68010, only the short index flag is encoded.
144: */
145: R2PACKFLGS(flags,shortx,ibit,scale);
146: p->tn.rval = R2PACK( breg, xreg, flags );
147:
148: tfree(f);
149: return;
150: }
151:
152:
153: /*
154: * Multiply a value by a constant.
155: * Multiplies are slow on the 68010, so do some shifting and
156: * adding here.
157: * For each 1-bit in the constant the value is shifted
158: * by n where 2**n equals the bit.
159: * The shifted value is then added into an accumulated value.
160: * One tricky part is for runs of three or more consecutive
161: * bits. For a number like 7, it is cheaper to calculate
162: * (8 - 1), than it is (3 + 2 + 1)
163: */
164: conmul(p, cookie)
165: register NODE *p;
166: {
167: register const; /* The constant value */
168: register int curpos; /* Position of last one bit */
169: register int power; /* The bit being tested */
170: int run; /* Num of consecutive one bits */
171: int nbits; /* Num of bits since the last one bit */
172: int negconst; /* Is the constant <0 ? */
173: char * destreg; /* name of "AL" register */
174: char * helper; /* name of "A1" register */
175: int helperreg;
176: TWORD ltype;
177: char typechar;
178: int t;
179:
180: /*
181: * first determine how many instructions we will need to do
182: * it in line. Cost estimator is: # single bits + 2* # of multi bit
183: * runs. If this exceeds 5, then it is more compact to use a
184: * multiply instruction or routine.
185: */
186: const = p->in.right->tn.lval;
187: if (const<0){
188: negconst = 1;
189: const = - const;
190: } else
191: negconst = 0;
192: run = const & (const>>1); /* each run shortened by one bit */
193: run = cntbits( run ^ (run>>1) ) + (run&1); /* 2*# multibit runs */
194: nbits = cntbits( const ^ (const>>1)) +(const&1); /* 2* #total runs*/
195: run += nbits; /* 2* estimator */
196: ltype = p->in.left->in.type;
197: if ((ttype(ltype,TUCHAR|TCHAR|TUSHORT|TSHORT) && run>6) || (run > 10)){
198: /* old-fashioned way */
199: if (tshape( p->in.right, SSCON ) ){
200: if (negconst){
201: expand( p->in.left, INAREG|INTAREG, " negZB AL\nZv");
202: p->in.right->tn.lval = const;
203: }
204: if (ttype(ltype, TSHORT|TCHAR)){
205: expand( p, cookie, " muls #CR,AL\nZv");
206: } else if (ttype(ltype, TUSHORT|TUCHAR)){
207: expand( p, cookie, " mulu #CR,AL\n");
208: } else if (use68020) {
209: if (ISUNSIGNED(p->in.type)) {
210: expand( p, cookie, " mulul #CR,AL\n");
211: } else {
212: expand( p, cookie, " mulsl #CR,AL\nZv");
213: }
214: } else {
215:
216: expand( p, cookie,
217: "\tmovl\tAL,A1\n\tswap\tA1\n\tmulu\t#CR,AL\n");
218: fputs( ttype(ltype, TULONG|TUNSIGNED|TUCHAR|TPOINT)
219: ? "\tmulu" : "\tmuls", stdout);
220: expand( p, cookie,
221: "\t#CR,A1\n\tswap\tA1\n\tclrw\tA1\n\taddl\tA1,AL\nZv");
222: }
223: } else if (use68020) {
224: if (ISUNSIGNED(p->in.type)) {
225: expand( p, cookie, " mulul #CR,AL\n");
226: } else {
227: expand( p, cookie, " mulsl #CR,AL\nZv");
228: }
229: } else {
230: order( p->in.right, INTAREG );
231: order( p, INAREG|INTAREG );
232: }
233: return;
234: }
235: typechar = (((t=p->in.type)==CHAR)||t==UCHAR) ? 'b'
236: : (t==SHORT||t==USHORT) ? 'w'
237: : 'l';
238: /*
239: * if the result type is larger than the operand type, we must expand
240: * the operand before doing the operation.
241: */
242: switch( p->in.left->tn.type){
243: case UCHAR:
244: case USHORT:
245: if (typechar=='b' || typechar=='w') break;
246: expand( p->in.left, INAREG|INTAREG, " andl #0xffff,AL\n");
247: break;
248: case CHAR:
249: case SHORT:
250: if (typechar=='b' || typechar=='w') break;
251: expand( p->in.left, INAREG|INTAREG, " extl AL\n");
252: break;
253: }
254: p->in.left->tn.type = t;
255: nbits = ffs( const )-1;
256: power = 0;
257: helperreg = resc[0].tn.rval ;
258: helper = rnames[ helperreg ];
259: destreg = rnames[ p->in.left->tn.rval];
260: if (negconst){
261: expand( p->in.left, INAREG|INTAREG, " negZB AL\nZv");
262: }
263: if (nbits>0){
264: shiftreg( nbits, destreg, helperreg , 1, typechar, t);
265: const >>= nbits;
266: }
267: if (const==1) return;
268: /*
269: * the first time is special (ask Ann Landers). If it is a run,
270: * then we move, negate, shift add. Otherwise, we don't negate.
271: */
272: run = ffs( ~const) -1;
273: expand(p, cookie, " movZB AL,A1\n");
274: switch (run){
275: case 2:
276: shiftreg( 1, helper, -1, 1, typechar, t);
277: expand( p, cookie, "\taddZB\tA1,AL\nZv");
278: /* fall through */
279: case 1:
280: curpos = 0;
281: break;
282: default:
283: shiftreg( run, helper, -1, 1, typechar, t);
284: expand( p->in.left, INAREG|INTAREG, " negZB AL\nZv");
285: expand( p, cookie, "\taddZB\tA1,AL\nZv");
286: curpos = 1;
287: break;
288: }
289: for ( const >>= run; const >>= (power=ffs(const))-1; const >>= run){
290: run = ffs(~const)-1;
291: switch(run) {
292: case 1:
293: shiftreg( power-curpos, helper, -1, 1, typechar, t);
294: expand( p, cookie, "\taddZB\tA1,AL\nZv");
295: curpos = 0;
296: break;
297: case 2:
298: shiftreg( power-curpos, helper, -1, 1, typechar, t);
299: expand( p, cookie, "\taddZB\tA1,AL\nZv");
300: shiftreg( 1, helper, -1, 1, typechar, t);
301: expand( p, cookie, "\taddZB\tA1,AL\nZv");
302: curpos = 0;
303: break;
304: default:
305: shiftreg( power-curpos, helper, -1, 1, typechar, t);
306: expand( p, cookie, "\tsubZB\tA1,AL\nZv");
307: shiftreg( run, helper, -1, 1, typechar, t);
308: expand( p, cookie, "\taddZB\tA1,AL\nZv");
309: curpos = 1;
310: break;
311: }
312: }
313: }
314:
315: /*
316: * divide a signed number by a constant.
317: * divides are really slow on this machine, so we really want to avoid them.
318: * the only interesting case is divide by power-of-two. Others, we really
319: * have to do the division.
320: */
321: void
322: condiv( p, cookie ) register NODE *p;
323: {
324: char sizechar;
325: register const;
326: register TWORD ltype;
327: int lab1f;
328: char * lname = rnames[p->in.left->tn.rval];
329: const = p->in.right->tn.lval;
330: ltype = p->in.left->tn.type;
331: if (const & (const-1)){
332: /* too bad -- not a positive power of two */
333: switch (ltype){
334: case CHAR:
335: print_str_str_nl( " extw ", lname );
336: /* fall through */
337: case SHORT:
338: print_str_str_nl( " extl ", lname );
339: printf( " divs #%d,%s\n", const, lname);
340: break;
341: default:
342: if (use68020) {
343: printf( " divsl #%d,%s\n",
344: const, lname);
345: } else {
346: order( p->in.right, INTAREG );
347: order( p, INTAREG );
348: }
349: break;
350: }
351: return;
352: }
353: switch (ltype){
354: case CHAR: sizechar = 'b'; break;
355: case SHORT: sizechar = 'w'; break;
356: default: sizechar = 'l';
357: }
358: lab1f = getlab();
359: printf(" tst%c %s\n jge L%d\n", sizechar, lname, lab1f);
360: print_str((const >= 1 && const <= 8) ? " addq" : " add");
361: printf("%c #%d,%s\n", sizechar, const-1, lname );
362: deflab(lab1f);
363: const = ffs(const)-1;
364: /* like shiftreg(), but for right, arithmetic shifts */
365: while (const > 0){
366: if (const> 8){
367: printf(" asr%c #8,%s\n", sizechar, lname );
368: const -= 8;
369: } else {
370: printf(" asr%c #%d,%s\n", sizechar, const, lname );
371: const = 0;
372: }
373: }
374: return;
375: }
376:
377:
378: /*
379: * remainder a signed number by a constant.
380: * remainders are really slow on this machine, so we really want to avoid them.
381: * the only interesting case is powers-of-two. Others, we really
382: * have to do the division.
383: */
384: void
385: conrem( p, cookie ) register NODE *p;
386: {
387: char sizechar, opchar;
388: register const;
389: register TWORD ltype;
390: char * lname = rnames[p->in.left->tn.rval];
391: char * helper, u;
392: int lab1f, lab2f;
393: const = p->in.right->tn.lval;
394: ltype = p->in.left->tn.type;
395: if (const & (const-1)){
396: /* too bad -- not a positive power of two */
397: switch (ltype){
398: case CHAR:
399: print_str_str_nl( " extw ", lname );
400: /* fall through */
401: case SHORT:
402: print_str_str_nl( " extl ", lname );
403: printf( " divs #%d,%s\n", const, lname);
404: print_str_str_nl( " swap ", lname );
405: break;
406: case UCHAR:
407: print_str_str_nl(" andl #0xff,", lname );
408: goto divu;
409: case USHORT:
410: print_str_str_nl(" andl #0xffff,", lname );
411: divu: printf(" divu #%d,%s\n", const, lname);
412: print_str_str_nl(" swap ", lname);
413: break;
414: default:
415: if (use68020) {
416: helper = rnames[resc[0].tn.rval];
417: printf(" %s #%d,%s:%s\n",
418: (ISUNSIGNED(ltype)? "divull" : "divsll"),
419: const, helper, lname);
420: printf(" movl %s,%s\n", helper, lname);
421: } else {
422: order( p->in.right, INTAREG );
423: order( p, INTAREG );
424: }
425: break;
426: }
427: return;
428: }
429: helper = rnames[resc[0].tn.rval];
430: u = 0;
431: switch (ltype){
432: case UCHAR: u = 1; /* fall through */
433: case CHAR: sizechar = 'b'; opchar = 'w'; break;
434: case USHORT: u = 1; /* fall through */
435: case SHORT: sizechar = 'w'; opchar = 'w'; break;
436: case UNSIGNED: u = 1; /* fall through */
437: default: sizechar = 'l'; opchar = 'l';
438: }
439: if (!u){
440: lab1f = getlab();
441: lab2f = getlab();
442: }
443: if (const<=128 && const >=-128){
444: printf(" moveq #%d,%s\n", const-1, helper);
445: if (!u){
446: printf(" tst%c %s\n jge L%d\n neg%c %s\n",
447: sizechar, lname, lab1f, sizechar, lname);
448: printf(" and%c %s,%s\n neg%c %s\n jra L%d\n",
449: opchar, helper, lname, opchar, lname, lab2f );
450: deflab( lab1f );
451: }
452: printf(" and%c %s,%s\n", opchar, helper, lname);
453: if (!u){ deflab(lab2f);}
454: } else {
455: if (!u){
456: printf(" mov%c %s,%s\n jge L%d\n neg%c %s\n",
457: sizechar, lname, helper, lab1f, sizechar, lname);
458: deflab(lab1f);
459: }
460: printf(" and%c #%d,%s\n", opchar, const-1, lname );
461: if (!u){
462: printf(" tst%c %s\n jge L%d\n neg%c %s\n",
463: sizechar, helper, lab2f, opchar, lname );
464: deflab(lab2f);
465: }
466: }
467: return;
468: }
469:
470: optim2( p )
471: register NODE *p;
472: {
473: register NODE *q;
474: register NODE *r;
475: register long v;
476: register op;
477: int w;
478: int lsize, rsize;
479: NODE *rl, *rr, *qq;
480: TWORD t;
481:
482: /*
483: * reduction of strength on integer constant operands
484: * this is a practical, fruitful area of peephole code optimization,
485: * since there are so many easy things that can be done.
486: * we also check for possible single-o OREGs in a place where
487: * the oreg2() should but does not.
488: */
489: op = p->in.op;
490: switch (optype(op)) {
491: case LTYPE:
492: break;
493: case UTYPE:
494: optim2(p->in.left);
495: break;
496: case BITYPE:
497: optim2(p->in.left);
498: optim2(p->in.right);
499: break;
500: }
501: switch (op){
502: case LS:
503: case ASG LS:
504: case RS:
505: case ASG RS:
506: /* if rhs is an extending SCONV, don't bother converting */
507: r = p->in.right;
508: if (isconv(r, SHORT, USHORT) || isconv(r, CHAR, UCHAR)) {
509: q = r->in.left;
510: *r = *q;
511: q->in.op = FREE;
512: }
513: /* one interesting case: <lhs> <op> 0 */
514: if (r->tn.op != ICON ) break;
515: if (r->tn.lval == 0 && r->tn.name[0] == '\0' ){
516: promoteleft:
517: t = p->in.type;
518: q = p->in.left;
519: *p = *q; /* paint over */
520: p->in.type = t;
521: q->in.op = r->in.op = FREE;
522: }
523: /* could test for count of 1, too, but this is easier to do later on */
524: break;
525:
526: case UNARY MUL:
527: /* in case this wasn't done earlier... */
528: if (p->in.left->in.op == ICON) {
529: q = p->in.left;
530: t = p->in.type;
531: *p = *q;
532: p->in.op = NAME;
533: p->in.type = t;
534: q->in.op = FREE;
535: break;
536: }
537: /*
538: * put potential double index OREG trees into a canonical
539: * form: ( <base> + <offset> ) + <index>
540: */
541: p = p->in.left;
542: if (p->in.op != PLUS)
543: break;
544: q = p->in.left;
545: r = p->in.right;
546: if ( ISPTR(r->in.type) ) {
547: /*
548: * put the pointer on the left
549: */
550: p->in.left = r;
551: p->in.right = q;
552: q = p->in.left;
553: r = p->in.right;
554: }
555: if ( ISPTR(q->in.type)
556: && (r->in.op == PLUS || r->in.op == MINUS)
557: && !ISPTR(r->in.left->in.type)
558: && r->in.right->in.op == ICON ) {
559: /*
560: * <ptr exp> + ( <int exp> [+-] ICON )
561: * rewrite as
562: * (<ptr exp> [+-] ICON) + <int exp>
563: */
564: p->in.right = r->in.left;
565: r->in.left = q;
566: p->in.left = r;
567: r->in.type = q->in.type;
568: break;
569: }
570: if (r->in.op == LS
571: && ( (rr = r->in.right)->in.op == ICON )
572: && ( (rl = r->in.left)->in.op == PLUS
573: || rl->in.op == MINUS )
574: && !ISPTR(rl->in.left->in.type)
575: && rl->in.right->in.op == ICON ) {
576: /*
577: * <ptr exp> + ((<int exp> [+-] ICON) << ICON)
578: * rewrite as
579: * (<ptr exp> [+-] ICON*) + (<int exp> << ICON)
580: */
581: r->in.left = rl->in.left;
582: rl->in.left = q;
583: p->in.left = rl;
584: rl->in.type = q->in.type;
585: rl->in.right->tn.lval <<= rr->tn.lval;
586: break;
587: }
588: break;
589:
590: case PLUS:
591: case ASG PLUS:
592: case MINUS:
593: case ASG MINUS:
594: /*
595: * one interesting cases: <lhs> <op> 0.
596: * <address reg> + SCONV( <short> ) is a good one, too,
597: * but is best done later on.
598: */
599: if (((r=p->in.right)->tn.op == ICON
600: && r->tn.lval == 0 && r->tn.name[0] == '\0' )
601: || (r->tn.op == FCON && r->fpn.dval == 0.0 )) {
602: goto promoteleft;
603: }
604: break;
605:
606: case MUL:
607: /*
608: * put constants on the right
609: */
610: if (p->in.left->in.op == ICON && p->in.right->in.op != ICON) {
611: r = p->in.right;
612: p->in.right = p->in.left;
613: p->in.left = r;
614: }
615: /* fall through */
616:
617: case ASG MUL:
618: case DIV:
619: case ASG DIV:
620: case MOD:
621: case ASG MOD:
622: /*
623: * two interesting case: <lhs> <op> 1
624: * and: small multiplies that can be handled by
625: * the feeble instructions.
626: */
627: if (((r=p->in.right)->tn.op == ICON
628: && r->tn.lval == 1 && r->tn.name[0] == '\0')
629: || (r->tn.op == FCON && r->fpn.dval == 1.0 )) {
630: switch (op){
631: case MOD:
632: case ASG MOD:
633: /*
634: * x%1 == 0
635: * BUT x might have side effects, so...
636: * x%1 ==> (x,0)
637: */
638: p->in.op = COMOP;
639: if (r->tn.op==FCON)
640: r->fpn.dval = 0.0;
641: else
642: r->tn.lval = 0;
643: break;
644: default:
645: goto promoteleft;
646: }
647: break;
648: }
649: if (op == DIV || op == ASG DIV){
650: /*
651: * a very particular case: a difference of two
652: * pointers, divided by a power of two should
653: * always give an integral result (this is
654: * pointer subtraction, with the implied divide
655: * by sizeof( *p ) ). So, we can change this
656: * into a shift, if we ever see it.
657: * AND...
658: * a less peculiar case: unsigned divide by a power of 2.
659: */
660: if (
661: (p->in.type == UNSIGNED && r->in.op ==ICON )
662: || ((p->in.type == INT || p->in.type == UNSIGNED)
663: && r->in.op == ICON && (q = p->in.left)->in.op == MINUS
664: && ISPTR(q->in.left->in.type)
665: && ISPTR(q->in.right->in.type))
666: ){
667: if (cntbits( v=r->tn.lval )==1 && r->in.name[0]=='\0' ){
668: /* well, looks like we found one */
669: w = ffs( v ) - 1;
670: p->in.op = op += RS - DIV; /* keep ASG if present */
671: r->tn.lval = w;
672: break;
673: }
674: }
675: }
676: /* the other good case is multiply by a power of two,
677: and thats already being handled in the front end */
678: /*
679: * many multiplies
680: * can be done directly in the hardware:
681: * {SHORT, USHORT, CHAR, UCHAR} x
682: * {SHORT, USHORT, CHAR, UCHAR, ICON}
683: *
684: * so can the corresponding divides.
685: */
686: if (p->in.type != INT && p->in.type != UNSIGNED &&
687: !ISPTR(p->in.type))
688: break;
689: q = p->in.left;
690: if ( isconv(q, SHORT, USHORT ) ) lsize = 2;
691: else if (isconv(q, CHAR, UCHAR )) lsize = 1;
692: else if (q->in.type == SHORT) lsize = 0;
693: else break;
694: if ( isconv(r, SHORT, USHORT ) ||
695: special(r, SSCON) ) rsize = 2;
696: else if (isconv(r, CHAR, UCHAR )) rsize = 1;
697: else break;
698: /* we've looked at both sides and it looks plausable */
699: /* rearrange lhs */
700: if (lsize == 1){
701: /* diddle SCONV, but leave it in place */
702: q->in.type = (q->in.left->tn.type==UCHAR)?USHORT:SHORT;
703: } else if(lsize == 2){
704: p->in.left = q->in.left;
705: q->in.op = FREE;
706: }
707: /* now rearrange rhs */
708: if (rsize == 1){
709: r->in.type = (r->in.left->tn.type==UCHAR)?USHORT:SHORT;
710: } else if (r->tn.op == ICON){
711: r->tn.type = SHORT;
712: } else {
713: p->in.right = r->in.left;
714: r->in.op = FREE;
715: }
716: /*
717: * The result of the mul[us] instructions are ints
718: * anyway, so leave the type of the MUL node alone.
719: * But DIV must be acknowleged as short.
720: */
721: if ( (op==DIV || op== ASG DIV || op==MOD || op==ASG MOD)
722: && p->in.type != SHORT && p->in.type != USHORT){
723: w = (p->in.right->tn.type==SHORT && p->in.left->tn.type==SHORT) ? SHORT : USHORT;
724: q = talloc();
725: *q = *p;
726: p->in.op = SCONV;
727: q->in.type = w;
728: p->in.left = q;
729: p->in.right = 0;
730: }
731: break;
732: case SCONV:
733: /*
734: * conversions from float to double
735: * in a coprocessor register are vacuous
736: */
737: q = p->in.left;
738: if (p->in.type == DOUBLE && q->in.type == FLOAT
739: && q->in.op == REG && iscreg(q->tn.rval)) {
740: TWORD t = p->in.type;
741: *p = *q;
742: p->in.type = t;
743: q->in.op = FREE;
744: return;
745: }
746: /*
747: * John Gilmore memorial hack
748: *
749: * garbage-can case:
750: * if this is a shorten of a simple calculation
751: * whose (2) operands are no larger than the
752: * result type, then we can do the operation more
753: * cheaply, no?
754: * The architypical case looks like:
755: * (SCONV<short> (+<int> (SCONV<int> NAME<short> ) ICON ))
756: * p^ q^ r^
757: */
758: if ( q->in.type!=INT && q->in.type!=UNSIGNED ) return;
759: switch (q->in.op){
760: case PLUS:
761: case MINUS:
762: case MUL:
763: case DIV:
764: case MOD:
765: case LS:
766: case RS:
767: case AND:
768: case OR:
769: case ER:
770: break;
771: default:
772: return;
773: }
774: if ( p->in.type==SHORT || p->in.type==USHORT ){
775: w = 2;
776: v = 0x7fff;
777: }else if ( p->in.type==CHAR || p->in.type==UCHAR ){
778: w = 1;
779: v = 0x7f;
780: }else break;
781: qq = q;
782: r = q->in.right;
783: q = q->in.left;
784: if ( isconv(q, SHORT, USHORT ) ) lsize = 2;
785: else if (isconv(q, CHAR, UCHAR )) lsize = 1;
786: else if (q->in.op == ICON)
787: if (q->tn.name[0] == '\0'
788: && ((q->tn.lval | v)==v || (q->tn.lval|v)==-1))
789: lsize = 0;
790: else break;
791: else if (tlen(q) < sizeof(long)) lsize = -1;
792: else break;
793: if ( isconv(r, SHORT, USHORT ) ) rsize = 2;
794: else if (isconv(r, CHAR, UCHAR )) rsize = 1;
795: else if (r->in.op == ICON)
796: if (r->tn.name[0] == '\0'
797: && ((r->tn.lval | v)==v || (r->tn.lval|v)==-1))
798: rsize = 0;
799: else break;
800: else if (tlen(r) < sizeof(long)) rsize = -1;
801: else break;
802: if (lsize == -1) {
803: NODE *t = talloc();
804: t->in.op = SCONV;
805: t->in.type = qq->in.type;
806: t->in.left = q;
807: lsize = tlen(q);
808: q = t;
809: qq->in.left = q;
810: }
811: if (rsize == -1) {
812: NODE *t = talloc();
813: t->in.op = SCONV;
814: t->in.type = qq->in.type;
815: t->in.left = r;
816: rsize = tlen(r);
817: r = t;
818: qq->in.right = r;
819: }
820: if (rsize > w || lsize > w) {
821: /* must preserve top SCONV, but weaken operation */
822: p = p->in.left;
823: if (rsize >lsize){
824: p->in.type = r->in.left->in.type ;
825: w = rsize;
826: } else {
827: p->in.type = q->in.left->in.type;
828: w = lsize;
829: }
830: } else {
831: /* clobber SCONV */
832: NODE * t = p->in.left;
833: TWORD tt = p->in.type;
834: *p = *t; /* paint over */
835: p->in.type = tt; /* except type */
836: t->in.op = FREE; /* give a node back */
837: }
838: /* now weaken or elide child convs */
839: switch (lsize){
840: case 0: /* ICON -- diddle type */
841: q->in.type = p->in.type; break;
842: case 1: /* char */
843: if (lsize <w){
844: /* retain SCONV but weaken */
845: q->in.type = p->in.type; break;
846: }
847: /* else fall through */
848: case 2: /* same size -- elide SCONV */
849: { NODE * t = q->in.left;
850: *q = *t;
851: t->in.op = FREE;
852: }
853: }
854: switch (rsize){
855: case 0: /* ICON -- diddle type */
856: r->in.type = p->in.type; break;
857: case 1: /* char */
858: if (rsize <w){
859: /* retain SCONV but weaken */
860: r->in.type = p->in.type; break;
861: }
862: /* else fall through */
863: case 2: /* same size -- elide SCONV */
864: { NODE * t = r->in.left;
865: *r = *t;
866: t->in.op = FREE;
867: }
868: }
869: break;
870: case CHK:
871: /*
872: * A CHK with constant bounds, of which the left-hand-side
873: * is an SCONV that widens a shorter type can be converted
874: * to an SCONV over a CHK. This lets us use weaker CHK
875: * instructions.
876: */
877: if (p->in.type != INT && p->in.type != UNSIGNED) break;
878: q = p->in.left;
879: if (!isconv(q, CHAR, UCHAR) && !isconv(q, SHORT, USHORT) )break;
880: r = p->in.right;
881: rr = r->in.right;
882: rl = r->in.left;
883: if (rr->in.op != ICON || rl->in.op != ICON) break;
884: /*
885: * make bounds smaller using the type of the
886: * converted operand
887: */
888: t = q->in.left->in.type;
889: switch(t) {
890: case CHAR:
891: if (reduce_bounds(-128, 127, rl, rr))
892: goto delete_check;
893: break;
894: case UCHAR:
895: if (reduce_bounds(0, 255, rl, rr))
896: goto delete_check;
897: break;
898: case SHORT:
899: if (reduce_bounds(-32768, 32767, rl, rr))
900: goto delete_check;
901: break;
902: case USHORT:
903: if (reduce_bounds(0, 65535, rl, rr))
904: goto delete_check;
905: break;
906: delete_check:
907: *p = *q;
908: q->in.op = FREE;
909: tfree(r);
910: return;
911: }
912: /*
913: * weaken the conversion by
914: * exchanging CHK and SCONV nodes
915: */
916: *p = *q; /* p becomes SCONV node */
917: p->in.left = q;
918: q->in.op = CHK;
919: q->in.right = r;
920: q->in.type = r->in.type = rl->tn.type = rr->tn.type = t;
921: break;
922:
923: case INIT:
924: /*
925: * not an optimization, but prevents an
926: * infinite loop later on in code generation...
927: */
928: q = p->in.left;
929: if (q->in.op != ICON && q->in.op != FCON) {
930: uerror("Illegal initialization");
931: tfree(q);
932: q = talloc();
933: q->in.type = p->in.type;
934: if (ISFLOATING(p->in.type)) {
935: q->in.op = FCON;
936: q->fpn.dval = 0.0;
937: } else {
938: q->in.op = ICON;
939: q->tn.name = "";
940: q->tn.lval = 0;
941: }
942: p->in.left = q;
943: }
944: break;
945:
946: case FORCE:
947: /*
948: * if the type of a FORCE op is {u}char or {u}short,
949: * extend it into an INT.
950: */
951: switch(p->in.type){
952: case CHAR:
953: case UCHAR:
954: case SHORT:
955: case USHORT:
956: q = talloc();
957: q->in.op = SCONV;
958: q->in.type = INT;
959: q->in.left = p->in.left;
960: q->in.right = NULL;
961: p->in.left = q;
962: p->in.type = INT;
963: break;
964: }
965: break;
966:
967: } /* switch */
968: }
969:
970: /*
971: * reduce bounds of a range check using
972: * the known bounds of the domain type
973: */
974: int
975: reduce_bounds(domain_min, domain_max, range_min, range_max)
976: register CONSZ domain_min, domain_max;
977: register NODE *range_min, *range_max;
978: {
979: /* do the domain and range intersect? */
980: if (domain_min > range_max->tn.lval || domain_max < range_min->tn.lval) {
981: /* expression value is known to lie outside required range */
982: werror("expression value is out of range");
983: }
984: /* range := intersection(range, domain) */
985: if (domain_min > range_min->tn.lval)
986: range_min->tn.lval = domain_min;
987: if (domain_max < range_max->tn.lval)
988: range_max->tn.lval = domain_max;
989: /* if domain is a subset of range, range check is unnecessary */
990: if (domain_min >= range_min->tn.lval && domain_max <= range_max->tn.lval) {
991: return(1);
992: }
993: return(0);
994: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.