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: }

Defined functions

acommute defined in line 606; used 1 times
  • in line 83
distrib defined in line 707; used 1 times
getblk defined in line 1019; used 17 times
hardlongs defined in line 1056; used 2 times
insert defined in line 941; used 3 times
isconstant defined in line 1043; used 5 times
islong defined in line 1036; used 6 times
lconst defined in line 848; used 2 times
lvfield defined in line 555; used 1 times
  • in line 80
optim defined in line 10; used 35 times
squash defined in line 780; used 3 times
tconst defined in line 1008; used 8 times
tnode defined in line 991; used 33 times
unoptim defined in line 269; used 2 times

Defined variables

vp defined in line 790; used 12 times

Defined struct's

acl defined in line 599; used 8 times

Defined macros

LSTSIZ defined in line 598; used 3 times
Last modified: 1981-07-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1984
Valid CSS Valid XHTML 1.0 Strict