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