|
|
1.1 ! root 1: /* ! 2: * C compiler part 2 -- expression optimizer ! 3: */ ! 4: ! 5: #include "c1.h" ! 6: ! 7: union tree * ! 8: optim(tree) ! 9: register union tree *tree; ! 10: { ! 11: register op, dope; ! 12: int d1, d2; ! 13: union tree *t; ! 14: union { double dv; int iv[4];} fp11; ! 15: ! 16: if (tree==NULL) ! 17: return(NULL); ! 18: if ((op = tree->t.op)==0) ! 19: return(tree); ! 20: if (op==NAME && tree->n.class==AUTO) { ! 21: tree->n.class = OFFS; ! 22: tree->n.regno = 5; ! 23: tree->n.offset = tree->n.nloc; ! 24: } ! 25: dope = opdope[op]; ! 26: if ((dope&LEAF) != 0) { ! 27: if (op==FCON) { ! 28: fp11.dv = tree->f.fvalue; ! 29: if (fp11.iv[1]==0 ! 30: && fp11.iv[2]==0 ! 31: && fp11.iv[3]==0) { ! 32: tree->t.op = SFCON; ! 33: tree->f.value = fp11.iv[0]; ! 34: } ! 35: } ! 36: return(tree); ! 37: } ! 38: if ((dope&BINARY) == 0) ! 39: return(unoptim(tree)); ! 40: /* is known to be binary */ ! 41: if (tree->t.type==CHAR) ! 42: tree->t.type = INT; ! 43: switch(op) { ! 44: /* ! 45: * PDP-11 special: ! 46: * generate new &=~ operator out of &= ! 47: * by complementing the RHS. ! 48: */ ! 49: case ASAND: ! 50: tree->t.op = ASANDN; ! 51: tree->t.tr2 = tnode(COMPL, tree->t.tr2->t.type, tree->t.tr2, TNULL); ! 52: break; ! 53: ! 54: /* ! 55: * On the PDP-11, int->ptr via multiplication ! 56: * Longs are just truncated. ! 57: */ ! 58: case LTOP: ! 59: tree->t.op = ITOP; ! 60: tree->t.tr1 = unoptim(tnode(LTOI,INT,tree->t.tr1, TNULL)); ! 61: case ITOP: ! 62: tree->t.op = TIMES; ! 63: break; ! 64: ! 65: case MINUS: ! 66: if ((t = isconstant(tree->t.tr2)) && (!uns(t) || tree->t.type!=LONG) ! 67: && (t->t.type!=INT || t->c.value!=0100000)) { ! 68: tree->t.op = PLUS; ! 69: if (t->t.type==DOUBLE) ! 70: /* PDP-11 FP representation */ ! 71: t->c.value ^= 0100000; ! 72: else ! 73: t->c.value = -t->c.value; ! 74: } ! 75: break; ! 76: } ! 77: op = tree->t.op; ! 78: dope = opdope[op]; ! 79: if (dope&LVALUE && tree->t.tr1->t.op==FSEL) ! 80: return(lvfield(tree)); ! 81: if ((dope&COMMUTE)!=0) { ! 82: d1 = tree->t.type; ! 83: tree = acommute(tree); ! 84: if (tree->t.op == op) ! 85: tree->t.type = d1; ! 86: /* ! 87: * PDP-11 special: ! 88: * replace a&b by a ANDN ~ b. ! 89: * This will be undone when in ! 90: * truth-value context. ! 91: */ ! 92: if (tree->t.op!=AND) ! 93: return(tree); ! 94: /* ! 95: * long & pos-int is simpler ! 96: */ ! 97: if (tree->t.type==LONG && tree->t.tr2->t.op==ITOL ! 98: && (tree->t.tr2->t.tr1->t.op==CON && tree->t.tr2->t.tr1->c.value>=0 ! 99: || uns(tree->t.tr2->t.tr1))) { ! 100: tree->t.type = UNSIGN; ! 101: t = tree->t.tr2; ! 102: tree->t.tr2 = tree->t.tr2->t.tr1; ! 103: t->t.tr1 = tree; ! 104: tree->t.tr1 = tnode(LTOI, UNSIGN, tree->t.tr1, TNULL); ! 105: return(optim(t)); ! 106: } ! 107: /* ! 108: * Keep constants to the right ! 109: */ ! 110: if ((tree->t.tr1->t.op==ITOL && tree->t.tr1->t.tr1->t.op==CON) ! 111: || tree->t.tr1->t.op==LCON) { ! 112: t = tree->t.tr1; ! 113: tree->t.tr1 = tree->t.tr2; ! 114: tree->t.tr2 = t; ! 115: } ! 116: tree->t.op = ANDN; ! 117: op = ANDN; ! 118: tree->t.tr2 = tnode(COMPL, tree->t.tr2->t.type, tree->t.tr2, TNULL); ! 119: } ! 120: again: ! 121: tree->t.tr1 = optim(tree->t.tr1); ! 122: tree->t.tr2 = optim(tree->t.tr2); ! 123: if (tree->t.type == LONG) { ! 124: t = lconst(tree->t.op, tree->t.tr1, tree->t.tr2); ! 125: if (t) ! 126: return(t); ! 127: } ! 128: if ((dope&RELAT) != 0) { ! 129: if ((d1=degree(tree->t.tr1)) < (d2=degree(tree->t.tr2)) ! 130: || d1==d2 && tree->t.tr1->t.op==NAME && tree->t.tr2->t.op!=NAME) { ! 131: t = tree->t.tr1; ! 132: tree->t.tr1 = tree->t.tr2; ! 133: tree->t.tr2 = t; ! 134: tree->t.op = maprel[op-EQUAL]; ! 135: } ! 136: if (tree->t.tr1->t.type==CHAR && tree->t.tr2->t.op==CON ! 137: && (dcalc(tree->t.tr1, 0) <= 12 || tree->t.tr1->t.op==STAR) ! 138: && tree->t.tr2->c.value <= 127 && tree->t.tr2->c.value >= 0) ! 139: tree->t.tr2->t.type = CHAR; ! 140: } ! 141: d1 = max(degree(tree->t.tr1), islong(tree->t.type)); ! 142: d2 = max(degree(tree->t.tr2), 0); ! 143: switch (op) { ! 144: ! 145: /* ! 146: * In assignment to fields, treat all-zero and all-1 specially. ! 147: */ ! 148: case FSELA: ! 149: if (tree->t.tr2->t.op==CON && tree->t.tr2->c.value==0) { ! 150: tree->t.op = ASAND; ! 151: tree->t.tr2->c.value = ~tree->F.mask; ! 152: return(optim(tree)); ! 153: } ! 154: if (tree->t.tr2->t.op==CON && tree->F.mask==tree->t.tr2->c.value) { ! 155: tree->t.op = ASOR; ! 156: return(optim(tree)); ! 157: } ! 158: ! 159: case LTIMES: ! 160: case LDIV: ! 161: case LMOD: ! 162: case LASTIMES: ! 163: case LASDIV: ! 164: case LASMOD: ! 165: case UDIV: ! 166: case UMOD: ! 167: case ASUDIV: ! 168: case ASUMOD: ! 169: tree->t.degree = 10; ! 170: break; ! 171: ! 172: case ANDN: ! 173: if (isconstant(tree->t.tr2) && tree->t.tr2->c.value==0) { ! 174: return(tree->t.tr1); ! 175: } ! 176: goto def; ! 177: ! 178: case CALL: ! 179: tree->t.degree = 10; ! 180: break; ! 181: ! 182: case QUEST: ! 183: case COLON: ! 184: tree->t.degree = max(d1, d2); ! 185: break; ! 186: ! 187: case PTOI: ! 188: case DIVIDE: ! 189: case ASDIV: ! 190: case ASTIMES: ! 191: if (tree->t.tr2->t.op==CON && tree->t.tr2->c.value==1) { ! 192: if (op==PTOI) ! 193: return(optim(tnode(LTOI,INT,paint(tree->t.tr1,LONG), TNULL))); ! 194: return(paint(tree->t.tr1, tree->t.type)); ! 195: } ! 196: case MOD: ! 197: case ASMOD: ! 198: if ((uns(tree->t.tr1) || tree->t.op==PTOI) && ispow2(tree)) ! 199: return(pow2(tree)); ! 200: if ((op==MOD||op==ASMOD) && tree->t.type==DOUBLE) { ! 201: error("Floating %% not defined"); ! 202: tree->t.type = INT; ! 203: } ! 204: case ULSH: ! 205: case ASULSH: ! 206: d1 += 2 + regpanic; ! 207: d2 += 2 + regpanic; ! 208: panicposs++; ! 209: if (tree->t.type==LONG) ! 210: return(hardlongs(tree)); ! 211: if ((op==MOD || op==DIVIDE || op==ASMOD || op==ASDIV) ! 212: && (uns(tree->t.tr1) || uns(tree->t.tr2)) ! 213: && (tree->t.tr2->t.op!=CON || tree->t.tr2->c.value<=1)) { ! 214: if (op>=ASDIV) { ! 215: tree->t.op += ASUDIV - ASDIV; ! 216: } else ! 217: tree->t.op += UDIV - DIVIDE; ! 218: d1 = d2 = 10; ! 219: } ! 220: goto constant; ! 221: ! 222: case ASPLUS: ! 223: case ASMINUS: ! 224: if (tree->t.tr2->t.op==CON && tree->t.tr2->c.value==0) ! 225: return(tree->t.tr1); ! 226: goto def; ! 227: ! 228: case LSHIFT: ! 229: case RSHIFT: ! 230: case ASRSH: ! 231: case ASLSH: ! 232: if (tree->t.tr2->t.op==CON && tree->t.tr2->c.value==0) ! 233: return(paint(tree->t.tr1, tree->t.type)); ! 234: /* ! 235: * PDP-11 special: turn right shifts into negative ! 236: * left shifts ! 237: */ ! 238: if (tree->t.type == LONG) { ! 239: d1++; ! 240: d2++; ! 241: } ! 242: if (op==LSHIFT||op==ASLSH) ! 243: goto constant; ! 244: if (tree->t.tr2->t.op==CON && tree->t.tr2->c.value==1 ! 245: && !uns(tree->t.tr1) && !uns(tree->t.tr2)) ! 246: goto constant; ! 247: op += (LSHIFT-RSHIFT); ! 248: tree->t.op = op; ! 249: tree->t.tr2 = tnode(NEG, tree->t.tr2->t.type, tree->t.tr2, TNULL); ! 250: if (uns(tree->t.tr1) || uns(tree->t.tr2)) { ! 251: if (tree->t.op==LSHIFT) ! 252: tree->t.op = ULSH; ! 253: else if (tree->t.op==ASLSH) ! 254: tree->t.op = ASULSH; ! 255: } ! 256: goto again; ! 257: ! 258: constant: ! 259: if (tree->t.tr1->t.op==CON && tree->t.tr2->t.op==CON) { ! 260: const(op, &tree->t.tr1->c.value, tree->t.tr2->c.value, tree->t.type); ! 261: return(tree->t.tr1); ! 262: } ! 263: ! 264: ! 265: def: ! 266: default: ! 267: if (dope&RELAT) { ! 268: if (tree->t.tr1->t.type==LONG) /* long relations are a mess */ ! 269: d1 = 10; ! 270: if (opdope[tree->t.tr1->t.op]&RELAT && tree->t.tr2->t.op==CON ! 271: && tree->t.tr2->c.value==0) { ! 272: tree = tree->t.tr1; ! 273: switch(op) { ! 274: case GREATEQ: ! 275: return((union tree *)&cone); ! 276: case LESS: ! 277: return((union tree *)&czero); ! 278: case LESSEQ: ! 279: case EQUAL: ! 280: tree->t.op = notrel[tree->t.op-EQUAL]; ! 281: } ! 282: return(tree); ! 283: } ! 284: } ! 285: tree->t.degree = d1==d2? d1+islong(tree->t.type): max(d1, d2); ! 286: break; ! 287: } ! 288: return(tree); ! 289: } ! 290: ! 291: union tree * ! 292: unoptim(tree) ! 293: register union tree *tree; ! 294: { ! 295: register union tree *subtre, *p; ! 296: ! 297: if (tree==NULL) ! 298: return(NULL); ! 299: again: ! 300: if (tree->t.op==AMPER && tree->t.tr1->t.op==STAR) { ! 301: subtre = tree->t.tr1->t.tr1; ! 302: subtre->t.type = tree->t.type; ! 303: return(optim(subtre)); ! 304: } ! 305: subtre = tree->t.tr1 = optim(tree->t.tr1); ! 306: switch (tree->t.op) { ! 307: ! 308: case INCAFT: ! 309: case DECAFT: ! 310: if (tree->t.type!=subtre->t.type) ! 311: paint(subtre, tree->t.type); ! 312: break; ! 313: ! 314: case ITOL: ! 315: if (subtre->t.op==CON && subtre->t.type==INT && subtre->c.value<0) { ! 316: subtre = getblk(sizeof(struct lconst)); ! 317: subtre->t.op = LCON; ! 318: subtre->t.type = LONG; ! 319: subtre->l.lvalue = tree->t.tr1->c.value; ! 320: return(subtre); ! 321: } ! 322: break; ! 323: ! 324: case FTOI: ! 325: if (uns(tree)) { ! 326: tree->t.op = FTOL; ! 327: tree->t.type = LONG; ! 328: tree = tnode(LTOI, UNSIGN, tree, TNULL); ! 329: } ! 330: break; ! 331: ! 332: case LTOF: ! 333: if (subtre->t.op==LCON) { ! 334: tree = getblk(sizeof(struct ftconst)); ! 335: tree->t.op = FCON; ! 336: tree->t.type = DOUBLE; ! 337: tree->c.value = isn++; ! 338: tree->f.fvalue = subtre->l.lvalue; ! 339: return(optim(tree)); ! 340: } ! 341: break; ! 342: ! 343: case ITOF: ! 344: if (subtre->t.op==CON) { ! 345: tree = getblk(sizeof(struct ftconst)); ! 346: tree->t.op = FCON; ! 347: tree->t.type = DOUBLE; ! 348: tree->f.value = isn++; ! 349: if (uns(subtre)) ! 350: tree->f.fvalue = (unsigned)subtre->c.value; ! 351: else ! 352: tree->f.fvalue = subtre->c.value; ! 353: return(optim(tree)); ! 354: } ! 355: if (uns(subtre)) { ! 356: tree->t.tr1 = tnode(ITOL, LONG, subtre, TNULL); ! 357: tree->t.op = LTOF; ! 358: return(optim(tree)); ! 359: } ! 360: break; ! 361: ! 362: case ITOC: ! 363: /* ! 364: * Sign-extend PDP-11 characters ! 365: */ ! 366: if (subtre->t.op==CON) { ! 367: char c; ! 368: c = subtre->c.value; ! 369: subtre->c.value = c; ! 370: subtre->t.type = tree->t.type; ! 371: return(subtre); ! 372: } else if (subtre->t.op==NAME && tree->t.type==INT) { ! 373: subtre->t.type = CHAR; ! 374: return(subtre); ! 375: } ! 376: break; ! 377: ! 378: case LTOI: ! 379: switch (subtre->t.op) { ! 380: ! 381: case LCON: ! 382: subtre->t.op = CON; ! 383: subtre->t.type = tree->t.type; ! 384: subtre->c.value = subtre->l.lvalue; ! 385: return(subtre); ! 386: ! 387: case NAME: ! 388: subtre->n.offset += 2; ! 389: subtre->t.type = tree->t.type; ! 390: return(subtre); ! 391: ! 392: case STAR: ! 393: subtre->t.type = tree->t.type; ! 394: subtre->t.tr1->t.type = tree->t.type+PTR; ! 395: subtre->t.tr1 = tnode(PLUS, tree->t.type, subtre->t.tr1, tconst(2, INT)); ! 396: return(optim(subtre)); ! 397: ! 398: case ITOL: ! 399: return(paint(subtre->t.tr1, tree->t.type)); ! 400: ! 401: case PLUS: ! 402: case MINUS: ! 403: case AND: ! 404: case ANDN: ! 405: case OR: ! 406: case EXOR: ! 407: subtre->t.tr2 = tnode(LTOI, tree->t.type, subtre->t.tr2, TNULL); ! 408: case NEG: ! 409: case COMPL: ! 410: subtre->t.tr1 = tnode(LTOI, tree->t.type, subtre->t.tr1, TNULL); ! 411: subtre->t.type = tree->t.type; ! 412: return(optim(subtre)); ! 413: } ! 414: break; ! 415: ! 416: case FSEL: ! 417: tree->t.op = AND; ! 418: tree->t.tr1 = tree->t.tr2->t.tr1; ! 419: tree->t.tr2->t.tr1 = subtre; ! 420: tree->t.tr2->t.op = RSHIFT; ! 421: tree->t.tr1->c.value = (1 << tree->t.tr1->c.value) - 1; ! 422: return(optim(tree)); ! 423: ! 424: case FSELR: ! 425: tree->t.op = LSHIFT; ! 426: tree->t.type = UNSIGN; ! 427: tree->t.tr1 = tree->t.tr2; ! 428: tree->t.tr1->t.op = AND; ! 429: tree->t.tr2 = tree->t.tr2->t.tr2; ! 430: tree->t.tr1->t.tr2 = subtre; ! 431: tree->t.tr1->t.tr1->c.value = (1 << tree->t.tr1->t.tr1->c.value) -1; ! 432: return(optim(tree)); ! 433: ! 434: case AMPER: ! 435: if (subtre->t.op==STAR) ! 436: return(subtre->t.tr1); ! 437: if (subtre->t.op==NAME && subtre->n.class == OFFS) { ! 438: p = tnode(PLUS, tree->t.type, subtre, tree); ! 439: subtre->t.type = tree->t.type; ! 440: tree->t.op = CON; ! 441: tree->t.type = INT; ! 442: tree->t.degree = 0; ! 443: tree->c.value = subtre->n.offset; ! 444: subtre->n.class = REG; ! 445: subtre->n.nloc = subtre->n.regno; ! 446: subtre->n.offset = 0; ! 447: return(optim(p)); ! 448: } ! 449: if (subtre->t.op==LOAD) { ! 450: tree->t.tr1 = subtre->t.tr1; ! 451: goto again; ! 452: } ! 453: break; ! 454: ! 455: case STAR: ! 456: if (subtre->t.op==AMPER) { ! 457: subtre->t.tr1->t.type = tree->t.type; ! 458: return(subtre->t.tr1); ! 459: } ! 460: if (tree->t.type==STRUCT) ! 461: break; ! 462: if (subtre->t.op==NAME && subtre->n.class==REG) { ! 463: subtre->t.type = tree->t.type; ! 464: subtre->n.class = OFFS; ! 465: subtre->n.regno = subtre->n.nloc; ! 466: return(subtre); ! 467: } ! 468: p = subtre->t.tr1; ! 469: if ((subtre->t.op==INCAFT||subtre->t.op==DECBEF)&&tree->t.type!=LONG ! 470: && p->t.op==NAME && p->n.class==REG && p->t.type==subtre->t.type) { ! 471: p->t.type = tree->t.type; ! 472: p->t.op = subtre->t.op==INCAFT? AUTOI: AUTOD; ! 473: return(p); ! 474: } ! 475: if (subtre->t.op==PLUS && p->t.op==NAME && p->n.class==REG) { ! 476: if (subtre->t.tr2->t.op==CON) { ! 477: p->n.offset += subtre->t.tr2->c.value; ! 478: p->n.class = OFFS; ! 479: p->t.type = tree->t.type; ! 480: p->n.regno = p->n.nloc; ! 481: return(p); ! 482: } ! 483: if (subtre->t.tr2->t.op==AMPER) { ! 484: subtre = subtre->t.tr2->t.tr1; ! 485: subtre->n.class += XOFFS-EXTERN; ! 486: subtre->n.regno = p->n.nloc; ! 487: subtre->t.type = tree->t.type; ! 488: return(subtre); ! 489: } ! 490: } ! 491: break; ! 492: case EXCLA: ! 493: if ((opdope[subtre->t.op]&RELAT)==0) ! 494: break; ! 495: tree = subtre; ! 496: tree->t.op = notrel[tree->t.op-EQUAL]; ! 497: break; ! 498: ! 499: case COMPL: ! 500: if (tree->t.type==CHAR) ! 501: tree->t.type = INT; ! 502: if (tree->t.op == subtre->t.op) ! 503: return(paint(subtre->t.tr1, tree->t.type)); ! 504: if (subtre->t.op==CON) { ! 505: subtre->c.value = ~subtre->c.value; ! 506: return(paint(subtre, tree->t.type)); ! 507: } ! 508: if (subtre->t.op==LCON) { ! 509: subtre->l.lvalue = ~subtre->l.lvalue; ! 510: return(subtre); ! 511: } ! 512: if (subtre->t.op==ITOL) { ! 513: if (subtre->t.tr1->t.op==CON) { ! 514: tree = getblk(sizeof(struct lconst)); ! 515: tree->t.op = LCON; ! 516: tree->t.type = LONG; ! 517: if (uns(subtre->t.tr1)) ! 518: tree->l.lvalue = ~(long)(unsigned)subtre->t.tr1->c.value; ! 519: else ! 520: tree->l.lvalue = ~subtre->t.tr1->c.value; ! 521: return(tree); ! 522: } ! 523: if (uns(subtre->t.tr1)) ! 524: break; ! 525: subtre->t.op = tree->t.op; ! 526: subtre->t.type = subtre->t.tr1->t.type; ! 527: tree->t.op = ITOL; ! 528: tree->t.type = LONG; ! 529: goto again; ! 530: } ! 531: ! 532: case NEG: ! 533: if (tree->t.type==CHAR) ! 534: tree->t.type = INT; ! 535: if (tree->t.op==subtre->t.op) ! 536: return(paint(subtre->t.tr1, tree->t.type)); ! 537: if (subtre->t.op==CON) { ! 538: subtre->c.value = -subtre->c.value; ! 539: return(paint(subtre, tree->t.type)); ! 540: } ! 541: if (subtre->t.op==LCON) { ! 542: subtre->l.lvalue = -subtre->l.lvalue; ! 543: return(subtre); ! 544: } ! 545: if (subtre->t.op==ITOL && subtre->t.tr1->t.op==CON) { ! 546: tree = getblk(sizeof(struct lconst)); ! 547: tree->t.op = LCON; ! 548: tree->t.type = LONG; ! 549: if (uns(subtre->t.tr1)) ! 550: tree->l.lvalue = -(long)(unsigned)subtre->t.tr1->c.value; ! 551: else ! 552: tree->l.lvalue = -subtre->t.tr1->c.value; ! 553: return(tree); ! 554: } ! 555: /* ! 556: * PDP-11 FP negation ! 557: */ ! 558: if (subtre->t.op==SFCON) { ! 559: subtre->c.value ^= 0100000; ! 560: subtre->f.fvalue = -subtre->f.fvalue; ! 561: return(subtre); ! 562: } ! 563: if (subtre->t.op==FCON) { ! 564: subtre->f.fvalue = -subtre->f.fvalue; ! 565: return(subtre); ! 566: } ! 567: } ! 568: if ((opdope[tree->t.op]&LEAF)==0) ! 569: tree->t.degree = max(islong(tree->t.type), degree(subtre)); ! 570: return(tree); ! 571: } ! 572: ! 573: /* ! 574: * Deal with assignments to partial-word fields. ! 575: * The game is that select(x) += y turns into ! 576: * select(x += select(y)) where the shifts and masks ! 577: * are chosen properly. The outer select ! 578: * is discarded where the value doesn't matter. ! 579: * Sadly, overflow is undetected on += and the like. ! 580: * Pure assignment is handled specially. ! 581: */ ! 582: ! 583: union tree * ! 584: lvfield(t) ! 585: register union tree *t; ! 586: { ! 587: register union tree *t1, *t2; ! 588: ! 589: switch (t->t.op) { ! 590: ! 591: case ASSIGN: ! 592: t2 = getblk(sizeof(struct fasgn)); ! 593: t2->t.op = FSELA; ! 594: t2->t.type = UNSIGN; ! 595: t1 = t->t.tr1->t.tr2; ! 596: t2->F.mask = ((1<<t1->t.tr1->c.value)-1)<<t1->t.tr2->c.value; ! 597: t2->t.tr1 = t->t.tr1; ! 598: t2->t.tr2 = t->t.tr2; ! 599: t = t2; ! 600: ! 601: case ASANDN: ! 602: case ASPLUS: ! 603: case ASMINUS: ! 604: case ASOR: ! 605: case ASXOR: ! 606: case INCBEF: ! 607: case INCAFT: ! 608: case DECBEF: ! 609: case DECAFT: ! 610: t1 = t->t.tr1; ! 611: t1->t.op = FSELR; ! 612: t->t.tr1 = t1->t.tr1; ! 613: t1->t.tr1 = t->t.tr2; ! 614: t->t.tr2 = t1; ! 615: t1 = t1->t.tr2; ! 616: t1 = tnode(COMMA, INT, tconst(t1->t.tr1->c.value, INT), ! 617: tconst(t1->t.tr2->c.value, INT)); ! 618: return(optim(tnode(FSELT, UNSIGN, t, t1))); ! 619: ! 620: } ! 621: error("Unimplemented field operator"); ! 622: return(t); ! 623: } ! 624: ! 625: #define LSTSIZ 20 ! 626: struct acl { ! 627: int nextl; ! 628: int nextn; ! 629: union tree *nlist[LSTSIZ]; ! 630: union tree *llist[LSTSIZ+1]; ! 631: }; ! 632: ! 633: union tree * ! 634: acommute(tree) ! 635: register union tree *tree; ! 636: { ! 637: struct acl acl; ! 638: int d, i, op, flt, d1, type; ! 639: register union tree *t1, **t2; ! 640: union tree *t; ! 641: ! 642: acl.nextl = 0; ! 643: acl.nextn = 0; ! 644: op = tree->t.op; ! 645: type = tree->t.type; ! 646: flt = isfloat(tree); ! 647: insert(op, tree, &acl); ! 648: acl.nextl--; ! 649: t2 = &acl.llist[acl.nextl]; ! 650: if (!flt) { ! 651: /* put constants together */ ! 652: for (i=acl.nextl; i>0; i--) { ! 653: d = t2[-1]->t.type==UNSIGN||t2[0]->t.type==UNSIGN?UNSIGN:INT; ! 654: if (t2[0]->t.op==CON && t2[-1]->t.op==CON) { ! 655: acl.nextl--; ! 656: t2--; ! 657: const(op, &t2[0]->c.value, t2[1]->c.value, d); ! 658: t2[0]->t.type = d; ! 659: } else if (t = lconst(op, t2[-1], t2[0])) { ! 660: acl.nextl--; ! 661: t2--; ! 662: t2[0] = t; ! 663: } ! 664: } ! 665: } ! 666: if (op==PLUS || op==OR) { ! 667: /* toss out "+0" */ ! 668: if (acl.nextl>0 && ((t1 = isconstant(*t2)) && t1->c.value==0 ! 669: || (*t2)->t.op==LCON && (*t2)->l.lvalue==0)) { ! 670: acl.nextl--; ! 671: t2--; ! 672: } ! 673: if (acl.nextl <= 0) { ! 674: if ((*t2)->t.type==CHAR || (*t2)->t.type==UNCHAR) ! 675: *t2 = tnode(LOAD, tree->t.type, *t2, TNULL); ! 676: (*t2)->t.type = tree->t.type; ! 677: return(*t2); ! 678: } ! 679: /* subsume constant in "&x+c" */ ! 680: if (op==PLUS && t2[0]->t.op==CON && t2[-1]->t.op==AMPER) { ! 681: t2--; ! 682: t2[0]->t.tr1->n.offset += t2[1]->c.value; ! 683: acl.nextl--; ! 684: } ! 685: } else if (op==TIMES || op==AND) { ! 686: t1 = acl.llist[acl.nextl]; ! 687: if (t1->t.op==CON) { ! 688: if (t1->c.value==0) { ! 689: for (i=0; i<acl.nextl; i++) ! 690: if (sideeffects(acl.llist[i])) ! 691: break; ! 692: if (i==acl.nextl) ! 693: return(t1); ! 694: } ! 695: if (op==TIMES && t1->c.value==1 && acl.nextl>0) ! 696: if (--acl.nextl <= 0) { ! 697: t1 = acl.llist[0]; ! 698: if (uns(tree)) ! 699: paint(t1, tree->t.type); ! 700: return(t1); ! 701: } ! 702: } ! 703: } ! 704: if (op==PLUS && !flt) ! 705: distrib(&acl); ! 706: tree = *(t2 = &acl.llist[0]); ! 707: d = max(degree(tree), islong(tree->t.type)); ! 708: if (op==TIMES && !flt) { ! 709: d += regpanic+1; ! 710: panicposs++; ! 711: } ! 712: for (i=0; i<acl.nextl; i++) { ! 713: t1 = acl.nlist[i]; ! 714: t1->t.tr2 = t = *++t2; ! 715: d1 = degree(t); ! 716: /* ! 717: * PDP-11 strangeness: ! 718: * rt. op of ^ must be in a register. ! 719: */ ! 720: if (op==EXOR && dcalc(t, 0)<=12) { ! 721: t1->t.tr2 = t = optim(tnode(LOAD, t->t.type, t, TNULL)); ! 722: d1 = t->t.degree; ! 723: } ! 724: t1->t.degree = d = d==d1? d+islong(t1->t.type): max(d, d1); ! 725: t1->t.tr1 = tree; ! 726: tree = t1; ! 727: if (tree->t.type==LONG) { ! 728: if (tree->t.op==TIMES) ! 729: tree = hardlongs(tree); ! 730: else if (tree->t.op==PLUS && (t = isconstant(tree->t.tr1)) ! 731: && t->c.value < 0 && !uns(t)) { ! 732: tree->t.op = MINUS; ! 733: t->c.value = - t->c.value; ! 734: t = tree->t.tr1; ! 735: tree->t.tr1 = tree->t.tr2; ! 736: tree->t.tr2 = t; ! 737: } ! 738: } ! 739: } ! 740: if (tree->t.op==TIMES && ispow2(tree)) ! 741: tree->t.degree = max(degree(tree->t.tr1), islong(tree->t.type)); ! 742: paint(tree, type); ! 743: return(tree); ! 744: } ! 745: ! 746: sideeffects(tp) ! 747: register union tree *tp; ! 748: { ! 749: register dope; ! 750: ! 751: if (tp==NULL) ! 752: return(0); ! 753: dope = opdope[tp->t.op]; ! 754: if (dope&LEAF) { ! 755: if (tp->t.op==AUTOI || tp->t.op==AUTOD) ! 756: return(1); ! 757: return(0); ! 758: } ! 759: if (dope&ASSGOP) ! 760: return(1); ! 761: switch(tp->t.op) { ! 762: case CALL: ! 763: case FSELA: ! 764: case STRASG: ! 765: return(1); ! 766: } ! 767: if (sideeffects(tp->t.tr1)) ! 768: return(1); ! 769: if (dope&BINARY) ! 770: return(sideeffects(tp->t.tr2)); ! 771: return(0); ! 772: } ! 773: ! 774: distrib(list) ! 775: struct acl *list; ! 776: { ! 777: /* ! 778: * Find a list member of the form c1c2*x such ! 779: * that c1c2 divides no other such constant, is divided by ! 780: * at least one other (say in the form c1*y), and which has ! 781: * fewest divisors. Reduce this pair to c1*(y+c2*x) ! 782: * and iterate until no reductions occur. ! 783: */ ! 784: register union tree **p1, **p2; ! 785: union tree *t; ! 786: int ndmaj, ndmin; ! 787: union tree **dividend, **divisor; ! 788: union tree **maxnod, **mindiv; ! 789: ! 790: loop: ! 791: maxnod = &list->llist[list->nextl]; ! 792: ndmaj = 1000; ! 793: dividend = 0; ! 794: for (p1 = list->llist; p1 <= maxnod; p1++) { ! 795: if ((*p1)->t.op!=TIMES || (*p1)->t.tr2->t.op!=CON) ! 796: continue; ! 797: ndmin = 0; ! 798: for (p2 = list->llist; p2 <= maxnod; p2++) { ! 799: if (p1==p2 || (*p2)->t.op!=TIMES || (*p2)->t.tr2->t.op!=CON) ! 800: continue; ! 801: if ((*p1)->t.tr2->c.value == (*p2)->t.tr2->c.value) { ! 802: (*p2)->t.tr2 = (*p1)->t.tr1; ! 803: (*p2)->t.op = PLUS; ! 804: (*p1)->t.tr1 = (*p2); ! 805: *p1 = optim(*p1); ! 806: squash(p2, maxnod); ! 807: list->nextl--; ! 808: goto loop; ! 809: } ! 810: if (((*p2)->t.tr2->c.value % (*p1)->t.tr2->c.value) == 0) ! 811: goto contmaj; ! 812: if (((*p1)->t.tr2->c.value % (*p2)->t.tr2->c.value) == 0) { ! 813: ndmin++; ! 814: mindiv = p2; ! 815: } ! 816: } ! 817: if (ndmin > 0 && ndmin < ndmaj) { ! 818: ndmaj = ndmin; ! 819: dividend = p1; ! 820: divisor = mindiv; ! 821: } ! 822: contmaj:; ! 823: } ! 824: if (dividend==0) ! 825: return; ! 826: t = list->nlist[--list->nextn]; ! 827: p1 = dividend; ! 828: p2 = divisor; ! 829: t->t.op = PLUS; ! 830: t->t.type = (*p1)->t.type; ! 831: t->t.tr1 = (*p1); ! 832: t->t.tr2 = (*p2)->t.tr1; ! 833: (*p1)->t.tr2->c.value /= (*p2)->t.tr2->c.value; ! 834: (*p2)->t.tr1 = t; ! 835: t = optim(*p2); ! 836: if (p1 < p2) { ! 837: *p1 = t; ! 838: squash(p2, maxnod); ! 839: } else { ! 840: *p2 = t; ! 841: squash(p1, maxnod); ! 842: } ! 843: list->nextl--; ! 844: goto loop; ! 845: } ! 846: ! 847: squash(p, maxp) ! 848: union tree **p, **maxp; ! 849: { ! 850: register union tree **np; ! 851: ! 852: for (np = p; np < maxp; np++) ! 853: *np = *(np+1); ! 854: } ! 855: ! 856: const(op, vp, v, type) ! 857: register int *vp, v; ! 858: { ! 859: switch (op) { ! 860: ! 861: case PTOI: ! 862: (*vp) /= (unsigned)v; ! 863: return; ! 864: ! 865: case PLUS: ! 866: *vp += v; ! 867: return; ! 868: ! 869: case TIMES: ! 870: *vp *= v; ! 871: return; ! 872: ! 873: case AND: ! 874: *vp &= v; ! 875: return; ! 876: ! 877: case OR: ! 878: *vp |= v; ! 879: return; ! 880: ! 881: case EXOR: ! 882: *vp ^= v; ! 883: return; ! 884: ! 885: case UDIV: ! 886: case UMOD: ! 887: type = UNSIGN; ! 888: case DIVIDE: ! 889: case MOD: ! 890: if (type==UNSIGN && v!=0 && v<=1) { ! 891: if (op==UDIV || op==DIVIDE) { ! 892: if (v==1) ! 893: return; ! 894: *vp = *(unsigned *)vp >= (unsigned)v; ! 895: return; ! 896: } else { ! 897: if (v==1) { ! 898: *vp = 0; ! 899: return; ! 900: } ! 901: if (*(unsigned *)vp >= (unsigned)v) ! 902: *vp -= v; ! 903: return; ! 904: } ! 905: } ! 906: if (v==0) { ! 907: error("Warning: divide check"); ! 908: nerror--; ! 909: } else ! 910: if (type==INT) ! 911: if (op==DIVIDE || op==UDIV) ! 912: *vp /= v; ! 913: else ! 914: *vp %= v; ! 915: else ! 916: if (op==DIVIDE || op==UDIV) ! 917: *(unsigned *)vp /= (unsigned)v; ! 918: else ! 919: *(unsigned *)vp %= (unsigned)v; ! 920: return; ! 921: ! 922: case RSHIFT: ! 923: rshift: ! 924: if (v<0) { ! 925: v = -v; ! 926: goto lshift; ! 927: } ! 928: if (type==INT) ! 929: *vp >>= v; ! 930: else ! 931: *(unsigned *)vp >>= (unsigned)v; ! 932: return; ! 933: ! 934: case ULSH: ! 935: type = UNSIGN; ! 936: ! 937: case LSHIFT: ! 938: lshift: ! 939: if (v<0) { ! 940: v = -v; ! 941: goto rshift; ! 942: } ! 943: if (type==INT) ! 944: *vp <<= v; ! 945: else ! 946: *(unsigned *)vp <<= (unsigned)v; ! 947: return; ! 948: ! 949: case ANDN: ! 950: *vp &= ~ v; ! 951: return; ! 952: } ! 953: error("C error: const"); ! 954: } ! 955: ! 956: union tree * ! 957: lconst(op, lp, rp) ! 958: register union tree *lp, *rp; ! 959: { ! 960: long l, r; ! 961: ! 962: if (lp->t.op==LCON) ! 963: l = lp->l.lvalue; ! 964: else if (lp->t.op==ITOL && lp->t.tr1->t.op==CON) { ! 965: if (lp->t.tr1->t.type==INT) ! 966: l = lp->t.tr1->c.value; ! 967: else ! 968: l = (unsigned)lp->t.tr1->c.value; ! 969: } else ! 970: return(0); ! 971: if (rp->t.op==LCON) ! 972: r = rp->l.lvalue; ! 973: else if (rp->t.op==ITOL && rp->t.tr1->t.op==CON) { ! 974: if (rp->t.tr1->t.type==INT) ! 975: r = rp->t.tr1->c.value; ! 976: else ! 977: r = (unsigned)rp->t.tr1->c.value; ! 978: } else ! 979: return(0); ! 980: switch (op) { ! 981: ! 982: case PLUS: ! 983: l += r; ! 984: break; ! 985: ! 986: case MINUS: ! 987: l -= r; ! 988: break; ! 989: ! 990: case TIMES: ! 991: case LTIMES: ! 992: l *= r; ! 993: break; ! 994: ! 995: case DIVIDE: ! 996: case LDIV: ! 997: if (r==0) ! 998: error("Divide check"); ! 999: else ! 1000: l /= r; ! 1001: break; ! 1002: ! 1003: case MOD: ! 1004: case LMOD: ! 1005: if (r==0) ! 1006: error("Divide check"); ! 1007: else ! 1008: l %= r; ! 1009: break; ! 1010: ! 1011: case AND: ! 1012: l &= r; ! 1013: break; ! 1014: ! 1015: case ANDN: ! 1016: l &= ~r; ! 1017: break; ! 1018: ! 1019: case OR: ! 1020: l |= r; ! 1021: break; ! 1022: ! 1023: case EXOR: ! 1024: l ^= r; ! 1025: break; ! 1026: ! 1027: case LSHIFT: ! 1028: l <<= r; ! 1029: break; ! 1030: ! 1031: case RSHIFT: ! 1032: l >>= r; ! 1033: break; ! 1034: ! 1035: default: ! 1036: return(0); ! 1037: } ! 1038: if (lp->t.op==LCON) { ! 1039: lp->l.lvalue = l; ! 1040: return(lp); ! 1041: } ! 1042: lp = getblk(sizeof(struct lconst)); ! 1043: lp->t.op = LCON; ! 1044: lp->t.type = LONG; ! 1045: lp->l.lvalue = l; ! 1046: return(lp); ! 1047: } ! 1048: ! 1049: insert(op, tree, list) ! 1050: register union tree *tree; ! 1051: register struct acl *list; ! 1052: { ! 1053: register d; ! 1054: int d1, i; ! 1055: union tree *t; ! 1056: ! 1057: ins: ! 1058: if (tree->t.op != op) ! 1059: tree = optim(tree); ! 1060: if (tree->t.op == op && list->nextn < LSTSIZ-2) { ! 1061: list->nlist[list->nextn++] = tree; ! 1062: insert(op, tree->t.tr1, list); ! 1063: insert(op, tree->t.tr2, list); ! 1064: return; ! 1065: } ! 1066: if (!isfloat(tree)) { ! 1067: /* c1*(x+c2) -> c1*x+c1*c2 */ ! 1068: if ((tree->t.op==TIMES||tree->t.op==LSHIFT) ! 1069: && tree->t.tr2->t.op==CON && tree->t.tr2->c.value>0 ! 1070: && tree->t.tr1->t.op==PLUS && tree->t.tr1->t.tr2->t.op==CON) { ! 1071: d = tree->t.tr2->c.value; ! 1072: if (tree->t.op==TIMES) ! 1073: tree->t.tr2->c.value *= tree->t.tr1->t.tr2->c.value; ! 1074: else ! 1075: tree->t.tr2->c.value = tree->t.tr1->t.tr2->c.value << d; ! 1076: tree->t.tr1->t.tr2->c.value = d; ! 1077: tree->t.tr1->t.op = tree->t.op; ! 1078: tree->t.op = PLUS; ! 1079: tree = optim(tree); ! 1080: if (op==PLUS) ! 1081: goto ins; ! 1082: } ! 1083: } ! 1084: d = degree(tree); ! 1085: for (i=0; i<list->nextl; i++) { ! 1086: if ((d1=degree(list->llist[i]))<d) { ! 1087: t = list->llist[i]; ! 1088: list->llist[i] = tree; ! 1089: tree = t; ! 1090: d = d1; ! 1091: } ! 1092: } ! 1093: list->llist[list->nextl++] = tree; ! 1094: } ! 1095: ! 1096: union tree * ! 1097: tnode(op, type, tr1, tr2) ! 1098: union tree *tr1, *tr2; ! 1099: { ! 1100: register union tree *p; ! 1101: ! 1102: p = getblk(sizeof(struct tnode)); ! 1103: p->t.op = op; ! 1104: p->t.type = type; ! 1105: p->t.degree = 0; ! 1106: p->t.tr1 = tr1; ! 1107: p->t.tr2 = tr2; ! 1108: return(p); ! 1109: } ! 1110: ! 1111: union tree * ! 1112: tconst(val, type) ! 1113: { ! 1114: register union tree *p; ! 1115: ! 1116: p = getblk(sizeof(struct tconst)); ! 1117: p->t.op = CON; ! 1118: p->t.type = type; ! 1119: p->c.value = val; ! 1120: return(p); ! 1121: } ! 1122: ! 1123: union tree * ! 1124: getblk(size) ! 1125: { ! 1126: register union tree *p; ! 1127: ! 1128: if (size&01) { ! 1129: error("compiler botch: odd size"); ! 1130: exit(1); ! 1131: } ! 1132: p = (union tree *)curbase; ! 1133: if ((curbase += size) >= coremax) { ! 1134: if (sbrk(1024) == (char *)-1) { ! 1135: error("Out of space-- c1"); ! 1136: exit(1); ! 1137: } ! 1138: coremax += 1024; ! 1139: } ! 1140: return(p); ! 1141: } ! 1142: ! 1143: islong(t) ! 1144: { ! 1145: if (t==LONG) ! 1146: return(2); ! 1147: return(1); ! 1148: } ! 1149: ! 1150: union tree * ! 1151: isconstant(t) ! 1152: register union tree *t; ! 1153: { ! 1154: if (t->t.op==CON || t->t.op==SFCON) ! 1155: return(t); ! 1156: if (t->t.op==ITOL && t->t.tr1->t.op==CON) ! 1157: return(t->t.tr1); ! 1158: return(NULL); ! 1159: } ! 1160: ! 1161: union tree * ! 1162: hardlongs(t) ! 1163: register union tree *t; ! 1164: { ! 1165: switch(t->t.op) { ! 1166: ! 1167: case TIMES: ! 1168: case DIVIDE: ! 1169: case MOD: ! 1170: t->t.op += LTIMES-TIMES; ! 1171: break; ! 1172: ! 1173: case ASTIMES: ! 1174: case ASDIV: ! 1175: case ASMOD: ! 1176: t->t.op += LASTIMES-ASTIMES; ! 1177: t->t.tr1 = tnode(AMPER, LONG+PTR, t->t.tr1, TNULL); ! 1178: break; ! 1179: ! 1180: default: ! 1181: return(t); ! 1182: } ! 1183: return(optim(t)); ! 1184: } ! 1185: ! 1186: /* ! 1187: * Is tree of unsigned type? ! 1188: */ ! 1189: uns(tp) ! 1190: union tree *tp; ! 1191: { ! 1192: register t; ! 1193: ! 1194: t = tp->t.type; ! 1195: if (t==UNSIGN || t==UNCHAR || t&XTYPE) ! 1196: return(1); ! 1197: return(0); ! 1198: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.