|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)optim.c 5.3 (Berkeley) 3/9/86"; ! 9: #endif not lint ! 10: ! 11: /* ! 12: * optim.c ! 13: * ! 14: * Miscellaneous optimizer routines, f77 compiler pass 1. ! 15: * ! 16: * UCSD Chemistry modification history: ! 17: * ! 18: * $Log: optim.c,v $ ! 19: * Revision 5.2 86/03/04 17:47:08 donn ! 20: * Change buffcat() and buffct1() analogously to putcat and putct1() -- ! 21: * ensure that memoffset is evaluated before vleng. Take care not to ! 22: * screw up and return something other than an expression. ! 23: * ! 24: * Revision 5.1 85/08/10 03:48:42 donn ! 25: * 4.3 alpha ! 26: * ! 27: * Revision 2.12 85/06/08 22:57:01 donn ! 28: * Prevent core dumps -- bug in optinsert was causing lastslot to be wrong ! 29: * when a slot was inserted at the end of the buffer. ! 30: * ! 31: * Revision 2.11 85/03/18 08:05:05 donn ! 32: * Prevent warnings about implicit conversions. ! 33: * ! 34: * Revision 2.10 85/02/12 20:13:00 donn ! 35: * Resurrected the hack in 2.6.1.1 to avoid creating a temporary when ! 36: * there is a concatenation on the rhs of an assignment, and threw out ! 37: * all the code dealing with starcat(). It seems that we can't use a ! 38: * temporary because the lhs as well as the rhs may have nonconstant length. ! 39: * ! 40: * Revision 2.9 85/01/18 00:53:52 donn ! 41: * Missed a call to free() in the last change... ! 42: * ! 43: * Revision 2.8 85/01/18 00:50:03 donn ! 44: * Fixed goof made when modifying buffmnmx() to explicitly call expand(). ! 45: * ! 46: * Revision 2.7 85/01/15 18:47:35 donn ! 47: * Changes to allow character*(*) variables to appear in concatenations in ! 48: * the rhs of an assignment statement. ! 49: * ! 50: * Revision 2.6 84/12/16 21:46:27 donn ! 51: * Fixed bug that prevented concatenations from being run together. Changed ! 52: * buffpower() to not touch exponents greater than 64 -- let putpower do them. ! 53: * ! 54: * Revision 2.5 84/10/29 08:41:45 donn ! 55: * Added hack to flushopt() to prevent the compiler from trying to generate ! 56: * intermediate code after an error. ! 57: * ! 58: * Revision 2.4 84/08/07 21:28:00 donn ! 59: * Removed call to p2flush() in putopt() -- this allows us to make better use ! 60: * of the buffering on the intermediate code file. ! 61: * ! 62: * Revision 2.3 84/08/01 16:06:24 donn ! 63: * Forced expand() to expand subscripts. ! 64: * ! 65: * Revision 2.2 84/07/19 20:21:55 donn ! 66: * Decided I liked the expression tree algorithm after all. The algorithm ! 67: * which repeatedly squares temporaries is now checked in as rev. 2.1. ! 68: * ! 69: * Revision 1.3.1.1 84/07/10 14:18:18 donn ! 70: * I'm taking this branch off the trunk -- it works but it's not as good as ! 71: * the old version would be if it worked right. ! 72: * ! 73: * Revision 1.5 84/07/09 22:28:50 donn ! 74: * Added fix to buffpower() to prevent it chasing after huge exponents. ! 75: * ! 76: * Revision 1.4 84/07/09 20:13:59 donn ! 77: * Replaced buffpower() routine with a new one that generates trees which can ! 78: * be handled by CSE later on. ! 79: * ! 80: * Revision 1.3 84/05/04 21:02:07 donn ! 81: * Added fix for a bug in buffpower() that caused func(x)**2 to turn into ! 82: * func(x) * func(x). This bug had already been fixed in putpower()... ! 83: * ! 84: * Revision 1.2 84/03/23 22:47:21 donn ! 85: * The subroutine argument temporary fixes from Bob Corbett didn't take into ! 86: * account the fact that the code generator collects all the assignments to ! 87: * temporaries at the start of a statement -- hence the temporaries need to ! 88: * be initialized once per statement instead of once per call. ! 89: * ! 90: */ ! 91: ! 92: #include "defs.h" ! 93: #include "optim.h" ! 94: ! 95: ! 96: ! 97: /* ! 98: * Information buffered for each slot type ! 99: * ! 100: * slot type expptr integer pointer ! 101: * ! 102: * IFN expr label - ! 103: * GOTO - label - ! 104: * LABEL - label - ! 105: * EQ expr - - ! 106: * CALL expr - - ! 107: * CMGOTO expr num labellist* ! 108: * STOP expr - - ! 109: * DOHEAD [1] - ctlframe* ! 110: * ENDDO [1] - ctlframe* ! 111: * ARIF expr - labellist* ! 112: * RETURN expr label - ! 113: * ASGOTO expr - labellist* ! 114: * PAUSE expr - - ! 115: * ASSIGN expr label - ! 116: * SKIOIFN expr label - ! 117: * SKFRTEMP expr - - ! 118: * ! 119: * Note [1]: the nullslot field is a pointer to a fake slot which is ! 120: * at the end of the slots which may be replaced by this slot. In ! 121: * other words, it looks like this: ! 122: * DOHEAD slot ! 123: * slot \ ! 124: * slot > ordinary IF, GOTO, LABEL slots which implement the DO ! 125: * slot / ! 126: * NULL slot ! 127: */ ! 128: ! 129: ! 130: expptr expand(); ! 131: ! 132: Slotp firstslot = NULL; ! 133: Slotp lastslot = NULL; ! 134: int numslots = 0; ! 135: ! 136: ! 137: /* ! 138: * turns off optimization option ! 139: */ ! 140: ! 141: optoff() ! 142: ! 143: { ! 144: flushopt(); ! 145: optimflag = 0; ! 146: } ! 147: ! 148: ! 149: ! 150: /* ! 151: * initializes the code buffer for optimization ! 152: */ ! 153: ! 154: setopt() ! 155: ! 156: { ! 157: register Slotp sp; ! 158: ! 159: for (sp = firstslot; sp; sp = sp->next) ! 160: free ( (charptr) sp); ! 161: firstslot = lastslot = NULL; ! 162: numslots = 0; ! 163: } ! 164: ! 165: ! 166: ! 167: /* ! 168: * flushes the code buffer ! 169: */ ! 170: ! 171: LOCAL int alreadycalled = 0; ! 172: ! 173: flushopt() ! 174: { ! 175: register Slotp sp; ! 176: int savelineno; ! 177: ! 178: if (alreadycalled) return; /* to prevent recursive call during errors */ ! 179: alreadycalled = 1; ! 180: ! 181: if (debugflag[1]) ! 182: showbuffer (); ! 183: ! 184: frtempbuff (); ! 185: ! 186: savelineno = lineno; ! 187: for (sp = firstslot; sp; sp = sp->next) ! 188: { ! 189: if (nerr == 0) ! 190: putopt (sp); ! 191: else ! 192: frexpr (sp->expr); ! 193: if(sp->ctlinfo) free ( (charptr) sp->ctlinfo); ! 194: free ( (charptr) sp); ! 195: numslots--; ! 196: } ! 197: firstslot = lastslot = NULL; ! 198: numslots = 0; ! 199: clearbb(); ! 200: lineno = savelineno; ! 201: ! 202: alreadycalled = 0; ! 203: } ! 204: ! 205: ! 206: ! 207: /* ! 208: * puts out code for the given slot (from the code buffer) ! 209: */ ! 210: ! 211: LOCAL putopt (sp) ! 212: register Slotp sp; ! 213: { ! 214: lineno = sp->lineno; ! 215: switch (sp->type) { ! 216: case SKNULL: ! 217: break; ! 218: case SKIFN: ! 219: case SKIOIFN: ! 220: putif(sp->expr, sp->label); ! 221: break; ! 222: case SKGOTO: ! 223: putgoto(sp->label); ! 224: break; ! 225: case SKCMGOTO: ! 226: putcmgo(sp->expr, sp->label, sp->ctlinfo); ! 227: break; ! 228: case SKCALL: ! 229: putexpr(sp->expr); ! 230: break; ! 231: case SKSTOP: ! 232: putexpr (call1 (TYSUBR, "s_stop", sp->expr)); ! 233: break; ! 234: case SKPAUSE: ! 235: putexpr (call1 (TYSUBR, "s_paus", sp->expr)); ! 236: break; ! 237: case SKASSIGN: ! 238: puteq (sp->expr, ! 239: intrconv(sp->expr->headblock.vtype, mkaddcon(sp->label))); ! 240: break; ! 241: case SKDOHEAD: ! 242: case SKENDDO: ! 243: break; ! 244: case SKEQ: ! 245: putexpr(sp->expr); ! 246: break; ! 247: case SKARIF: ! 248: #define LM ((struct Labelblock * *)sp->ctlinfo)[0]->labelno ! 249: #define LZ ((struct Labelblock * *)sp->ctlinfo)[1]->labelno ! 250: #define LP ((struct Labelblock * *)sp->ctlinfo)[2]->labelno ! 251: prarif(sp->expr, LM, LZ, LP); ! 252: break; ! 253: case SKASGOTO: ! 254: putbranch((Addrp) sp->expr); ! 255: break; ! 256: case SKLABEL: ! 257: putlabel(sp->label); ! 258: break; ! 259: case SKRETURN: ! 260: if (sp->expr) ! 261: { ! 262: putforce(TYINT, sp->expr); ! 263: putgoto(sp->label); ! 264: } ! 265: else ! 266: putgoto(sp->label); ! 267: break; ! 268: case SKFRTEMP: ! 269: templist = mkchain (sp->expr,templist); ! 270: break; ! 271: default: ! 272: badthing("SKtype", "putopt", sp->type); ! 273: break; ! 274: } ! 275: ! 276: /* ! 277: * Recycle argument temporaries here. This must get done on a ! 278: * statement-by-statement basis because the code generator ! 279: * makes side effects happen at the start of a statement. ! 280: */ ! 281: argtemplist = hookup(argtemplist, activearglist); ! 282: activearglist = CHNULL; ! 283: } ! 284: ! 285: ! 286: ! 287: /* ! 288: * copies one element of the control stack ! 289: */ ! 290: ! 291: LOCAL struct Ctlframe *cpframe(p) ! 292: register char *p; ! 293: { ! 294: static int size = sizeof (struct Ctlframe); ! 295: register int n; ! 296: register char *q; ! 297: struct Ctlframe *q0; ! 298: ! 299: q0 = ALLOC(Ctlframe); ! 300: q = (char *) q0; ! 301: n = size; ! 302: while(n-- > 0) ! 303: *q++ = *p++; ! 304: return( q0); ! 305: } ! 306: ! 307: ! 308: ! 309: /* ! 310: * copies an array of labelblock pointers ! 311: */ ! 312: ! 313: LOCAL struct Labelblock **cplabarr(n,arr) ! 314: struct Labelblock *arr[]; ! 315: int n; ! 316: { ! 317: struct Labelblock **newarr; ! 318: register char *in, *out; ! 319: register int i,j; ! 320: ! 321: newarr = (struct Labelblock **) ckalloc (n * sizeof (char *)); ! 322: for (i = 0; i < n; i++) ! 323: { ! 324: newarr[i] = ALLOC (Labelblock); ! 325: out = (char *) newarr[i]; ! 326: in = (char *) arr[i]; ! 327: j = sizeof (struct Labelblock); ! 328: while (j-- > 0) ! 329: *out++ = *in++; ! 330: } ! 331: return (newarr); ! 332: } ! 333: ! 334: ! 335: ! 336: /* ! 337: * creates a new slot in the code buffer ! 338: */ ! 339: ! 340: LOCAL Slotp newslot() ! 341: { ! 342: register Slotp sp; ! 343: ! 344: ++numslots; ! 345: sp = ALLOC( slt ); ! 346: sp->next = NULL ; ! 347: if (lastslot) ! 348: { ! 349: sp->prev = lastslot; ! 350: lastslot = lastslot->next = sp; ! 351: } ! 352: else ! 353: { ! 354: firstslot = lastslot = sp; ! 355: sp->prev = NULL; ! 356: } ! 357: sp->lineno = lineno; ! 358: return (sp); ! 359: } ! 360: ! 361: ! 362: ! 363: /* ! 364: * removes (but not deletes) the specified slot from the code buffer ! 365: */ ! 366: ! 367: removeslot (sl) ! 368: Slotp sl; ! 369: ! 370: { ! 371: if (sl->next) ! 372: sl->next->prev = sl->prev; ! 373: else ! 374: lastslot = sl->prev; ! 375: if (sl->prev) ! 376: sl->prev->next = sl->next; ! 377: else ! 378: firstslot = sl->next; ! 379: sl->next = sl->prev = NULL; ! 380: ! 381: --numslots; ! 382: } ! 383: ! 384: ! 385: ! 386: /* ! 387: * inserts slot s1 before existing slot s2 in the code buffer; ! 388: * appends to end of list if s2 is NULL. ! 389: */ ! 390: ! 391: insertslot (s1,s2) ! 392: Slotp s1,s2; ! 393: ! 394: { ! 395: if (s2) ! 396: { ! 397: if (s2->prev) ! 398: s2->prev->next = s1; ! 399: else ! 400: firstslot = s1; ! 401: s1->prev = s2->prev; ! 402: s2->prev = s1; ! 403: } ! 404: else ! 405: { ! 406: s1->prev = lastslot; ! 407: lastslot->next = s1; ! 408: lastslot = s1; ! 409: } ! 410: s1->next = s2; ! 411: ! 412: ++numslots; ! 413: } ! 414: ! 415: ! 416: ! 417: /* ! 418: * deletes the specified slot from the code buffer ! 419: */ ! 420: ! 421: delslot (sl) ! 422: Slotp sl; ! 423: ! 424: { ! 425: removeslot (sl); ! 426: ! 427: if (sl->ctlinfo) ! 428: free ((charptr) sl->ctlinfo); ! 429: frexpr (sl->expr); ! 430: free ((charptr) sl); ! 431: numslots--; ! 432: } ! 433: ! 434: ! 435: ! 436: /* ! 437: * inserts a slot before the specified slot; if given NULL, it is ! 438: * inserted at the end of the buffer ! 439: */ ! 440: ! 441: Slotp optinsert (type,p,l,c,currslot) ! 442: int type; ! 443: expptr p; ! 444: int l; ! 445: int *c; ! 446: Slotp currslot; ! 447: ! 448: { ! 449: Slotp savelast,new; ! 450: ! 451: savelast = lastslot; ! 452: if (currslot) ! 453: lastslot = currslot->prev; ! 454: new = optbuff (type,p,l,c); ! 455: new->next = currslot; ! 456: if (currslot) ! 457: currslot->prev = new; ! 458: new->lineno = -1; /* who knows what the line number should be ??!! */ ! 459: if (currslot) ! 460: lastslot = savelast; ! 461: return (new); ! 462: } ! 463: ! 464: ! 465: ! 466: /* ! 467: * buffers the FRTEMP slots which have been waiting ! 468: */ ! 469: ! 470: frtempbuff () ! 471: ! 472: { ! 473: chainp ht; ! 474: register Slotp sp; ! 475: ! 476: for (ht = holdtemps; ht; ht = ht->nextp) ! 477: { ! 478: sp = newslot(); ! 479: /* this slot actually belongs to some previous source line */ ! 480: sp->lineno = sp->lineno - 1; ! 481: sp->type = SKFRTEMP; ! 482: sp->expr = (expptr) ht->datap; ! 483: sp->label = 0; ! 484: sp->ctlinfo = NULL; ! 485: } ! 486: holdtemps = NULL; ! 487: } ! 488: ! 489: ! 490: ! 491: /* ! 492: * puts the given information into a slot at the end of the code buffer ! 493: */ ! 494: ! 495: Slotp optbuff (type,p,l,c) ! 496: int type; ! 497: expptr p; ! 498: int l; ! 499: int *c; ! 500: ! 501: { ! 502: register Slotp sp; ! 503: ! 504: if (debugflag[1]) ! 505: { ! 506: fprintf (diagfile,"-----optbuff-----"); showslottype (type); ! 507: showexpr (p,0); fprintf (diagfile,"\n"); ! 508: } ! 509: ! 510: p = expand (p); ! 511: sp = newslot(); ! 512: sp->type = type; ! 513: sp->expr = p; ! 514: sp->label = l; ! 515: sp->ctlinfo = NULL; ! 516: switch (type) ! 517: { ! 518: case SKCMGOTO: ! 519: sp->ctlinfo = (int*) cplabarr (l, (struct Labelblock**) c); ! 520: break; ! 521: case SKARIF: ! 522: sp->ctlinfo = (int*) cplabarr (3, (struct Labelblock**) c); ! 523: break; ! 524: case SKDOHEAD: ! 525: case SKENDDO: ! 526: sp->ctlinfo = (int*) cpframe ((struct Ctlframe*) c); ! 527: break; ! 528: default: ! 529: break; ! 530: } ! 531: ! 532: frtempbuff (); ! 533: ! 534: return (sp); ! 535: } ! 536: ! 537: ! 538: ! 539: /* ! 540: * expands the given expression, if possible (e.g., concat, min, max, etc.); ! 541: * also frees temporaries when they are indicated as being the last use ! 542: */ ! 543: ! 544: #define APPEND(z) \ ! 545: res = res->exprblock.rightp = mkexpr (OPCOMMA, z, newtemp) ! 546: ! 547: LOCAL expptr expand (p) ! 548: tagptr p; ! 549: ! 550: { ! 551: Addrp t; ! 552: expptr q; ! 553: expptr buffmnmx(), buffpower(), buffcat(); ! 554: ! 555: if (!p) ! 556: return (ENULL); ! 557: switch (p->tag) ! 558: { ! 559: case TEXPR: ! 560: switch (p->exprblock.opcode) ! 561: { ! 562: case OPASSIGN: /* handle a = b // c */ ! 563: if (p->exprblock.vtype != TYCHAR) ! 564: goto standard; ! 565: q = p->exprblock.rightp; ! 566: if (!(q->tag == TEXPR && ! 567: q->exprblock.opcode == OPCONCAT)) ! 568: goto standard; ! 569: t = (Addrp) expand(p->exprblock.leftp); ! 570: frexpr(p->exprblock.vleng); ! 571: free( (charptr) p ); ! 572: p = (tagptr) q; ! 573: goto cat; ! 574: case OPCONCAT: ! 575: t = mktemp (TYCHAR, ICON(lencat(p))); ! 576: cat: ! 577: q = (expptr) cpexpr (p->exprblock.vleng); ! 578: p = (tagptr) buffcat (t, p); ! 579: frexpr (p->headblock.vleng); ! 580: p->headblock.vleng = q; ! 581: break; ! 582: case OPMIN: ! 583: case OPMAX: ! 584: p = (tagptr) buffmnmx (p); ! 585: break; ! 586: case OPPOWER: ! 587: p = (tagptr) buffpower (p); ! 588: break; ! 589: default: ! 590: standard: ! 591: p->exprblock.leftp = ! 592: expand (p->exprblock.leftp); ! 593: if (p->exprblock.rightp) ! 594: p->exprblock.rightp = ! 595: expand (p->exprblock.rightp); ! 596: break; ! 597: } ! 598: break; ! 599: ! 600: case TLIST: ! 601: { ! 602: chainp t; ! 603: for (t = p->listblock.listp; t; t = t->nextp) ! 604: t->datap = (tagptr) expand (t->datap); ! 605: } ! 606: break; ! 607: ! 608: case TTEMP: ! 609: if (p->tempblock.istemp) ! 610: frtemp(p); ! 611: break; ! 612: ! 613: case TADDR: ! 614: p->addrblock.memoffset = expand( p->addrblock.memoffset ); ! 615: break; ! 616: ! 617: default: ! 618: break; ! 619: } ! 620: return ((expptr) p); ! 621: } ! 622: ! 623: ! 624: ! 625: /* ! 626: * local version of routine putcat in putpcc.c, called by expand ! 627: */ ! 628: ! 629: LOCAL expptr buffcat(lhs, rhs) ! 630: register Addrp lhs; ! 631: register expptr rhs; ! 632: { ! 633: int n; ! 634: Addrp lp, cp; ! 635: expptr ep, buffct1(); ! 636: ! 637: n = ncat(rhs); ! 638: lp = (Addrp) mkaltmpn(n, TYLENG, PNULL); ! 639: cp = (Addrp) mkaltmpn(n, TYADDR, PNULL); ! 640: ! 641: n = 0; ! 642: ep = buffct1(rhs, lp, cp, &n); ! 643: ! 644: ep = mkexpr(OPCOMMA, ep, ! 645: call4(TYSUBR, "s_cat", lhs, cp, lp, mkconv(TYLONG, ICON(n)))); ! 646: ! 647: return (ep); ! 648: } ! 649: ! 650: ! 651: ! 652: /* ! 653: * local version of routine putct1 in putpcc.c, called by expand ! 654: */ ! 655: ! 656: LOCAL expptr buffct1(q, lp, cp, ip) ! 657: register expptr q; ! 658: register Addrp lp, cp; ! 659: int *ip; ! 660: { ! 661: int i; ! 662: Addrp lp1, cp1; ! 663: expptr eleft, eright; ! 664: ! 665: if(q->tag==TEXPR && q->exprblock.opcode==OPCONCAT) ! 666: { ! 667: eleft = buffct1(q->exprblock.leftp, lp, cp, ip); ! 668: eright = buffct1(q->exprblock.rightp, lp, cp, ip); ! 669: frexpr(q->exprblock.vleng); ! 670: free( (charptr) q ); ! 671: } ! 672: else ! 673: { ! 674: i = (*ip)++; ! 675: cp1 = (Addrp) cpexpr(cp); ! 676: cp1->memoffset = mkexpr(OPPLUS, cp1->memoffset, ICON(i*SZADDR)); ! 677: lp1 = (Addrp) cpexpr(lp); ! 678: lp1->memoffset = mkexpr(OPPLUS, lp1->memoffset, ICON(i*SZLENG)); ! 679: eleft = mkexpr(OPASSIGN, cp1, addrof(expand(cpexpr(q)))); ! 680: eright = mkexpr(OPASSIGN, lp1, cpexpr(q->headblock.vleng)); ! 681: frexpr(q); ! 682: } ! 683: return (mkexpr(OPCOMMA, eleft, eright)); ! 684: } ! 685: ! 686: ! 687: ! 688: /* ! 689: * local version of routine putmnmx in putpcc.c, called by expand ! 690: */ ! 691: ! 692: LOCAL expptr buffmnmx(p) ! 693: register expptr p; ! 694: { ! 695: int op, type; ! 696: expptr qp; ! 697: chainp p0, p1; ! 698: Addrp sp, tp; ! 699: Addrp newtemp; ! 700: expptr result, res; ! 701: ! 702: if(p->tag != TEXPR) ! 703: badtag("buffmnmx", p->tag); ! 704: ! 705: type = p->exprblock.vtype; ! 706: op = (p->exprblock.opcode==OPMIN ? OPLT : OPGT ); ! 707: qp = expand(p->exprblock.leftp); ! 708: if(qp->tag != TLIST) ! 709: badtag("buffmnmx list", qp->tag); ! 710: p0 = qp->listblock.listp; ! 711: free( (charptr) qp ); ! 712: free( (charptr) p ); ! 713: ! 714: sp = mktemp(type, PNULL); ! 715: tp = mktemp(type, PNULL); ! 716: qp = mkexpr(OPCOLON, cpexpr(tp), cpexpr(sp)); ! 717: qp = mkexpr(OPQUEST, mkexpr(op, cpexpr(tp),cpexpr(sp)), qp); ! 718: qp = fixexpr(qp); ! 719: ! 720: newtemp = mktemp (type,PNULL); ! 721: ! 722: result = res = mkexpr (OPCOMMA, ! 723: mkexpr( OPASSIGN, cpexpr(sp), p0->datap ), cpexpr(newtemp)); ! 724: ! 725: for(p1 = p0->nextp ; p1 ; p1 = p1->nextp) ! 726: { ! 727: APPEND (mkexpr( OPASSIGN, cpexpr(tp), p1->datap )); ! 728: if(p1->nextp) ! 729: APPEND (mkexpr (OPASSIGN, cpexpr(sp), cpexpr(qp)) ); ! 730: else ! 731: APPEND (mkexpr (OPASSIGN, cpexpr(newtemp), qp)); ! 732: } ! 733: ! 734: frtemp(sp); ! 735: frtemp(tp); ! 736: frtemp(newtemp); ! 737: frchain( &p0 ); ! 738: ! 739: return (result); ! 740: } ! 741: ! 742: ! 743: ! 744: /* ! 745: * Called by expand() to eliminate exponentiations to integer constants. ! 746: */ ! 747: LOCAL expptr buffpower( p ) ! 748: expptr p; ! 749: { ! 750: expptr base; ! 751: Addrp newtemp; ! 752: expptr storetemp = ENULL; ! 753: expptr powtree(); ! 754: expptr result; ! 755: ftnint exp; ! 756: ! 757: if ( ! ISICON( p->exprblock.rightp ) ) ! 758: fatal( "buffpower: bad non-integer exponent" ); ! 759: ! 760: base = expand(p->exprblock.leftp); ! 761: exp = p->exprblock.rightp->constblock.const.ci; ! 762: if ( exp < 2 ) ! 763: fatal( "buffpower: bad exponent less than 2" ); ! 764: ! 765: if ( exp > 64 ) { ! 766: /* ! 767: * Let's be reasonable, here... Let putpower() do the job. ! 768: */ ! 769: p->exprblock.leftp = base; ! 770: return ( p ); ! 771: } ! 772: ! 773: /* ! 774: * If the base is not a simple variable, evaluate it and copy the ! 775: * result into a temporary. ! 776: */ ! 777: if ( ! (base->tag == TADDR && ISCONST( base->addrblock.memoffset )) ) { ! 778: newtemp = mktemp( base->headblock.vtype, PNULL ); ! 779: storetemp = mkexpr( OPASSIGN, ! 780: cpexpr( (expptr) newtemp ), ! 781: cpexpr( base ) ); ! 782: base = (expptr) newtemp; ! 783: } ! 784: ! 785: result = powtree( base, exp ); ! 786: ! 787: if ( storetemp != ENULL ) ! 788: result = mkexpr( OPCOMMA, storetemp, result ); ! 789: frexpr( p ); ! 790: ! 791: return ( result ); ! 792: } ! 793: ! 794: ! 795: ! 796: /* ! 797: * powtree( base, exp ) -- Create a tree of multiplications which computes ! 798: * base ** exp. The tree is built so that CSE will compact it if ! 799: * possible. The routine works by creating subtrees that compute ! 800: * exponents which are powers of two, then multiplying these ! 801: * together to get the result; this gives a log2( exp ) tree depth ! 802: * and lots of subexpressions which can be eliminated. ! 803: */ ! 804: LOCAL expptr powtree( base, exp ) ! 805: expptr base; ! 806: register ftnint exp; ! 807: { ! 808: register expptr r = ENULL, r1; ! 809: register int i; ! 810: ! 811: for ( i = 0; exp; ++i, exp >>= 1 ) ! 812: if ( exp & 1 ) ! 813: if ( i == 0 ) ! 814: r = (expptr) cpexpr( base ); ! 815: else { ! 816: r1 = powtree( base, 1 << (i - 1) ); ! 817: r1 = mkexpr( OPSTAR, r1, cpexpr( r1 ) ); ! 818: r = (r ? mkexpr( OPSTAR, r1, r ) : r1); ! 819: } ! 820: ! 821: return ( r ); ! 822: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.