Add tests, fixes for tests, reinstate and type-convert stuff marked "bitrot"
[ccom.git] / c12.c
1 /*
2  *              C compiler part 2 -- expression optimizer
3  */
4
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include "c0.h" /* for Tblock() which replaces getblk() in single pass mode */
8 #include "c1.h"
9
10 /*
11  * Macros for fast min/max.
12  */
13 #define min(a,b) (((a)<(b))?(a):(b))
14 #define max(a,b) (((a)>(b))?(a):(b))
15
16 struct node *optim(tree) register struct node *tree; {
17         register int op, dope;
18 #ifdef pdp11
19         union { double dv; _INT iv[4];} fp11;
20 #endif
21
22         if (tree==NULL)
23                 return(NULL);
24         if ((op = tree->n_op)==0)
25                 return(tree);
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;
31 #undef locntree
32         }
33         dope = opdope1[op];
34         if ((dope&LEAF) != 0) {
35                 if (op==FCON) {
36 #define ftree ((struct fnode *)tree)
37 #ifdef pdp11
38                         fp11.dv = ftree->fn_fvalue;
39                         if (fp11.iv[1]==0
40                          && fp11.iv[2]==0
41                          && fp11.iv[3]==0) {
42                                 ftree->fn_op = SFCON;
43                                 ftree->fn_value = fp11.iv[0];
44                         }
45 #else
46                         if (ftree->fn_fvalue.l==0
47                          && (ftree->fn_fvalue.h & 0xffff)==0) {
48                                 ftree->fn_op = SFCON;
49                                 ftree->fn_value = (int)(ftree->fn_fvalue.h >> 16) & 0xffff;
50                         }
51 #endif
52 #undef ftree
53                 }
54                 return(tree);
55         }
56         if ((dope&BINARY) == 0)
57                 return(unoptim(tree));
58         return(binoptim(tree));
59 }
60
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;
64         int d1, d2;
65         struct node *t;
66
67 #define ttree ((struct tnode *)tree)
68         if (ttree->tn_type==CHAR)
69                 ttree->tn_type = INT;
70         switch(ttree->tn_op) {
71         /*
72          * PDP-11 special:
73          * generate new &=~ operator out of &=
74          * by complementing the RHS.
75          */
76         case ASAND:
77                 ttree->tn_op = ASANDN;
78                 ttree->tn_tr2 = (struct node *)tnode(COMPL, ttree->tn_tr2->n_type, ttree->tn_tr2, (struct node *)NULL);
79                 break;
80
81         /*
82          * On the PDP-11, int->ptr via multiplication
83          * Longs are just truncated.
84          */
85         case LTOP:
86                 ttree->tn_op = ITOP;
87                 ttree->tn_tr1 = unoptim((struct node *)tnode(LTOI,INT,ttree->tn_tr1, (struct node *)NULL));
88         case ITOP:
89                 ttree->tn_op = TIMES;
90                 break;
91
92         case MINUS:
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)) {
96                         ttree->tn_op = PLUS;
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;
101                         } else
102                                 ((struct cnode *)t)->cn_value = -((struct cnode *)t)->cn_value;
103                 }
104                 break;
105         }
106         op = ttree->tn_op;
107         dope = opdope1[op];
108         if (dope&LVALUE && ttree->tn_tr1->n_op==FSEL)
109                 return(lvfield(ttree));
110         if ((dope&COMMUTE)!=0) {
111                 d1 = ttree->tn_type;
112 #undef ttree
113                 tree = acommute(tree);
114                 if (tree->n_op == op)
115                         tree->n_type = d1;
116                 /*
117                  * PDP-11 special:
118                  * replace a&b by a ANDN ~ b.
119                  * This will be undone when in
120                  * truth-value context.
121                  */
122                 if (tree->n_op!=AND)
123                         return(tree);
124 #define ttree ((struct tnode *)tree)
125                 /*
126                  * long & pos-int is simpler
127                  */
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;
132                         t = ttree->tn_tr2;
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);
136                         return(optim(t));
137                 }
138                 /*
139                  * Keep constants to the right
140                  */
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) {
143                         t = ttree->tn_tr1;
144                         ttree->tn_tr1 = ttree->tn_tr2;
145                         ttree->tn_tr2 = t;
146                 }
147                 ttree->tn_op = ANDN;
148                 op = ANDN;
149                 ttree->tn_tr2 = (struct node *)tnode(COMPL, ttree->tn_tr2->n_type, ttree->tn_tr2, (struct node *)NULL);
150         }
151     again:
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);
156                 if (t)
157                         return(t);
158         }
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) {
162                         t = ttree->tn_tr1;
163                         ttree->tn_tr1 = ttree->tn_tr2;
164                         ttree->tn_tr2 = t;
165                         ttree->tn_op = maprel[op-EQUAL];
166                 }
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;
171         }
172         d1 = max(degree(ttree->tn_tr1), islong(ttree->tn_type));
173         d2 = max(degree(ttree->tn_tr2), 0);
174         switch (op) {
175
176         /*
177          * In assignment to fields, treat all-zero and all-1 specially.
178          */
179         case FSELA:
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));
185                 }
186                 if (Ftree->fa_tr2->n_op==CON && Ftree->fa_mask==((struct cnode *)Ftree->fa_tr2)->cn_value) {
187                         Ftree->fa_op = ASOR;
188                         return(optim((struct node *)Ftree));
189                 }
190 #undef Ftree
191
192         case LTIMES:
193         case LDIV:
194         case LMOD:
195         case LASTIMES:
196         case LASDIV:
197         case LASMOD:
198         case UDIV:
199         case UMOD:
200         case ASUDIV:
201         case ASUMOD:
202         case ULASMOD:
203         case ULTIMES:
204         case ULDIV:
205         case ULMOD:
206         case ULASTIMES:
207         case ULASDIV:
208                 ttree->tn_degree = 10;
209                 break;
210
211         case ANDN:
212                 if (isconstant(ttree->tn_tr2) && ((struct cnode *)ttree->tn_tr2)->cn_value==0) {
213                         return(ttree->tn_tr1);
214                 }
215                 goto def;
216
217         case CALL:
218                 ttree->tn_degree = 10;
219                 break;
220
221         case QUEST:
222         case COLON:
223                 ttree->tn_degree = max(d1, d2);
224                 break;
225
226         case PTOI:
227         case DIVIDE:
228         case ASDIV:
229         case ASTIMES:
230                 if (ttree->tn_tr2->n_op==CON && ((struct cnode *)ttree->tn_tr2)->cn_value==1) {
231                         if (op==PTOI)
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));
234                 }
235         case MOD:
236         case ASMOD:
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;
242                 }
243         case ULSH:
244         case ASULSH:
245                 d1 += 2 + regpanic;
246                 d2 += 2 + regpanic;
247                 panicposs++;
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)) {
253                         if (op>=ASDIV) {
254                                 ttree->tn_op += ASUDIV - ASDIV;
255                         } else
256                                 ttree->tn_op += UDIV - DIVIDE;
257                         d1 = d2 = 10;
258                 }
259                 goto constant;
260
261         case ASPLUS:
262         case ASMINUS:
263                 if (ttree->tn_tr2->n_op==CON && ((struct cnode *)ttree->tn_tr2)->cn_value==0)
264                         return(ttree->tn_tr1);
265                 goto def;
266
267         case LSHIFT:
268         case RSHIFT:
269         case ASRSH:
270         case ASLSH:
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));
273                 /*
274                  * PDP-11 special: turn right shifts into negative
275                  * left shifts
276                  */
277                 if (ttree->tn_type == LONG || ttree->tn_type==UNLONG) {
278                         d1++;
279                         d2++;
280                 }
281                 if (op==LSHIFT||op==ASLSH)
282                         goto constant;
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))
285                         goto constant;
286                 op += (LSHIFT-RSHIFT);
287                 ttree->tn_op = op;
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)
291                                 ttree->tn_op = ULSH;
292                         else if (ttree->tn_op==ASLSH)
293                                 ttree->tn_op = ASULSH;
294                 }
295                 goto again;
296
297         constant:
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);
301                 }
302
303
304         def:
305         default:
306                 if (dope&RELAT) {
307                         if (ttree->tn_tr1->n_type==LONG || ttree->tn_tr1->n_type==UNLONG)       /* long relations are a mess */
308                                 d1 = 10;
309                         if (opdope1[ttree->tn_tr1->n_op]&RELAT && ttree->tn_tr2->n_op==CON
310                          && ((struct cnode *)ttree->tn_tr2)->cn_value==0) {
311                                 switch(op) {
312                                 case GREATEQ:
313                                         return((struct node *)&cone);
314                                 case LESS:
315                                         return((struct node *)&czero);
316                                 case LESSEQ:
317                                 case EQUAL:
318                                         ttree->tn_tr1->n_op = notrel[ttree->tn_tr1->n_op-EQUAL];
319                                 }
320                                 return(ttree->tn_tr1);
321                         }
322                 }
323                 ttree->tn_degree = d1==d2? d1+islong(ttree->tn_type): max(d1, d2);
324                 break;
325         }
326         return((struct node *)ttree);
327 }
328
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;
332
333 #define ttree ((struct tnode *)tree)
334         if (ttree==NULL)
335                 return(NULL);
336     again:
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));
341         }
342         subtre = ttree->tn_tr1 = optim(ttree->tn_tr1);
343         switch (ttree->tn_op) {
344
345         case INCAFT:
346         case DECAFT:
347                 if (ttree->tn_type!=subtre->n_type) 
348                         paint(subtre, ttree->tn_type);
349                 break;
350
351         case ITOL:
352                 if (subtre->n_op==CON && subtre->n_type==INT && ((struct cnode *)subtre)->cn_value<0) {
353 #undef ttree
354 #define csubtre ((struct cnode *)subtre)
355                         tree = getblk(sizeof(struct lnode));
356 #define ltree ((struct lnode *)tree)
357                         ltree->ln_op = LCON;
358                         ltree->ln_type = LONG;
359                         ltree->ln_lvalue = csubtre->cn_value;
360                         return((struct node *)ltree);
361 #define ttree ((struct tnode *)tree)
362 #undef csubtre
363 #undef ltree
364                 }
365                 break;
366
367         case FTOI:
368                 if (uns((struct node *)ttree)) {
369                         ttree->tn_op = FTOL;
370                         ttree->tn_type = LONG;
371                         /*t*/tree = (struct node *)tnode(LTOI, UNSIGN, (struct node *)ttree, (struct node *)NULL);
372                 }
373                 break;
374
375         case LTOF:
376                 if (subtre->n_op==LCON) {
377 #undef ttree
378 #define lsubtre ((struct lnode *)subtre)
379                         tree = getblk(sizeof(struct fnode));
380 #define ftree ((struct fnode *)tree)
381                         ftree->fn_op = FCON;
382                         ftree->fn_type = DOUBLE;
383                         ftree->fn_value = isn1++;
384 #ifdef pdp11
385                         ftree->fn_fvalue = lsubtre->ln_lvalue;
386 #else
387                         ftree->fn_fvalue = fp_long_to_double(lsubtre->ln_lvalue);
388 #endif
389                         return(optim((struct node *)ftree));
390 #define ttree ((struct tnode *)tree)
391 #undef lsubtre
392 #undef ftree
393                 }
394                 if (subtre->n_type==UNLONG) 
395                         ttree->tn_op = ULTOF;
396                 break;
397
398         case ITOF:
399                 if (subtre->n_op==CON) {
400 #undef ttree
401 #define csubtre ((struct cnode *)subtre)
402                         tree = getblk(sizeof(struct fnode));
403 #define ftree ((struct fnode *)tree)
404                         ftree->fn_op = FCON;
405                         ftree->fn_type = DOUBLE;
406                         ftree->fn_value = isn1++;
407 #ifdef pdp11
408                         if (uns((struct node *)subtre))
409                                 ftree->fn_fvalue = (_UNSIGNED_INT)csubtre->cn_value;
410                         else
411                                 ftree->fn_fvalue = csubtre->cn_value;
412 #else
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);
416                         else
417                                 ftree->fn_fvalue = fp_int_to_double(csubtre->cn_value);
418 #endif
419                         return(optim((struct node *)ftree));
420 #define ttree ((struct tnode *)tree)
421 #undef csubtre
422 #undef ftree
423                 }
424                 if (uns(subtre)) {
425                         ttree->tn_tr1 = (struct node *)tnode(ITOL, LONG, subtre, (struct node *)NULL);
426                         ttree->tn_op = LTOF;
427                         return(optim((struct node *)ttree));
428                 }
429                 break;
430
431         case ITOC:
432                 /*
433                  * Sign-extend PDP-11 characters
434                  */
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);
440 #undef csubtre
441                 } else if (subtre->n_op==NAME && ttree->tn_type==INT) {
442                         subtre->n_type = CHAR;
443                         return(subtre);
444                 }
445                 break;
446
447         case LTOI:
448                 switch (subtre->n_op) {
449
450                 case LCON:
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);
456 #undef csubtre
457
458                 case NAME:
459 #define nsubtre ((struct nnode *)subtre)
460                         nsubtre->nn_offset += 2;
461                         nsubtre->nn_type = ttree->tn_type;
462                         return((struct node *)nsubtre);
463 #undef nsubtre
464
465                 case STAR:
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));
471 #undef tsubtre
472
473                 case ITOL:
474 #define tsubtre ((struct tnode *)subtre)
475                         return(paint(tsubtre->tn_tr1, ttree->tn_type));
476 #undef tsubtre
477
478                 case PLUS:
479                 case MINUS:
480                 case AND:
481                 case ANDN:
482                 case OR:
483                 case EXOR:
484 #define tsubtre ((struct tnode *)subtre)
485                         tsubtre->tn_tr2 = (struct node *)tnode(LTOI, ttree->tn_type, tsubtre->tn_tr2, (struct node *)NULL);
486                 case NEG:
487                 case COMPL:
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));
491 #undef tsubtre
492                 }
493                 break;
494
495         case FSEL:
496                 ttree->tn_op = AND;
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));
504
505         case FSELR:
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));
516
517         case AMPER:
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;
523 #undef ttree
524 #define ctree ((struct cnode *)tree)
525                         ctree->cn_op = CON;
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)));
534 #undef nsubtre
535 #define ttree ((struct tnode *)tree)
536 #undef ctree
537                 }
538                 if (subtre->n_op==LOAD) {
539                         ttree->tn_tr1 = ((struct tnode *)subtre)->tn_tr1;
540                         goto again;
541                 }
542                 break;
543
544         case STAR:
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);
549 #undef tsubtre
550                 }
551                 if (ttree->tn_type==STRUCT)
552                         break;
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);
559 #undef locnsubtre
560                 }
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);
569 #undef tsubtre
570 #undef np
571                 }
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);
581                         }
582                         if (tsubtre->tn_tr2->n_op==AMPER) {
583 #undef tsubtre
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)
592 #undef nsubtre
593                         }
594 #undef tsubtre
595 #undef locnp
596                 }
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);
606 #undef tsubtre
607 #undef locnp
608                 }
609                 break;
610         case EXCLA:
611 #undef ttree
612                 if ((opdope1[subtre->n_op]&RELAT)==0)
613                         break;
614                 tree = subtre;
615                 tree->n_op = notrel[tree->n_op-EQUAL];
616                 break;
617 #define ttree ((struct tnode *)tree)
618
619         case COMPL:
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));
628 #undef csubtre
629                 }
630                 if (subtre->n_op==LCON) {
631 #define lsubtre ((struct lnode *)subtre)
632                         lsubtre->ln_lvalue = ~lsubtre->ln_lvalue;
633                         return((struct node *)lsubtre);
634 #undef lsubtre
635                 }
636                 if (subtre->n_op==ITOL) {
637 #define tsubtre ((struct tnode *)subtre)
638                         if (tsubtre->tn_tr1->n_op==CON) {
639 #undef ttree
640                                 tree = getblk(sizeof(struct lnode));
641 #define ltree ((struct lnode *)tree)
642                                 ltree->ln_op = LCON;
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;
647                                 else
648                                         ltree->ln_lvalue =
649                                                 ~((struct cnode *)tsubtre->tn_tr1)->cn_value;
650                                 return((struct node *)ltree);
651 #define ttree ((struct tnode *)tree)
652 #undef ltree
653                         }
654                         if (uns(tsubtre->tn_tr1))
655                                 break;
656                         tsubtre->tn_op = ttree->tn_op;
657                         tsubtre->tn_type = tsubtre->tn_tr1->n_type;
658                         ttree->tn_op = ITOL;
659                         ttree->tn_type = LONG;
660                         goto again;
661 #undef tsubtre
662                 }
663  /* previously was a fallthru, but I think it must have been an oversight */
664  break;
665
666         case NEG:
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));
675 #undef csubtre
676                 }
677                 if (subtre->n_op==LCON) {
678 #define lsubtre ((struct lnode *)subtre)
679                         lsubtre->ln_lvalue = -lsubtre->ln_lvalue;
680                         return((struct node *)lsubtre);
681 #undef lsubtre
682                 }
683                 if (subtre->n_op==ITOL && ((struct tnode *)subtre)->tn_tr1->n_op==CON) {
684 #define tsubtre ((struct tnode *)subtre)
685 #undef ttree
686                         tree = getblk(sizeof(struct lnode));
687 #define ltree ((struct lnode *)tree)
688                         ltree->ln_op = LCON;
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;
693                         else
694                                 ltree->ln_lvalue = -((struct cnode *)tsubtre->tn_tr1)->cn_value;
695                         return((struct node *)ltree);
696 #undef tsubtre
697 #define ttree ((struct tnode *)tree)
698 #undef ltree
699                 }
700                 /*
701                  * PDP-11 FP negation
702                  */
703                 if (subtre->n_op==SFCON) {
704 #define fsubtre ((struct fnode *)subtre)
705                         fsubtre->fn_value ^= 0100000;
706 #ifdef pdp11
707                         fsubtre->fn_fvalue = -fsubtre->fn_fvalue;
708 #else
709                         fsubtre->fn_fvalue = fp_neg(fsubtre->fn_fvalue);
710 #endif
711                         return((struct node *)fsubtre);
712 #undef fsubtre
713                 }
714                 if (subtre->n_op==FCON) {
715 #define fsubtre ((struct fnode *)subtre)
716 #ifdef pdp11
717                         fsubtre->fn_fvalue = -fsubtre->fn_fvalue;
718 #else
719                         fsubtre->fn_fvalue = fp_neg(fsubtre->fn_fvalue);
720 #endif
721                         return((struct node *)fsubtre);
722 #undef fsubtre
723                 }
724                 break;
725         }
726 #undef ttree
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));
730 #undef ttree
731         return((struct node *)tree);
732 }
733
734 /*
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.
742  */
743
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;
748
749         switch (t->tn_op) {
750
751         case ASSIGN:
752                 t2 = (struct fasgn *)getblk(sizeof(struct fasgn));
753                 t2->fa_op = FSELA;
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;
763 #undef FSt1
764
765         case ASANDN:
766         case ASPLUS:
767         case ASMINUS:
768         case ASOR:
769         case ASXOR:
770         case INCBEF:
771         case INCAFT:
772         case DECBEF:
773         case DECAFT:
774  /*t=ASANDN(FSEL(mos,COMMA(flen,bitoffs)),arg)*/
775                 t1 = (struct tnode *)t->tn_tr1;
776  /*t1=FSEL(mos,COMMA(flen,bitoffs))*/
777                 t1->tn_op = FSELR;
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)));
793 #undef FSt1
794         }
795         error1("Unimplemented field operator");
796         return((struct node *)t);
797 }
798
799 #if 0 /* now moved to c1.h */
800 #define LSTSIZ  20
801 struct acl {
802         int nextl;
803         int nextn;
804         struct tnode *nlist[LSTSIZ];
805         struct node *llist[LSTSIZ+1];
806 };
807 #endif
808
809 /* in reality this can only be called with a struct tnode argument */
810 struct node *acommute(tree) register struct node *tree; {
811         struct acl acl;
812         int d, i, op, flt, d1, type;
813         register struct node *t1, **t2;
814         struct node *t;
815
816 #define ttree ((struct tnode *)tree)
817         acl.nextl = 0;
818         acl.nextn = 0;
819         op = ttree->tn_op;
820         type = ttree->tn_type;
821         flt = isfloat((struct node *)ttree);
822         insert(op, (struct node *)ttree, &acl);
823         acl.nextl--;
824         t2 = &acl.llist[acl.nextl];
825         if (!flt) {
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) {
830                                 acl.nextl--;
831                                 t2--;
832                                 _const(op, &((struct cnode *)t2[0])->cn_value, ((struct cnode *)t2[1])->cn_value, d);
833                                 t2[0]->n_type = d;
834                         } else if (t = (struct node *)lconst(op, t2[-1], t2[0])) {
835                                 acl.nextl--;
836                                 t2--;
837                                 t2[0] = t;
838                         }
839                 }
840         }
841         if (op==PLUS || op==OR) {
842                 /* toss out "+0" */
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)) {
846                         acl.nextl--;
847                         t2--;
848                 }
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;
853                         return(*t2);
854                 }
855                 /* subsume constant in "&x+c" */
856                 if (op==PLUS && t2[0]->n_op==CON && t2[-1]->n_op==AMPER) {
857                         t2--;
858                         ((struct nnode *)((struct tnode *)t2[0])->tn_tr1)->nn_offset += ((struct cnode *)t2[1])->cn_value;
859                         acl.nextl--;
860                 }
861         } else if (op==TIMES || op==AND) {
862                 t1 = acl.llist[acl.nextl];
863                 if (t1->n_op==CON) {
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]))
868                                                 break;
869                                 if (i==acl.nextl)
870                                         return((struct node *)ct1);
871                         }
872                         if (op==TIMES && ct1->cn_value==1 && acl.nextl>0)
873                                 if (--acl.nextl <= 0) {
874                                         t1 = acl.llist[0];
875                                         if (uns((struct node *)ttree))
876                                                 paint(t1, ttree->tn_type);
877                                         return(t1);
878                                 }
879 #undef ct1
880                 }
881         }
882 #undef ttree
883         if (op==PLUS && !flt)
884                 distrib(&acl);
885         tree = *(t2 = &acl.llist[0]);
886         d = max(degree(tree), islong(tree->n_type));
887         if (op==TIMES && !flt) {
888                 d += regpanic+1;
889                 panicposs++;
890         }
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;
895                 d1 = degree(t);
896                 /*
897                  * PDP-11 strangeness:
898                  * rt. op of ^ must be in a register.
899                  */
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;
905                 }
906                 tt1->tn_degree = d = d==d1? d+islong(tt1->tn_type): max(d, d1);
907                 tt1->tn_tr1 = tree;
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;
918                                 t = ttree->tn_tr1;
919                                 ttree->tn_tr1 = ttree->tn_tr2;
920                                 ttree->tn_tr2 = t;
921 #undef ttree
922                         }
923                 }
924 #undef tt1
925         }
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));
929 #undef ttree
930         paint(tree, type);
931         return(tree);
932 }
933
934 int sideeffects(tp) register struct node *tp; {
935         register int dope;
936
937         if (tp==NULL)
938                 return(0);
939         dope = opdope1[tp->n_op];
940         if (dope&LEAF) {
941                 if (tp->n_op==AUTOI || tp->n_op==AUTOD)
942                         return(1);
943                 return(0);
944         }
945 #define ttp ((struct tnode *)tp)
946         if (dope&ASSGOP)
947                 return(1);
948         switch(ttp->tn_op) {
949         case CALL:
950         case FSELA:
951         case STRASG:
952                 return(1);
953         }
954         if (sideeffects(ttp->tn_tr1))
955                 return(1);
956         if (dope&BINARY)
957                 return(sideeffects(ttp->tn_tr2));
958         return(0);
959 #undef ttp
960 }
961
962 void distrib(list) struct acl *list; {
963 /*
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.
969  */
970         register struct node **p1, **p2;
971         struct node *t;
972         int ndmaj, ndmin;
973         struct node **dividend, **divisor;
974         struct node **maxnod, **mindiv;
975
976     loop:
977         maxnod = &list->llist[list->nextl];
978         ndmaj = 1000;
979         dividend = 0;
980         for (p1 = list->llist; p1 <= maxnod; p1++) {
981                 if ((*p1)->n_op!=TIMES || ((struct tnode *)*p1)->tn_tr2->n_op!=CON)
982                         continue;
983                 ndmin = 0;
984                 for (p2 = list->llist; p2 <= maxnod; p2++) {
985                         if (p1==p2 || (*p2)->n_op!=TIMES || ((struct tnode *)*p2)->tn_tr2->n_op!=CON)
986                                 continue;
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);
991                                 *p1 = optim(*p1);
992                                 squash(p2, maxnod);
993                                 list->nextl--;
994                                 goto loop;
995                         }
996                         if ((((struct cnode *)((struct tnode *)*p2)->tn_tr2)->cn_value % ((struct cnode *)((struct tnode *)*p1)->tn_tr2)->cn_value) == 0)
997                                 goto contmaj;
998                         if ((((struct cnode *)((struct tnode *)*p1)->tn_tr2)->cn_value % ((struct cnode *)((struct tnode *)*p2)->tn_tr2)->cn_value) == 0) {
999                                 ndmin++;
1000                                 mindiv = p2;
1001                         }
1002                 }
1003                 if (ndmin > 0 && ndmin < ndmaj) {
1004                         ndmaj = ndmin;
1005                         dividend = p1;
1006                         divisor = mindiv;
1007                 }
1008     contmaj:;
1009         }
1010         if (dividend==0)
1011                 return;
1012 #define tt (*(struct tnode **)&t)
1013  if (list->nextn == 0) abort();
1014         tt = list->nlist[--list->nextn];
1015         p1 = dividend;
1016         p2 = divisor;
1017         tt->tn_op = PLUS;
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;
1023 #undef tt
1024         t = optim(*p2);
1025         if (p1 < p2) {
1026                 *p1 = t;
1027                 squash(p2, maxnod);
1028         } else {
1029                 *p2 = t;
1030                 squash(p1, maxnod);
1031         }
1032         list->nextl--;
1033         goto loop;
1034 }
1035
1036 void squash(p, maxp) struct node **p; struct node **maxp; {
1037         register struct node **np;
1038
1039         for (np = p; np < maxp; np++)
1040                 *np = *(np+1);
1041 }
1042
1043 void _const(op, vp, v, type) int op; register _INT *vp; register _INT v; int type; {
1044         switch (op) {
1045
1046         case PTOI:
1047                 (*vp) /= (_UNSIGNED_INT)v;
1048                 return;
1049
1050         case PLUS:
1051                 *vp += v;
1052                 return;
1053
1054         case TIMES:
1055                 *vp *= v;
1056                 return;
1057
1058         case AND:
1059                 *vp &= v;
1060                 return;
1061
1062         case OR:
1063                 *vp |= v;
1064                 return;
1065
1066         case EXOR:
1067                 *vp ^= v;
1068                 return;
1069
1070         case UDIV:
1071         case UMOD:
1072                 type = UNSIGN;
1073         case DIVIDE:
1074         case MOD:
1075                 if (type==UNSIGN && v!=0 && v<=1) {
1076                         if (op==UDIV || op==DIVIDE) {
1077                                 if (v==1)
1078                                         return;
1079                                 *vp = *(_UNSIGNED_INT *)vp >= (_UNSIGNED_INT)v;
1080                                 return;
1081                         } else {
1082                                 if (v==1) {
1083                                         *vp = 0;
1084                                         return;
1085                                 }
1086                                 if (*(_UNSIGNED_INT *)vp >= (_UNSIGNED_INT)v)
1087                                         *vp -= v;
1088                                 return;
1089                         }
1090                 }
1091                 if (v==0)
1092                         werror1("divide check");
1093                 else
1094                         if (type==INT)
1095                                 if (op==DIVIDE || op==UDIV)
1096                                         *vp /= v;
1097                                 else
1098                                         *vp %= v;
1099                         else
1100                                 if (op==DIVIDE || op==UDIV)
1101                                         *(_UNSIGNED_INT *)vp /= (_UNSIGNED_INT)v;
1102                                 else
1103                                         *(_UNSIGNED_INT *)vp %= (_UNSIGNED_INT)v;
1104                         return;
1105
1106         case RSHIFT:
1107         rshift:
1108                 if (v<0) {
1109                         v = -v;
1110                         goto lshift;
1111                 }
1112                 if (type==INT)
1113                         *vp >>= v;
1114                 else
1115                         *(_UNSIGNED_INT *)vp >>= (_UNSIGNED_INT)v;
1116                 return;
1117
1118         case ULSH:
1119                 type = UNSIGN;
1120
1121         case LSHIFT:
1122         lshift:
1123                 if (v<0) {
1124                         v = -v;
1125                         goto rshift;
1126                 }
1127                 if (type==INT)
1128                         *vp <<= v;
1129                 else
1130                         *(_UNSIGNED_INT *)vp <<= (_UNSIGNED_INT)v;
1131                 return;
1132
1133         case ANDN:
1134                 *vp &= ~ v;
1135                 return;
1136         }
1137         error1("C error: const");
1138 }
1139
1140 struct lnode *lconst(op, lp, rp) int op; register struct node *lp; register struct node *rp; {
1141         _UNSIGNED_LONG l, r;
1142
1143         if (lp->n_op==LCON)
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;
1149                 else
1150                         l = (_UNSIGNED_INT)((struct cnode *)tlp->tn_tr1)->cn_value;
1151 #undef tlp
1152         } else
1153                 return(0);
1154         if (rp->n_op==LCON)
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;
1160                 else
1161                         r = (_UNSIGNED_INT)((struct cnode *)trp->tn_tr1)->cn_value;
1162 #undef trp
1163         } else
1164                 return(0);
1165         switch (op) {
1166
1167         case PLUS:
1168                 l += r;
1169                 break;
1170
1171         case MINUS:
1172                 l -= r;
1173                 break;
1174
1175         case TIMES:
1176         case LTIMES:
1177                 l *= r;
1178                 break;
1179
1180         case DIVIDE:
1181         case LDIV:
1182                 if (r==0)
1183                         error1("Divide check");
1184                 else
1185                         l /= r;
1186                 break;
1187
1188         case MOD:
1189         case LMOD:
1190                 if (r==0)
1191                         error1("Divide check");
1192                 else
1193                         l %= r;
1194                 break;
1195
1196         case AND:
1197                 l &= r;
1198                 break;
1199
1200         case ANDN:
1201                 l &= ~r;
1202                 break;
1203
1204         case OR:
1205                 l |= r;
1206                 break;
1207
1208         case EXOR:
1209                 l ^= r;
1210                 break;
1211
1212         case LSHIFT:
1213                 l <<= r;
1214                 break;
1215
1216         case RSHIFT:
1217                 l >>= r;
1218                 break;
1219
1220         default:
1221                 return(0);
1222         }
1223         if (lp->n_op==LCON) {
1224 #define llp ((struct lnode *)lp)
1225                 llp->ln_lvalue = l;
1226                 return(llp);
1227 #undef llp
1228         }
1229         lp = getblk(sizeof(struct lnode));
1230 #define llp ((struct lnode *)lp)
1231         llp->ln_op = LCON;
1232         llp->ln_type = LONG;
1233         llp->ln_lvalue = l;
1234         return(llp);
1235 #undef llp
1236 }
1237
1238 void insert(op, tree, list) int op; register struct node *tree; register struct acl *list; {
1239         register int d;
1240         int d1, i;
1241         struct node *t;
1242
1243 ins:
1244         if (tree->n_op != op)
1245                 tree = optim(tree);
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);
1251                 return;
1252 #undef ttree
1253         }
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;
1263                         else
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;
1268 #undef ttree
1269                         tree = optim(tree);
1270                         if (op==PLUS)
1271                                 goto ins;
1272                 }
1273         }
1274         d = degree(tree);
1275         for (i=0; i<list->nextl; i++) {
1276                 if ((d1=degree(list->llist[i]))<d) {
1277                         t = list->llist[i];
1278                         list->llist[i] = tree;
1279                         tree = t;
1280                         d = d1;
1281                 }
1282         }
1283         list->llist[list->nextl++] = tree;
1284 }
1285
1286 struct tnode *tnode(op, type, tr1, tr2) int op; int type; struct node *tr1; struct node *tr2; {
1287         register struct tnode *p;
1288
1289         p = (struct tnode *)getblk(sizeof(struct tnode));
1290         p->tn_op = op;
1291         p->tn_type = type;
1292  p->tn_subsp = (int *)NULL;
1293  p->tn_strp = (union str *)NULL;
1294         p->tn_tr1 = tr1;
1295         p->tn_tr2 = tr2;
1296         p->tn_degree = 0;
1297         return(p);
1298 }
1299
1300 struct cnode *tconst(val, type) int val; int type; {
1301         register struct cnode *p;
1302
1303         p = (struct cnode *)getblk(sizeof(struct cnode));
1304         p->cn_op = CON;
1305         p->cn_type = type;
1306  p->cn_subsp = (int *)NULL;
1307  p->cn_strp = (union str *)NULL;
1308         p->cn_value = val;
1309         return(p);
1310 }
1311
1312 struct node *getblk(size) int size; {
1313 #if 1
1314  return (struct node *)Tblock(size);
1315 #else
1316         register struct node *p;
1317
1318         if (size&01)
1319                 size++;
1320         p = (struct node *)curbase;
1321         if ((curbase += size) >= coremax) {
1322 #ifdef pdp11
1323                 if (sbrk(1024) == (char *)-1) {
1324 #else
1325                 if (sbrk(1024) != coremax) {
1326 #endif
1327                         error1("Out of space-- c1");
1328                         exit(1);
1329                 }
1330                 coremax += 1024;
1331         }
1332         return(p);
1333 #endif
1334 }
1335
1336 int islong(t) int t; {
1337         if (t==LONG || t==UNLONG)
1338                 return(2);
1339         return(1);
1340 }
1341
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);
1348         return(NULL);
1349 }
1350
1351 struct node *hardlongs(t) register struct node *t; {
1352         switch(t->n_op) {
1353
1354         case TIMES:
1355         case DIVIDE:
1356         case MOD:
1357 #define tt ((struct tnode *)t)
1358                 if (tt->tn_type == UNLONG)
1359                         tt->tn_op += ULTIMES-TIMES;
1360                 else
1361                         tt->tn_op += LTIMES-TIMES;
1362                 break;
1363 #undef tt
1364
1365         case ASTIMES:
1366         case ASDIV:
1367         case ASMOD:
1368 #define tt ((struct tnode *)t)
1369                 if (tt->tn_type == UNLONG)
1370                         tt->tn_op += ULASTIMES-ASTIMES;
1371                 else
1372                         tt->tn_op += LASTIMES-ASTIMES;
1373                 tt->tn_tr1 = (struct node *)tnode(AMPER, LONG+PTR, tt->tn_tr1, (struct node *)NULL);
1374                 break;
1375 #undef tt
1376
1377         default:
1378                 return(t);
1379         }
1380         return(optim(t));
1381 }
1382
1383 /*
1384  * Is tree of unsigned type?
1385  */
1386 int uns(tp) struct node *tp; {
1387         register int t;
1388
1389         t = tp->n_type;
1390         if (t==UNSIGN || t==UNCHAR || t==UNLONG || t&XTYPE)
1391                 return(1);
1392         return(0);
1393 }