|
|
1.1 ! root 1: #include "defs.h" ! 2: #include "optim.h" ! 3: ! 4: ! 5: #define SCFREE 0 ! 6: #define SCSAFE 1 ! 7: ! 8: ! 9: ! 10: typedef ! 11: struct varblock ! 12: { ! 13: struct varblock *next; ! 14: field vstg; ! 15: int memno; /* holds memalloc for TTEMP */ ! 16: short sets; ! 17: short uses; ! 18: field setfirst; ! 19: } VARBLOCK; ! 20: ! 21: typedef VARBLOCK *Varp; ! 22: ! 23: #define TABLESIZE 59 ! 24: ! 25: LOCAL Varp table[TABLESIZE]; ! 26: ! 27: ! 28: ! 29: LOCAL Varp mkbucket(vstg,memno) ! 30: field vstg; ! 31: int memno; ! 32: ! 33: { ! 34: Varp q; ! 35: ! 36: q = ALLOC(varblock); ! 37: q->vstg = vstg; ! 38: q->memno = memno; ! 39: return q; ! 40: } ! 41: ! 42: ! 43: ! 44: LOCAL Varp lookup(p) ! 45: tagptr p; ! 46: ! 47: { ! 48: int vstg, memno; ! 49: int key; ! 50: Varp q, r; ! 51: ! 52: switch (p->tag) ! 53: { ! 54: case TTEMP: ! 55: vstg = 0; ! 56: memno = (int) p->tempblock.memalloc; ! 57: break; ! 58: ! 59: case TADDR: ! 60: vstg = p->addrblock.vstg; ! 61: memno = p->addrblock.memno; ! 62: break; ! 63: ! 64: default: ! 65: badtag ("lookup",p->tag); ! 66: } ! 67: key = memno % TABLESIZE; ! 68: q = table[key]; ! 69: ! 70: if (q) ! 71: { ! 72: for (; q; r = q, q = q->next) ! 73: if ((q->vstg == vstg) && (q->memno == memno)) ! 74: return q; ! 75: return r->next = mkbucket(vstg,memno); ! 76: } ! 77: else ! 78: return table[key] = mkbucket(vstg,memno); ! 79: } ! 80: ! 81: ! 82: ! 83: LOCAL freetable() ! 84: ! 85: { ! 86: int i; ! 87: Varp p, q; ! 88: ! 89: for (i = 0; i < TABLESIZE; i++) ! 90: if (table[i]) ! 91: { ! 92: p = table[i]; ! 93: table[i] = NULL; ! 94: ! 95: while (p) ! 96: { ! 97: q = p->next; ! 98: free((char *) p); ! 99: p = q; ! 100: } ! 101: } ! 102: } ! 103: ! 104: ! 105: ! 106: Slotp newcode; ! 107: Slotp dohead, doend; ! 108: LOCAL Slotp first, last; ! 109: LOCAL commonset; ! 110: LOCAL int comocount; /* count of number of code motions done */ ! 111: ! 112: ! 113: optloops() ! 114: ! 115: { ! 116: int match; ! 117: Slotp nextslot; ! 118: Slotp sl1,sl2; ! 119: Slotp lastlabslot; ! 120: int lab; ! 121: ! 122: if (! optimflag) return; ! 123: if (debugflag[6]) return; ! 124: ! 125: lastlabslot = NULL; ! 126: comocount = 0; ! 127: for (sl1 = firstslot; sl1; sl1 = nextslot) ! 128: { ! 129: nextslot = sl1->next; ! 130: switch (sl1->type) ! 131: { ! 132: case SKLABEL: ! 133: lastlabslot = sl1; ! 134: break; ! 135: ! 136: case SKGOTO: ! 137: if (lastlabslot && sl1->label == lastlabslot->label) ! 138: { ! 139: lab = newlabel (); ! 140: first = optinsert (SKLABEL,0,lab,0,lastlabslot->next); ! 141: last = sl1; ! 142: last->label = lab; ! 143: optloop (); ! 144: } ! 145: break; ! 146: ! 147: case SKDOHEAD: ! 148: match = 0; ! 149: for (sl2 = sl1; sl2; sl2 = sl2->next) ! 150: { ! 151: if (sl2->type == SKDOHEAD) match++; ! 152: else if (sl2->type == SKENDDO) match--; ! 153: if (match == 0) break; ! 154: } ! 155: if (sl2) ! 156: last = sl2; ! 157: else ! 158: fatal ("unmatched do in code buffer"); ! 159: if (sl2->type != SKENDDO) ! 160: fatal ("internal error in optloops"); ! 161: ! 162: /* last now points to the SKENDDO slot; the SKNULL slot ! 163: * is reached through last->nullslot ! 164: */ ! 165: last = (Slotp) last->nullslot; ! 166: ! 167: first = sl1; ! 168: ! 169: optloop (); ! 170: break; ! 171: ! 172: default: ! 173: break; ! 174: } ! 175: } ! 176: ! 177: if (debugflag[0]) ! 178: fprintf (diagfile,"%d code motion%s performed\n",comocount, ! 179: (comocount==1 ? "" : "s") ); ! 180: return; ! 181: } ! 182: ! 183: ! 184: ! 185: optloop() ! 186: ! 187: { ! 188: newcode = NULL; ! 189: ! 190: modify(); ! 191: ! 192: return; ! 193: } ! 194: ! 195: ! 196: LOCAL modify() ! 197: ! 198: { ! 199: Slotp sp; ! 200: int s; ! 201: ! 202: scanvars(); ! 203: ! 204: for (sp = first; sp != last->next; sp = sp->next) ! 205: switch (sp->type) ! 206: { ! 207: case SKEQ: ! 208: s = anex(sp->expr); ! 209: if (s == SCSAFE) ! 210: removesafe (&sp->expr); ! 211: break; ! 212: ! 213: case SKARIF: ! 214: case SKASGOTO: ! 215: case SKCALL: ! 216: case SKCMGOTO: ! 217: case SKIFN: ! 218: case SKSTOP: ! 219: case SKRETURN: ! 220: case SKPAUSE: ! 221: case SKIOIFN: ! 222: s = anex(sp->expr); ! 223: if (s == SCSAFE) ! 224: removesafe(&sp->expr); ! 225: break; ! 226: ! 227: default: ! 228: break; ! 229: } ! 230: ! 231: freetable(); ! 232: return; ! 233: } ! 234: ! 235: ! 236: LOCAL scanvars() ! 237: ! 238: { ! 239: Slotp sp; ! 240: Varp varinfo; ! 241: int i; ! 242: Varp p; ! 243: ! 244: commonset = NO; ! 245: ! 246: for (sp = first; sp != last->next; sp = sp->next) ! 247: { ! 248: switch (sp->type) ! 249: { ! 250: case SKARIF: ! 251: case SKASGOTO: ! 252: case SKCALL: ! 253: case SKCMGOTO: ! 254: case SKIFN: ! 255: case SKSTOP: ! 256: case SKRETURN: ! 257: case SKPAUSE: ! 258: case SKIOIFN: ! 259: case SKEQ: ! 260: setsuses(sp->expr); ! 261: break; ! 262: ! 263: default: ! 264: break; ! 265: } ! 266: } ! 267: ! 268: if (commonset) ! 269: for (i = 0; i < TABLESIZE; i++) ! 270: for (p = table[i]; p; p = p->next) ! 271: if (p->vstg == STGCOMMON) ! 272: { ! 273: p->sets++; ! 274: p->setfirst = NO; ! 275: } ! 276: } ! 277: ! 278: ! 279: LOCAL setsuses(p) ! 280: expptr p; ! 281: ! 282: { ! 283: Addrp lhs; ! 284: Varp varinfo; ! 285: chainp args; ! 286: ! 287: if (!p) return; ! 288: ! 289: switch (p->tag) ! 290: { ! 291: case TEXPR: ! 292: switch (p->exprblock.opcode) ! 293: { ! 294: default: ! 295: setsuses(p->exprblock.leftp); ! 296: setsuses(p->exprblock.rightp); ! 297: setsuses(p->exprblock.vleng); ! 298: break; ! 299: ! 300: case OPASSIGN: ! 301: switch (p->exprblock.leftp->tag) ! 302: { ! 303: case TTEMP: ! 304: lhs = (Addrp) p->exprblock.leftp; ! 305: goto taddr; ! 306: ! 307: case TADDR: ! 308: lhs = (Addrp) p->exprblock.leftp; ! 309: setsuses(lhs->memoffset); ! 310: setsuses(lhs->vleng); ! 311: taddr: ! 312: setsuses(p->exprblock.rightp); ! 313: setsuses(p->exprblock.vleng); ! 314: varinfo = lookup(lhs); ! 315: varinfo->sets++; ! 316: if (varinfo->uses == 0) ! 317: varinfo->setfirst = YES; ! 318: break; ! 319: ! 320: default: ! 321: fatal("O6: l-value expected"); ! 322: } ! 323: break; ! 324: ! 325: case OPSTAREQ: ! 326: case OPPLUSEQ: ! 327: switch (p->exprblock.leftp->tag) ! 328: { ! 329: case TADDR: ! 330: lhs = (Addrp) p->exprblock.leftp; ! 331: break; ! 332: case TTEMP: ! 333: lhs = (Addrp) p->exprblock.leftp; ! 334: break; ! 335: default: ! 336: fatal("O7: l-value expected"); ! 337: } ! 338: setsuses(p->exprblock.leftp); ! 339: setsuses(p->exprblock.rightp); ! 340: setsuses(p->exprblock.vleng); ! 341: varinfo = lookup(lhs); ! 342: varinfo->sets++; ! 343: break; ! 344: ! 345: case OPCALL: ! 346: if (p->exprblock.leftp->tag != TADDR) ! 347: fatal("O8: subprogram expected"); ! 348: setsuses(p->exprblock.rightp); ! 349: setsuses(p->exprblock.vleng); ! 350: if (p->exprblock.leftp->addrblock.vstg != STGEXT) break; ! 351: commonset = YES; ! 352: if (p->exprblock.rightp == NULL) break; ! 353: args = p->exprblock.rightp->listblock.listp; ! 354: for (; args; args = args->nextp) ! 355: if (args->datap->tag == TADDR) ! 356: { ! 357: lhs = (Addrp) args->datap; ! 358: switch (lhs->vstg) ! 359: { ! 360: case STGARG: ! 361: case STGAUTO: ! 362: case STGBSS: ! 363: case STGINIT: ! 364: case STGCOMMON: ! 365: case STGEQUIV: ! 366: case STGREG: ! 367: case STGPREG: ! 368: varinfo = lookup(lhs); ! 369: varinfo->sets++; ! 370: } ! 371: } ! 372: else if (args->datap->tag == TTEMP) ! 373: { ! 374: lhs = (Addrp) args->datap; ! 375: varinfo = lookup (lhs); ! 376: varinfo->sets++; ! 377: } ! 378: break; ! 379: } ! 380: ! 381: return; ! 382: ! 383: case TTEMP: ! 384: varinfo = lookup((Addrp) p); ! 385: varinfo->uses++; ! 386: return; ! 387: ! 388: case TADDR: ! 389: setsuses(p->addrblock.memoffset); ! 390: setsuses(p->addrblock.vleng); ! 391: varinfo = lookup((Addrp) p); ! 392: varinfo->uses++; ! 393: return; ! 394: ! 395: case TLIST: ! 396: for (args = p->listblock.listp; args; args = args->nextp) ! 397: setsuses(args->datap); ! 398: ! 399: case TCONST: ! 400: case TERROR: ! 401: return; ! 402: ! 403: default: ! 404: fatal("O9: bad tag value"); ! 405: } ! 406: } ! 407: ! 408: ! 409: LOCAL int anex(p) ! 410: expptr p; ! 411: ! 412: { ! 413: int s1, s2, s3; ! 414: expptr q; ! 415: Varp varinfo; ! 416: chainp ch; ! 417: int setfirst; ! 418: expptr expr; ! 419: ! 420: ! 421: if (p == ENULL) ! 422: return SCSAFE; ! 423: ! 424: switch (p->tag) ! 425: { ! 426: case TCONST: ! 427: return SCSAFE; ! 428: ! 429: case TLIST: ! 430: for (ch = p->listblock.listp; ch; ch = ch->nextp) ! 431: { ! 432: s1 = anex (ch->datap); ! 433: if (s1 == SCSAFE) ! 434: removesafe (&ch->datap); ! 435: } ! 436: return SCFREE; ! 437: ! 438: case TEXPR: ! 439: s1 = anex(p->exprblock.leftp); ! 440: s2 = anex(p->exprblock.rightp); ! 441: s3 = anex(p->exprblock.vleng); ! 442: ! 443: switch (p->exprblock.opcode) ! 444: { ! 445: case OPASSIGN: ! 446: expr = p->exprblock.leftp; ! 447: varinfo = lookup(expr); ! 448: setfirst = varinfo->setfirst && (varinfo->sets == 1); ! 449: if (expr->tag == TTEMP && setfirst && ! 450: s2 == SCSAFE && s3 == SCSAFE) ! 451: { ! 452: movefrtemp (expr); ! 453: return SCSAFE; ! 454: } ! 455: else ! 456: { ! 457: if (s2 == SCSAFE) removesafe (&p->exprblock.rightp); ! 458: if (s3 == SCSAFE) removesafe (&p->exprblock.vleng); ! 459: return SCFREE; ! 460: } ! 461: ! 462: case OPNEG: ! 463: case OPNOT: ! 464: case OPABS: ! 465: case OPADDR: ! 466: case OPBITNOT: ! 467: if ((s2 == SCSAFE) && (s3 == SCSAFE)) ! 468: return s1; ! 469: else ! 470: return SCFREE; ! 471: ! 472: case OPCONV: ! 473: if ((s2 != SCSAFE) || (s3 != SCSAFE)) ! 474: return SCFREE; ! 475: ! 476: if (ISINT(p->exprblock.vtype)) ! 477: return s1; ! 478: if (ISINT(p->exprblock.leftp->headblock.vtype)) ! 479: return s1; ! 480: ! 481: return SCFREE; ! 482: ! 483: ! 484: case OPSTAR: ! 485: if (ISINT(p->exprblock.vtype)) ! 486: goto safeop; ! 487: ! 488: if (safefactor(p->exprblock.leftp) || ! 489: safefactor(p->exprblock.rightp)) ! 490: goto safeop; ! 491: ! 492: goto floatop; ! 493: ! 494: ! 495: case OPPLUS: ! 496: case OPMINUS: ! 497: if (ISINT(p->exprblock.vtype)) ! 498: goto safeop; ! 499: ! 500: floatop: ! 501: if (!(ISREAL(p->exprblock.vtype) || ISCOMPLEX(p->exprblock.vtype))) ! 502: return SCFREE; ! 503: ! 504: switch (s1) ! 505: { ! 506: case SCSAFE: ! 507: removesafe(&p->exprblock.leftp); ! 508: if (s2 == SCSAFE) ! 509: removesafe(&p->exprblock.leftp); ! 510: return SCFREE; ! 511: ! 512: case SCFREE: ! 513: if (s2 == SCSAFE) ! 514: removesafe(&p->exprblock.rightp); ! 515: return SCFREE; ! 516: } ! 517: ! 518: case OPOR: ! 519: case OPAND: ! 520: case OPEQV: ! 521: case OPNEQV: ! 522: case OPLT: ! 523: case OPEQ: ! 524: case OPGT: ! 525: case OPLE: ! 526: case OPNE: ! 527: case OPGE: ! 528: case OPLSHIFT: ! 529: case OPMIN: ! 530: case OPMAX: ! 531: case OPBITOR: ! 532: case OPBITAND: ! 533: case OPBITXOR: ! 534: case OPRSHIFT: ! 535: safeop: ! 536: if ((p->exprblock.vleng != ENULL) && ( ! ISCONST(p->exprblock.vleng))) ! 537: return SCFREE; ! 538: ! 539: switch (s1) ! 540: { ! 541: case SCSAFE: ! 542: if (s2 == SCFREE) removesafe (&p->exprblock.leftp); ! 543: return s2; ! 544: ! 545: case SCFREE: ! 546: if (s2 == SCSAFE) removesafe (&p->exprblock.rightp); ! 547: return SCFREE; ! 548: } ! 549: ! 550: default: ! 551: if (s1 == SCSAFE) removesafe(&p->exprblock.leftp); ! 552: if (s2 == SCSAFE) removesafe(&p->exprblock.rightp); ! 553: if (s3 == SCSAFE) removesafe(&p->exprblock.vleng); ! 554: return SCFREE; ! 555: } ! 556: ! 557: ! 558: case TTEMP: ! 559: varinfo = lookup(p); ! 560: if (varinfo->sets == 0) ! 561: return SCSAFE; ! 562: else ! 563: return SCFREE; ! 564: ! 565: case TADDR: ! 566: s1 = anex(p->addrblock.memoffset); ! 567: s2 = anex(p->addrblock.vleng); ! 568: ! 569: varinfo = lookup(p); ! 570: ! 571: if (varinfo->sets == 0) ! 572: switch (s1) ! 573: { ! 574: case SCSAFE: ! 575: if (s2 == SCFREE) removesafe(&p->addrblock.memoffset); ! 576: return s2; ! 577: ! 578: case SCFREE: ! 579: if (s2 == SCSAFE) removesafe(&p->addrblock.vleng); ! 580: return SCFREE; ! 581: } ! 582: ! 583: if (s1 == SCSAFE) removesafe(&p->addrblock.memoffset); ! 584: if (s2 == SCSAFE) removesafe(&p->addrblock.vleng); ! 585: return SCFREE; ! 586: ! 587: ! 588: default: ! 589: return SCFREE; ! 590: } ! 591: } ! 592: ! 593: ! 594: LOCAL safefactor(p) ! 595: expptr p; ! 596: ! 597: { ! 598: if ( ! ISCONST(p)) ! 599: return NO; ! 600: ! 601: if (ISINT(p->constblock.vtype)) ! 602: if (abs(p->constblock.const.ci) <= 1) ! 603: return YES; ! 604: ! 605: if (ISREAL(p->constblock.vtype)) ! 606: if (abs(p->constblock.const.cd[0]) <= 1.0) ! 607: return YES; ! 608: ! 609: return NO; ! 610: } ! 611: ! 612: ! 613: LOCAL int worthcost(p) ! 614: expptr p; ! 615: ! 616: { ! 617: int cost; ! 618: chainp q; ! 619: expptr memoffset,vleng; ! 620: ! 621: if (p == ENULL) ! 622: return NO; ! 623: ! 624: switch (p->tag) ! 625: { ! 626: case TCONST: ! 627: return NO; ! 628: ! 629: case TTEMP: ! 630: return NO; ! 631: ! 632: case TADDR: ! 633: if ((memoffset = p->addrblock.memoffset) && ! ISCONST(memoffset)) ! 634: return YES; ! 635: else if ((vleng = p->addrblock.vleng) && ! ISCONST(vleng)) ! 636: return YES; ! 637: else ! 638: return NO; ! 639: ! 640: case TEXPR: ! 641: return YES; ! 642: ! 643: case TLIST: ! 644: cost = 0; ! 645: for (q = p->listblock.listp; q; q = q->nextp) ! 646: { ! 647: if (worthcost ((expptr) q->datap)) ! 648: return YES; ! 649: cost++; ! 650: } ! 651: return (cost>2 ? YES : NO); ! 652: ! 653: default: ! 654: return NO; ! 655: } ! 656: } ! 657: ! 658: ! 659: LOCAL removesafe(refexpr) ! 660: expptr *refexpr; ! 661: ! 662: { ! 663: expptr ep; ! 664: Tempp ap; ! 665: Slotp newslot; ! 666: ! 667: extern Addrp gettemp(); ! 668: ! 669: ep = *refexpr; ! 670: if (! worthcost(ep)) ! 671: return; ! 672: ! 673: if (ep->tag == TEXPR && ep->exprblock.opcode == OPASSIGN) ! 674: { ! 675: if (ep->exprblock.leftp->tag != TTEMP) ! 676: fatal ("non-TEMP in assignment to be moved in optloop"); ! 677: ! 678: newslot = optinsert (SKEQ, ep, 0, 0, first); ! 679: *refexpr = ep->exprblock.leftp; ! 680: } ! 681: else ! 682: { ! 683: ap = (Tempp) gettemp(ep); ! 684: newslot = optinsert (SKEQ, mkexpr(OPASSIGN,cpexpr(ap),ep), 0, 0, first); ! 685: *refexpr = (expptr) ap; ! 686: optinsert (SKFRTEMP,ap->memalloc,0,0,last->next); ! 687: } ! 688: ! 689: comocount++; ! 690: if (!newcode) ! 691: newcode = newslot; ! 692: ! 693: return; ! 694: } ! 695: ! 696: ! 697: LOCAL Addrp gettemp(p) ! 698: expptr p; ! 699: ! 700: { ! 701: return mktemp(p->headblock.vtype, p->headblock.vleng); ! 702: } ! 703: ! 704: ! 705: ! 706: LOCAL movefrtemp (expr) ! 707: Tempp expr; ! 708: ! 709: { ! 710: Slotp s; ! 711: ! 712: if (expr->tag != TTEMP) ! 713: badtag ("movefrtemp",expr->tag); ! 714: ! 715: for (s = first; s; s = s->next) ! 716: if (s->type == SKFRTEMP && s->expr == (expptr) expr->memalloc) ! 717: { ! 718: removeslot (s); ! 719: insertslot (s,last->next); ! 720: return; ! 721: } ! 722: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.