2 * C compiler part 2 -- expression optimizer
7 #include "c0.h" /* for Tblock() which replaces getblk() in single pass mode */
11 * Macros for fast min/max.
13 #define min(a,b) (((a)<(b))?(a):(b))
14 #define max(a,b) (((a)>(b))?(a):(b))
16 struct node *optim(tree) register struct node *tree; {
17 register int op, dope;
19 union { double dv; _INT iv[4];} fp11;
24 if ((op = tree->n_op)==0)
26 if (op==NAME && ((struct nnode *)tree)->nn_class==AUTO) {
27 #define locntree ((struct locnnode *)tree)
28 locntree->locnn_class = OFFS;
29 locntree->locnn_regno = 5;
30 locntree->locnn_offset = locntree->locnn_nloc;
34 if ((dope&LEAF) != 0) {
36 #define ftree ((struct fnode *)tree)
38 fp11.dv = ftree->fn_fvalue;
43 ftree->fn_value = fp11.iv[0];
46 if (ftree->fn_fvalue.l==0
47 && (ftree->fn_fvalue.h & 0xffff)==0) {
49 ftree->fn_value = (int)(ftree->fn_fvalue.h >> 16) & 0xffff;
56 if ((dope&BINARY) == 0)
57 return(unoptim(tree));
58 return(binoptim(tree));
61 /* in reality this can only be called with a struct tnode argument */
62 struct node *binoptim(tree) register struct node *tree; {
63 register int op, dope;
67 #define ttree ((struct tnode *)tree)
68 if (ttree->tn_type==CHAR)
70 switch(ttree->tn_op) {
73 * generate new &=~ operator out of &=
74 * by complementing the RHS.
77 ttree->tn_op = ASANDN;
78 ttree->tn_tr2 = (struct node *)tnode(COMPL, ttree->tn_tr2->n_type, ttree->tn_tr2, (struct node *)NULL);
82 * On the PDP-11, int->ptr via multiplication
83 * Longs are just truncated.
87 ttree->tn_tr1 = unoptim((struct node *)tnode(LTOI,INT,ttree->tn_tr1, (struct node *)NULL));
93 if ((t = (struct node *)isconstant(ttree->tn_tr2)) && (!uns(t) || ttree->tn_type!=LONG)
94 /* I don't think the following test matters since -0100000 == 0100000 */
95 && (((struct cnode *)t)->cn_type!=INT || ((struct cnode *)t)->cn_value!=(_INT)0100000)) {
97 if (t->n_type==DOUBLE) {
98 /* here it's an SFCON, so fn_value is filled in instead of fn_fvalue */
99 /* PDP-11 FP representation */
100 ((struct fnode *)t)->fn_value ^= 0100000;
102 ((struct cnode *)t)->cn_value = -((struct cnode *)t)->cn_value;
108 if (dope&LVALUE && ttree->tn_tr1->n_op==FSEL)
109 return(lvfield(ttree));
110 if ((dope&COMMUTE)!=0) {
113 tree = acommute(tree);
114 if (tree->n_op == op)
118 * replace a&b by a ANDN ~ b.
119 * This will be undone when in
120 * truth-value context.
124 #define ttree ((struct tnode *)tree)
126 * long & pos-int is simpler
128 if ((ttree->tn_type==LONG || ttree->tn_type==UNLONG) && ttree->tn_tr2->n_op==ITOL
129 && (((struct tnode *)ttree->tn_tr2)->tn_tr1->n_op==CON && ((struct cnode *)((struct tnode *)ttree->tn_tr2)->tn_tr1)->cn_value>=0
130 || uns(((struct tnode *)ttree->tn_tr2)->tn_tr1))) {
131 ttree->tn_type = UNSIGN;
133 ttree->tn_tr2 = ((struct tnode *)ttree->tn_tr2)->tn_tr1;
134 ((struct tnode *)t)->tn_tr1 = (struct node *)ttree;
135 ttree->tn_tr1 = (struct node *)tnode(LTOI, UNSIGN, ttree->tn_tr1, (struct node *)NULL);
139 * Keep constants to the right
141 if ((ttree->tn_tr1->n_op==ITOL && ((struct tnode *)ttree->tn_tr1)->tn_tr1->n_op==CON)
142 || ttree->tn_tr1->n_op==LCON) {
144 ttree->tn_tr1 = ttree->tn_tr2;
149 ttree->tn_tr2 = (struct node *)tnode(COMPL, ttree->tn_tr2->n_type, ttree->tn_tr2, (struct node *)NULL);
152 ttree->tn_tr1 = optim(ttree->tn_tr1);
153 ttree->tn_tr2 = optim(ttree->tn_tr2);
154 if (ttree->tn_type == LONG || ttree->tn_type==UNLONG) {
155 t = (struct node *)lconst(ttree->tn_op, ttree->tn_tr1, ttree->tn_tr2);
159 if ((dope&RELAT) != 0) {
160 if ((d1=degree(ttree->tn_tr1)) < (d2=degree(ttree->tn_tr2))
161 || d1==d2 && ttree->tn_tr1->n_op==NAME && ttree->tn_tr2->n_op!=NAME) {
163 ttree->tn_tr1 = ttree->tn_tr2;
165 ttree->tn_op = maprel[op-EQUAL];
167 if (ttree->tn_tr1->n_type==CHAR && ttree->tn_tr2->n_op==CON
168 && (dcalc(ttree->tn_tr1, 0) <= 12 || ttree->tn_tr1->n_op==STAR)
169 && ((struct cnode *)ttree->tn_tr2)->cn_value <= 127 && ((struct cnode *)ttree->tn_tr2)->cn_value >= 0)
170 ttree->tn_tr2->n_type = CHAR;
172 d1 = max(degree(ttree->tn_tr1), islong(ttree->tn_type));
173 d2 = max(degree(ttree->tn_tr2), 0);
177 * In assignment to fields, treat all-zero and all-1 specially.
180 #define Ftree ((struct fasgn *)ttree)
181 if (Ftree->fa_tr2->n_op==CON && ((struct cnode *)Ftree->fa_tr2)->cn_value==0) {
182 Ftree->fa_op = ASAND;
183 ((struct cnode *)Ftree->fa_tr2)->cn_value = ~Ftree->fa_mask;
184 return(optim((struct node *)Ftree));
186 if (Ftree->fa_tr2->n_op==CON && Ftree->fa_mask==((struct cnode *)Ftree->fa_tr2)->cn_value) {
188 return(optim((struct node *)Ftree));
208 ttree->tn_degree = 10;
212 if (isconstant(ttree->tn_tr2) && ((struct cnode *)ttree->tn_tr2)->cn_value==0) {
213 return(ttree->tn_tr1);
218 ttree->tn_degree = 10;
223 ttree->tn_degree = max(d1, d2);
230 if (ttree->tn_tr2->n_op==CON && ((struct cnode *)ttree->tn_tr2)->cn_value==1) {
232 return(optim((struct node *)tnode(LTOI,INT,paint(ttree->tn_tr1,LONG), (struct node *)NULL)));
233 return(paint(ttree->tn_tr1, ttree->tn_type));
237 if ((uns(ttree->tn_tr1) || ttree->tn_op==PTOI) && ispow2(ttree))
238 return((struct node *)pow2(ttree));
239 if ((op==MOD||op==ASMOD) && ttree->tn_type==DOUBLE) {
240 error1("Floating %% not defined");
241 ttree->tn_type = INT;
248 if (ttree->tn_type==LONG || ttree->tn_type==UNLONG)
249 return(hardlongs((struct node *)ttree));
250 if ((op==MOD || op==DIVIDE || op==ASMOD || op==ASDIV)
251 && (uns(ttree->tn_tr1) || uns(ttree->tn_tr2))
252 && (ttree->tn_tr2->n_op!=CON || ((struct cnode *)ttree->tn_tr2)->cn_value<=1)) {
254 ttree->tn_op += ASUDIV - ASDIV;
256 ttree->tn_op += UDIV - DIVIDE;
263 if (ttree->tn_tr2->n_op==CON && ((struct cnode *)ttree->tn_tr2)->cn_value==0)
264 return(ttree->tn_tr1);
271 if (ttree->tn_tr2->n_op==CON && ((struct cnode *)ttree->tn_tr2)->cn_value==0)
272 return(paint(ttree->tn_tr1, ttree->tn_type));
274 * PDP-11 special: turn right shifts into negative
277 if (ttree->tn_type == LONG || ttree->tn_type==UNLONG) {
281 if (op==LSHIFT||op==ASLSH)
283 if (ttree->tn_tr2->n_op==CON && ((struct cnode *)ttree->tn_tr2)->cn_value==1
284 && !uns(ttree->tn_tr1) && !uns(ttree->tn_tr2))
286 op += (LSHIFT-RSHIFT);
288 ttree->tn_tr2 = (struct node *)tnode(NEG, ttree->tn_tr2->n_type, ttree->tn_tr2, (struct node *)NULL);
289 if (uns(ttree->tn_tr1) || uns(ttree->tn_tr2)) {
290 if (ttree->tn_op==LSHIFT)
292 else if (ttree->tn_op==ASLSH)
293 ttree->tn_op = ASULSH;
298 if (ttree->tn_tr1->n_op==CON && ttree->tn_tr2->n_op==CON) {
299 _const(op, &((struct cnode *)ttree->tn_tr1)->cn_value, ((struct cnode *)ttree->tn_tr2)->cn_value, ttree->tn_type);
300 return(ttree->tn_tr1);
307 if (ttree->tn_tr1->n_type==LONG || ttree->tn_tr1->n_type==UNLONG) /* long relations are a mess */
309 if (opdope1[ttree->tn_tr1->n_op]&RELAT && ttree->tn_tr2->n_op==CON
310 && ((struct cnode *)ttree->tn_tr2)->cn_value==0) {
313 return((struct node *)&cone);
315 return((struct node *)&czero);
318 ttree->tn_tr1->n_op = notrel[ttree->tn_tr1->n_op-EQUAL];
320 return(ttree->tn_tr1);
323 ttree->tn_degree = d1==d2? d1+islong(ttree->tn_type): max(d1, d2);
326 return((struct node *)ttree);
329 /* in reality this can only be called with a struct tnode argument */
330 struct node *unoptim(tree) register struct node *tree; {
331 register struct node *subtre, *p;
333 #define ttree ((struct tnode *)tree)
337 if (ttree->tn_op==AMPER && ttree->tn_tr1->n_op==STAR) {
338 subtre = ((struct tnode *)ttree->tn_tr1)->tn_tr1;
339 subtre->n_type = ttree->tn_type;
340 return(optim(subtre));
342 subtre = ttree->tn_tr1 = optim(ttree->tn_tr1);
343 switch (ttree->tn_op) {
347 if (ttree->tn_type!=subtre->n_type)
348 paint(subtre, ttree->tn_type);
352 if (subtre->n_op==CON && subtre->n_type==INT && ((struct cnode *)subtre)->cn_value<0) {
354 #define csubtre ((struct cnode *)subtre)
355 tree = getblk(sizeof(struct lnode));
356 #define ltree ((struct lnode *)tree)
358 ltree->ln_type = LONG;
359 ltree->ln_lvalue = csubtre->cn_value;
360 return((struct node *)ltree);
361 #define ttree ((struct tnode *)tree)
368 if (uns((struct node *)ttree)) {
370 ttree->tn_type = LONG;
371 /*t*/tree = (struct node *)tnode(LTOI, UNSIGN, (struct node *)ttree, (struct node *)NULL);
376 if (subtre->n_op==LCON) {
378 #define lsubtre ((struct lnode *)subtre)
379 tree = getblk(sizeof(struct fnode));
380 #define ftree ((struct fnode *)tree)
382 ftree->fn_type = DOUBLE;
383 ftree->fn_value = isn1++;
385 ftree->fn_fvalue = lsubtre->ln_lvalue;
387 ftree->fn_fvalue = fp_long_to_double(lsubtre->ln_lvalue);
389 return(optim((struct node *)ftree));
390 #define ttree ((struct tnode *)tree)
394 if (subtre->n_type==UNLONG)
395 ttree->tn_op = ULTOF;
399 if (subtre->n_op==CON) {
401 #define csubtre ((struct cnode *)subtre)
402 tree = getblk(sizeof(struct fnode));
403 #define ftree ((struct fnode *)tree)
405 ftree->fn_type = DOUBLE;
406 ftree->fn_value = isn1++;
408 if (uns((struct node *)subtre))
409 ftree->fn_fvalue = (_UNSIGNED_INT)csubtre->cn_value;
411 ftree->fn_fvalue = csubtre->cn_value;
413 /* revisit the unsigned case */
414 if (uns((struct node *)subtre))
415 ftree->fn_fvalue = fp_long_to_double((_LONG)(_UNSIGNED_INT)csubtre->cn_value);
417 ftree->fn_fvalue = fp_int_to_double(csubtre->cn_value);
419 return(optim((struct node *)ftree));
420 #define ttree ((struct tnode *)tree)
425 ttree->tn_tr1 = (struct node *)tnode(ITOL, LONG, subtre, (struct node *)NULL);
427 return(optim((struct node *)ttree));
433 * Sign-extend PDP-11 characters
435 if (subtre->n_op==CON) {
436 #define csubtre ((struct cnode *)subtre)
437 csubtre->cn_type = ttree->tn_type;
438 csubtre->cn_value = (char)csubtre->cn_value;
439 return((struct node *)csubtre);
441 } else if (subtre->n_op==NAME && ttree->tn_type==INT) {
442 subtre->n_type = CHAR;
448 switch (subtre->n_op) {
451 #define csubtre ((struct cnode *)subtre)
452 csubtre->cn_op = CON;
453 csubtre->cn_type = ttree->tn_type;
454 csubtre->cn_value = ((struct lnode *)csubtre)->ln_lvalue;
455 return((struct node *)csubtre);
459 #define nsubtre ((struct nnode *)subtre)
460 nsubtre->nn_offset += 2;
461 nsubtre->nn_type = ttree->tn_type;
462 return((struct node *)nsubtre);
466 #define tsubtre ((struct tnode *)subtre)
467 tsubtre->tn_type = ttree->tn_type;
468 tsubtre->tn_tr1->n_type = ttree->tn_type+PTR;
469 tsubtre->tn_tr1 = (struct node *)tnode(PLUS, ttree->tn_type, tsubtre->tn_tr1, (struct node *)tconst(2, INT));
470 return(optim((struct node *)tsubtre));
474 #define tsubtre ((struct tnode *)subtre)
475 return(paint(tsubtre->tn_tr1, ttree->tn_type));
484 #define tsubtre ((struct tnode *)subtre)
485 tsubtre->tn_tr2 = (struct node *)tnode(LTOI, ttree->tn_type, tsubtre->tn_tr2, (struct node *)NULL);
488 tsubtre->tn_tr1 = (struct node *)tnode(LTOI, ttree->tn_type, tsubtre->tn_tr1, (struct node *)NULL);
489 tsubtre->tn_type = ttree->tn_type;
490 return(optim((struct node *)tsubtre));
497 /* ttree->tn_tr1 = ttree->tn_tr2->tn_tr1;
498 ttree->tn_tr2->tn_tr1 = subtre;
499 ttree->tn_tr2->tn_op = RSHIFT;
500 ttree->tn_tr1->cn_value = (1 << ttree->tn_tr1->cn_value) - 1;*/
501 ttree->tn_tr1 = (struct node *)tconst((1 << ((struct FS *)ttree->tn_tr2)->flen) - 1, INT);
502 ttree->tn_tr2 = (struct node *)tnode(RSHIFT, INT, subtre, (struct node *)tconst(((struct FS *)ttree->tn_tr2)->bitoffs, INT));
503 return(optim((struct node *)ttree));
506 ttree->tn_op = LSHIFT;
507 ttree->tn_type = UNSIGN;
508 /* ttree->tn_tr1 = ttree->tn_tr2;
509 ttree->tn_tr1->tn_op = AND;
510 ttree->tn_tr2 = ttree->tn_tr2->tn_tr2;
511 ttree->tn_tr1->tn_tr2 = subtre;
512 ttree->tn_tr1->tn_tr1->cn_value = (1 << ttree->tn_tr1->tn_tr1->cn_value) -1;*/
513 ttree->tn_tr1 = (struct node *)tnode(AND, INT, (struct node *)tconst((1 << ((struct FS *)ttree->tn_tr2)->flen) - 1, INT), subtre);
514 ttree->tn_tr2 = (struct node *)tconst(((struct FS *)ttree->tn_tr2)->bitoffs, INT);
515 return(optim((struct node *)ttree));
518 if (subtre->n_op==STAR)
519 return(((struct tnode *)subtre)->tn_tr1);
520 if (subtre->n_op==NAME && ((struct nnode *)subtre)->nn_class == OFFS) {
521 #define locnsubtre ((struct locnnode *)subtre)
522 locnsubtre->locnn_type = ttree->tn_type;
524 #define ctree ((struct cnode *)tree)
526 ctree->cn_type = INT;
527 /* the below seems to have been an oversight, probably a harmless one */
528 /* ctree->cn_degree = 0;*/
529 ctree->cn_value = locnsubtre->locnn_offset;
530 locnsubtre->locnn_class = REG;
531 locnsubtre->locnn_nloc = locnsubtre->locnn_regno;
532 locnsubtre->locnn_offset = 0;
533 return(optim((struct node *)tnode(PLUS, locnsubtre->locnn_type, (struct node *)locnsubtre, (struct node *)ctree)));
535 #define ttree ((struct tnode *)tree)
538 if (subtre->n_op==LOAD) {
539 ttree->tn_tr1 = ((struct tnode *)subtre)->tn_tr1;
545 if (subtre->n_op==AMPER) {
546 #define tsubtre ((struct tnode *)subtre)
547 tsubtre->tn_tr1->n_type = ttree->tn_type;
548 return(tsubtre->tn_tr1);
551 if (ttree->tn_type==STRUCT)
553 if (subtre->n_op==NAME && ((struct nnode *)subtre)->nn_class==REG) {
554 #define locnsubtre ((struct locnnode *)subtre)
555 locnsubtre->locnn_type = ttree->tn_type;
556 locnsubtre->locnn_class = OFFS;
557 locnsubtre->locnn_regno = locnsubtre->locnn_nloc;
558 return((struct node *)locnsubtre);
561 if ((subtre->n_op==INCAFT||subtre->n_op==DECBEF)
562 && ttree->tn_type!=LONG && ttree->tn_type!=UNLONG
563 && (p = ((struct tnode *)subtre)->tn_tr1)->n_op==NAME && ((struct nnode *)p)->nn_class==REG && ((struct nnode *)p)->nn_type==((struct tnode *)subtre)->tn_type) {
564 #define tsubtre ((struct tnode *)subtre)
565 #define np ((struct nnode *)p)
566 np->nn_type = ttree->tn_type;
567 np->nn_op = tsubtre->tn_op==INCAFT? AUTOI: AUTOD;
568 return((struct node *)p);
572 if (subtre->n_op==PLUS && (p = ((struct tnode *)subtre)->tn_tr1)->n_op==NAME && ((struct nnode *)p)->nn_class==REG) {
573 #define tsubtre ((struct tnode *)subtre)
574 #define locnp ((struct locnnode *)p)
575 if (tsubtre->tn_tr2->n_op==CON) {
576 locnp->locnn_offset += ((struct cnode *)tsubtre->tn_tr2)->cn_value;
577 locnp->locnn_class = OFFS;
578 locnp->locnn_type = ttree->tn_type;
579 locnp->locnn_regno = locnp->locnn_nloc;
580 return((struct node *)locnp);
582 if (tsubtre->tn_tr2->n_op==AMPER) {
584 subtre = ((struct tnode *)((struct tnode *)subtre)->tn_tr2)->tn_tr1;
585 if (subtre->n_op != NAME) abort();
586 #define nsubtre ((struct nnode *)subtre)
587 nsubtre->nn_class += XOFFS-EXTERN;
588 nsubtre->nn_regno = locnp->locnn_nloc;
589 nsubtre->nn_type = ttree->tn_type;
590 return((struct node *)nsubtre);
591 #define tsubtre ((struct tnode *)subtre)
597 if (subtre->n_op==MINUS && (p = ((struct tnode *)subtre)->tn_tr1)->n_op==NAME && ((struct nnode *)p)->nn_class==REG
598 && ((struct tnode *)subtre)->tn_tr2->n_op==CON) {
599 #define tsubtre ((struct tnode *)subtre)
600 #define locnp ((struct locnnode *)p)
601 locnp->locnn_offset -= ((struct cnode *)tsubtre->tn_tr2)->cn_value;
602 locnp->locnn_class = OFFS;
603 locnp->locnn_type = ttree->tn_type;
604 locnp->locnn_regno = locnp->locnn_nloc;
605 return((struct node *)locnp);
612 if ((opdope1[subtre->n_op]&RELAT)==0)
615 tree->n_op = notrel[tree->n_op-EQUAL];
617 #define ttree ((struct tnode *)tree)
620 if (ttree->tn_type==CHAR)
621 ttree->tn_type = INT;
622 if (subtre->n_op == COMPL)
623 return(paint(((struct tnode *)subtre)->tn_tr1, ttree->tn_type));
624 if (subtre->n_op==CON) {
625 #define csubtre ((struct cnode *)subtre)
626 csubtre->cn_value = ~csubtre->cn_value;
627 return(paint((struct node *)csubtre, ttree->tn_type));
630 if (subtre->n_op==LCON) {
631 #define lsubtre ((struct lnode *)subtre)
632 lsubtre->ln_lvalue = ~lsubtre->ln_lvalue;
633 return((struct node *)lsubtre);
636 if (subtre->n_op==ITOL) {
637 #define tsubtre ((struct tnode *)subtre)
638 if (tsubtre->tn_tr1->n_op==CON) {
640 tree = getblk(sizeof(struct lnode));
641 #define ltree ((struct lnode *)tree)
643 ltree->ln_type = LONG;
644 if (uns(tsubtre->tn_tr1))
645 ltree->ln_lvalue = ~(_LONG)(_UNSIGNED_INT)
646 ((struct cnode *)tsubtre->tn_tr1)->cn_value;
649 ~((struct cnode *)tsubtre->tn_tr1)->cn_value;
650 return((struct node *)ltree);
651 #define ttree ((struct tnode *)tree)
654 if (uns(tsubtre->tn_tr1))
656 tsubtre->tn_op = ttree->tn_op;
657 tsubtre->tn_type = tsubtre->tn_tr1->n_type;
659 ttree->tn_type = LONG;
663 /* previously was a fallthru, but I think it must have been an oversight */
667 if (ttree->tn_type==CHAR)
668 ttree->tn_type = INT;
669 if (subtre->n_op == NEG)
670 return(paint(((struct tnode *)subtre)->tn_tr1, ttree->tn_type));
671 if (subtre->n_op==CON) {
672 #define csubtre ((struct cnode *)subtre)
673 csubtre->cn_value = -csubtre->cn_value;
674 return(paint((struct node *)csubtre, ttree->tn_type));
677 if (subtre->n_op==LCON) {
678 #define lsubtre ((struct lnode *)subtre)
679 lsubtre->ln_lvalue = -lsubtre->ln_lvalue;
680 return((struct node *)lsubtre);
683 if (subtre->n_op==ITOL && ((struct tnode *)subtre)->tn_tr1->n_op==CON) {
684 #define tsubtre ((struct tnode *)subtre)
686 tree = getblk(sizeof(struct lnode));
687 #define ltree ((struct lnode *)tree)
689 ltree->ln_type = LONG;
690 if (uns(tsubtre->tn_tr1))
691 ltree->ln_lvalue = -(_LONG)(_UNSIGNED_INT)
692 ((struct cnode *)tsubtre->tn_tr1)->cn_value;
694 ltree->ln_lvalue = -((struct cnode *)tsubtre->tn_tr1)->cn_value;
695 return((struct node *)ltree);
697 #define ttree ((struct tnode *)tree)
703 if (subtre->n_op==SFCON) {
704 #define fsubtre ((struct fnode *)subtre)
705 fsubtre->fn_value ^= 0100000;
707 fsubtre->fn_fvalue = -fsubtre->fn_fvalue;
709 fsubtre->fn_fvalue = fp_neg(fsubtre->fn_fvalue);
711 return((struct node *)fsubtre);
714 if (subtre->n_op==FCON) {
715 #define fsubtre ((struct fnode *)subtre)
717 fsubtre->fn_fvalue = -fsubtre->fn_fvalue;
719 fsubtre->fn_fvalue = fp_neg(fsubtre->fn_fvalue);
721 return((struct node *)fsubtre);
727 if ((opdope1[tree->n_op]&LEAF)==0)
728 #define ttree ((struct tnode *)tree)
729 ttree->tn_degree = max(islong(ttree->tn_type), degree(subtre));
731 return((struct node *)tree);
735 * Deal with assignments to partial-word fields.
736 * The game is that select(x) += y turns into
737 * select(x += select(y)) where the shifts and masks
738 * are chosen properly. The outer select
739 * is discarded where the value doesn't matter.
740 * Sadly, overflow is undetected on += and the like.
741 * Pure assignment is handled specially.
744 /* note that t->tn_tr1->n_op == FSEL */
745 struct node *lvfield(t) register struct tnode *t; {
746 register struct tnode *t1;
747 register struct fasgn *t2;
752 t2 = (struct fasgn *)getblk(sizeof(struct fasgn));
754 t2->fa_type = UNSIGN;
755 t1 = (struct tnode *)((struct tnode *)t->tn_tr1)->tn_tr2;
756 /* t1 formerly pointed to a COMMA node holding 2 constants */
757 /* now it contains its pass 0 value which is the field descriptor */
758 #define FSt1 ((struct FS *)t1)
759 t2->fa_tr1 = t->tn_tr1;
760 t2->fa_tr2 = t->tn_tr2;
761 t2->fa_mask = ((1<</*t1->tn_tr1->cn_value*/FSt1->flen)-1)<</*t1->tn_tr2->cn_value*/FSt1->bitoffs;
762 t = (struct tnode *)t2;
774 /*t=ASANDN(FSEL(mos,COMMA(flen,bitoffs)),arg)*/
775 t1 = (struct tnode *)t->tn_tr1;
776 /*t1=FSEL(mos,COMMA(flen,bitoffs))*/
778 /*t1=FSELR(mos,COMMA(flen,bitoffs))*/
779 t->tn_tr1 = t1->tn_tr1;
780 /*t=ASANDN(mos,arg)*/
781 t1->tn_tr1 = t->tn_tr2;
782 /*t1=FSELR(arg,COMMA(flen,bitoffs))*/
783 t->tn_tr2 = (struct node *)t1;
784 /*t=ASANDN(mos,FSELR(arg,COMMA(flen,bitoffs)))*/
785 t1 = (struct tnode *)t1->tn_tr2;
786 /*t1=COMMA(flen,bitoffs)*/
787 /*t1 = (struct node *)tnode(COMMA, INT, (struct node *)tconst(t1->tn_tr1->cn_value, INT),
788 (struct node *)tconst(t1->tn_tr2->cn_value, INT));*/
789 /* t1 formerly pointed to a COMMA node holding 2 constants */
790 /* now it contains its pass 0 value which is the field descriptor */
791 #define FSt1 ((struct FS *)t1)
792 return(optim((struct node *)tnode(FSELT, UNSIGN, (struct node *)t, (struct node *)FSt1)));
795 error1("Unimplemented field operator");
796 return((struct node *)t);
799 #if 0 /* now moved to c1.h */
804 struct tnode *nlist[LSTSIZ];
805 struct node *llist[LSTSIZ+1];
809 /* in reality this can only be called with a struct tnode argument */
810 struct node *acommute(tree) register struct node *tree; {
812 int d, i, op, flt, d1, type;
813 register struct node *t1, **t2;
816 #define ttree ((struct tnode *)tree)
820 type = ttree->tn_type;
821 flt = isfloat((struct node *)ttree);
822 insert(op, (struct node *)ttree, &acl);
824 t2 = &acl.llist[acl.nextl];
826 /* put constants together */
827 for (i=acl.nextl; i>0; i--) {
828 d = t2[-1]->n_type==UNSIGN||t2[0]->n_type==UNSIGN?UNSIGN:INT;
829 if (t2[0]->n_op==CON && t2[-1]->n_op==CON) {
832 _const(op, &((struct cnode *)t2[0])->cn_value, ((struct cnode *)t2[1])->cn_value, d);
834 } else if (t = (struct node *)lconst(op, t2[-1], t2[0])) {
841 if (op==PLUS || op==OR) {
843 /* note: cn_value == 0 means a constant value of 0 (CON) or 0. (SFCON) */
844 if (acl.nextl>0 && ((t1 = (struct node *)isconstant(*t2)) && ((struct cnode *)t1)->cn_value==0
845 || (*t2)->n_op==LCON && ((struct lnode *)*t2)->ln_lvalue==0)) {
849 if (acl.nextl <= 0) {
850 if ((*t2)->n_type==CHAR || (*t2)->n_type==UNCHAR)
851 *t2 = (struct node *)tnode(LOAD, ttree->tn_type, *t2, (struct node *)NULL);
852 (*t2)->n_type = ttree->tn_type;
855 /* subsume constant in "&x+c" */
856 if (op==PLUS && t2[0]->n_op==CON && t2[-1]->n_op==AMPER) {
858 ((struct nnode *)((struct tnode *)t2[0])->tn_tr1)->nn_offset += ((struct cnode *)t2[1])->cn_value;
861 } else if (op==TIMES || op==AND) {
862 t1 = acl.llist[acl.nextl];
864 #define ct1 ((struct cnode *)t1)
865 if (ct1->cn_value==0) {
866 for (i=0; i<acl.nextl; i++)
867 if (sideeffects(acl.llist[i]))
870 return((struct node *)ct1);
872 if (op==TIMES && ct1->cn_value==1 && acl.nextl>0)
873 if (--acl.nextl <= 0) {
875 if (uns((struct node *)ttree))
876 paint(t1, ttree->tn_type);
883 if (op==PLUS && !flt)
885 tree = *(t2 = &acl.llist[0]);
886 d = max(degree(tree), islong(tree->n_type));
887 if (op==TIMES && !flt) {
891 for (i=0; i<acl.nextl; i++) {
892 t1 = (struct node *)acl.nlist[i];
893 #define tt1 ((struct tnode *)t1)
894 tt1->tn_tr2 = t = *++t2;
897 * PDP-11 strangeness:
898 * rt. op of ^ must be in a register.
900 if (op==EXOR && dcalc(t, 0)<=12) {
901 tt1->tn_tr2 = t = optim((struct node *)tnode(LOAD, t->n_type, t, (struct node *)NULL));
902 /* in this case optim() is guaranteed to return a struct tnode */
903 if (opdope1[t->n_op] & LEAF) abort();
904 d1 = ((struct tnode *)t)->tn_degree;
906 tt1->tn_degree = d = d==d1? d+islong(tt1->tn_type): max(d, d1);
908 tree = (struct node *)tt1;
909 if (tree->n_type==LONG || tree->n_type==UNLONG) {
910 if (tree->n_op==TIMES)
911 tree = hardlongs(tree);
912 /* assume isconstant() returns cnode (CON) not fnode (SFCON) since long */
913 else if (tree->n_op==PLUS && (t = (struct node *)isconstant(((struct tnode *)tree)->tn_tr1))
914 && ((struct cnode *)t)->cn_value < 0 && !uns(t)) {
915 #define ttree ((struct tnode *)tree)
916 ttree->tn_op = MINUS;
917 ((struct cnode *)t)->cn_value = -((struct cnode *)t)->cn_value;
919 ttree->tn_tr1 = ttree->tn_tr2;
926 if (tree->n_op==TIMES && ispow2((struct tnode *)tree))
927 #define ttree ((struct tnode *)tree)
928 ttree->tn_degree = max(degree(ttree->tn_tr1), islong(ttree->tn_type));
934 int sideeffects(tp) register struct node *tp; {
939 dope = opdope1[tp->n_op];
941 if (tp->n_op==AUTOI || tp->n_op==AUTOD)
945 #define ttp ((struct tnode *)tp)
954 if (sideeffects(ttp->tn_tr1))
957 return(sideeffects(ttp->tn_tr2));
962 void distrib(list) struct acl *list; {
964 * Find a list member of the form c1c2*x such
965 * that c1c2 divides no other such constant, is divided by
966 * at least one other (say in the form c1*y), and which has
967 * fewest divisors. Reduce this pair to c1*(y+c2*x)
968 * and iterate until no reductions occur.
970 register struct node **p1, **p2;
973 struct node **dividend, **divisor;
974 struct node **maxnod, **mindiv;
977 maxnod = &list->llist[list->nextl];
980 for (p1 = list->llist; p1 <= maxnod; p1++) {
981 if ((*p1)->n_op!=TIMES || ((struct tnode *)*p1)->tn_tr2->n_op!=CON)
984 for (p2 = list->llist; p2 <= maxnod; p2++) {
985 if (p1==p2 || (*p2)->n_op!=TIMES || ((struct tnode *)*p2)->tn_tr2->n_op!=CON)
987 if (((struct cnode *)((struct tnode *)*p1)->tn_tr2)->cn_value == ((struct cnode *)((struct tnode *)*p2)->tn_tr2)->cn_value) {
988 ((struct tnode *)*p2)->tn_tr2 = ((struct tnode *)*p1)->tn_tr1;
989 ((struct tnode *)*p2)->tn_op = PLUS;
990 ((struct tnode *)*p1)->tn_tr1 = (struct node *)((struct tnode *)*p2);
996 if ((((struct cnode *)((struct tnode *)*p2)->tn_tr2)->cn_value % ((struct cnode *)((struct tnode *)*p1)->tn_tr2)->cn_value) == 0)
998 if ((((struct cnode *)((struct tnode *)*p1)->tn_tr2)->cn_value % ((struct cnode *)((struct tnode *)*p2)->tn_tr2)->cn_value) == 0) {
1003 if (ndmin > 0 && ndmin < ndmaj) {
1012 #define tt (*(struct tnode **)&t)
1013 if (list->nextn == 0) abort();
1014 tt = list->nlist[--list->nextn];
1018 tt->tn_type = ((struct tnode *)*p1)->tn_type;
1019 tt->tn_tr1 = (struct node *)((struct tnode *)*p1);
1020 tt->tn_tr2 = ((struct tnode *)*p2)->tn_tr1;
1021 ((struct cnode *)((struct tnode *)*p1)->tn_tr2)->cn_value /= ((struct cnode *)((struct tnode *)*p2)->tn_tr2)->cn_value;
1022 ((struct tnode *)*p2)->tn_tr1 = (struct node *)tt;
1036 void squash(p, maxp) struct node **p; struct node **maxp; {
1037 register struct node **np;
1039 for (np = p; np < maxp; np++)
1043 void _const(op, vp, v, type) int op; register _INT *vp; register _INT v; int type; {
1047 (*vp) /= (_UNSIGNED_INT)v;
1075 if (type==UNSIGN && v!=0 && v<=1) {
1076 if (op==UDIV || op==DIVIDE) {
1079 *vp = *(_UNSIGNED_INT *)vp >= (_UNSIGNED_INT)v;
1086 if (*(_UNSIGNED_INT *)vp >= (_UNSIGNED_INT)v)
1092 werror1("divide check");
1095 if (op==DIVIDE || op==UDIV)
1100 if (op==DIVIDE || op==UDIV)
1101 *(_UNSIGNED_INT *)vp /= (_UNSIGNED_INT)v;
1103 *(_UNSIGNED_INT *)vp %= (_UNSIGNED_INT)v;
1115 *(_UNSIGNED_INT *)vp >>= (_UNSIGNED_INT)v;
1130 *(_UNSIGNED_INT *)vp <<= (_UNSIGNED_INT)v;
1137 error1("C error: const");
1140 struct lnode *lconst(op, lp, rp) int op; register struct node *lp; register struct node *rp; {
1141 _UNSIGNED_LONG l, r;
1144 l = ((struct lnode *)lp)->ln_lvalue;
1145 else if (lp->n_op==ITOL && ((struct tnode *)lp)->tn_tr1->n_op==CON) {
1146 #define tlp ((struct tnode *)lp)
1147 if (tlp->tn_tr1->n_type==INT)
1148 l = ((struct cnode *)tlp->tn_tr1)->cn_value;
1150 l = (_UNSIGNED_INT)((struct cnode *)tlp->tn_tr1)->cn_value;
1155 r = ((struct lnode *)rp)->ln_lvalue;
1156 else if (rp->n_op==ITOL && ((struct tnode *)rp)->tn_tr1->n_op==CON) {
1157 #define trp ((struct tnode *)rp)
1158 if (trp->tn_tr1->n_type==INT)
1159 r = ((struct cnode *)trp->tn_tr1)->cn_value;
1161 r = (_UNSIGNED_INT)((struct cnode *)trp->tn_tr1)->cn_value;
1183 error1("Divide check");
1191 error1("Divide check");
1223 if (lp->n_op==LCON) {
1224 #define llp ((struct lnode *)lp)
1229 lp = getblk(sizeof(struct lnode));
1230 #define llp ((struct lnode *)lp)
1232 llp->ln_type = LONG;
1238 void insert(op, tree, list) int op; register struct node *tree; register struct acl *list; {
1244 if (tree->n_op != op)
1246 if (tree->n_op == op && list->nextn < LSTSIZ-2) {
1247 #define ttree ((struct tnode *)tree)
1248 list->nlist[list->nextn++] = ttree;
1249 insert(op, ttree->tn_tr1, list);
1250 insert(op, ttree->tn_tr2, list);
1254 if (!isfloat(tree)) {
1255 /* c1*(x+c2) -> c1*x+c1*c2 */
1256 if ((tree->n_op==TIMES||tree->n_op==LSHIFT)
1257 && ((struct tnode *)tree)->tn_tr2->n_op==CON && ((struct cnode *)((struct tnode *)tree)->tn_tr2)->cn_value>0
1258 && ((struct tnode *)tree)->tn_tr1->n_op==PLUS && ((struct tnode *)((struct tnode *)tree)->tn_tr1)->tn_tr2->n_op==CON) {
1259 #define ttree ((struct tnode *)tree)
1260 d = ((struct cnode *)ttree->tn_tr2)->cn_value;
1261 if (ttree->tn_op==TIMES)
1262 ((struct cnode *)ttree->tn_tr2)->cn_value *= ((struct cnode *)((struct tnode *)ttree->tn_tr1)->tn_tr2)->cn_value;
1264 ((struct cnode *)ttree->tn_tr2)->cn_value = ((struct cnode *)((struct tnode *)ttree->tn_tr1)->tn_tr2)->cn_value << d;
1265 ((struct cnode *)((struct tnode *)ttree->tn_tr1)->tn_tr2)->cn_value = d;
1266 ((struct tnode *)ttree->tn_tr1)->tn_op = ttree->tn_op;
1267 ttree->tn_op = PLUS;
1275 for (i=0; i<list->nextl; i++) {
1276 if ((d1=degree(list->llist[i]))<d) {
1278 list->llist[i] = tree;
1283 list->llist[list->nextl++] = tree;
1286 struct tnode *tnode(op, type, tr1, tr2) int op; int type; struct node *tr1; struct node *tr2; {
1287 register struct tnode *p;
1289 p = (struct tnode *)getblk(sizeof(struct tnode));
1292 p->tn_subsp = (int *)NULL;
1293 p->tn_strp = (union str *)NULL;
1300 struct cnode *tconst(val, type) int val; int type; {
1301 register struct cnode *p;
1303 p = (struct cnode *)getblk(sizeof(struct cnode));
1306 p->cn_subsp = (int *)NULL;
1307 p->cn_strp = (union str *)NULL;
1312 struct node *getblk(size) int size; {
1314 return (struct node *)Tblock(size);
1316 register struct node *p;
1320 p = (struct node *)curbase;
1321 if ((curbase += size) >= coremax) {
1323 if (sbrk(1024) == (char *)-1) {
1325 if (sbrk(1024) != coremax) {
1327 error1("Out of space-- c1");
1336 int islong(t) int t; {
1337 if (t==LONG || t==UNLONG)
1342 /* returns a struct cnode, may be a struct fnode containing struct cnode */
1343 struct cnode *isconstant(t) register struct node *t; {
1344 if (t->n_op==CON || t->n_op==SFCON)
1345 return((struct cnode *)t);
1346 if (t->n_op==ITOL && ((struct tnode *)t)->tn_tr1->n_op==CON)
1347 return((struct cnode *)((struct tnode *)t)->tn_tr1);
1351 struct node *hardlongs(t) register struct node *t; {
1357 #define tt ((struct tnode *)t)
1358 if (tt->tn_type == UNLONG)
1359 tt->tn_op += ULTIMES-TIMES;
1361 tt->tn_op += LTIMES-TIMES;
1368 #define tt ((struct tnode *)t)
1369 if (tt->tn_type == UNLONG)
1370 tt->tn_op += ULASTIMES-ASTIMES;
1372 tt->tn_op += LASTIMES-ASTIMES;
1373 tt->tn_tr1 = (struct node *)tnode(AMPER, LONG+PTR, tt->tn_tr1, (struct node *)NULL);
1384 * Is tree of unsigned type?
1386 int uns(tp) struct node *tp; {
1390 if (t==UNSIGN || t==UNCHAR || t==UNLONG || t&XTYPE)