1: // Copyright (C) 1986-1998 by Symantec
2: // Copyright (C) 2000-2011 by Digital Mars
3: // All Rights Reserved
4: // http://www.digitalmars.com
5: // Written by Walter Bright
6: /*
7: * This source file is made available for personal use
8: * only. The license is in /dmd/src/dmd/backendlicense.txt
9: * or /dm/src/dmd/backendlicense.txt
10: * For any other uses, please contact Digital Mars.
11: */
12:
13:
14: #if (SCPP || MARS) && !HTOD
15:
16: #include <stdio.h>
17: #include <time.h>
18:
19: #include "cc.h"
20: #include "global.h"
21: #include "el.h"
22: #include "go.h"
23: #include "ty.h"
24: #include "oper.h"
25: #include "vec.h"
26:
27: static char __file__[] = __FILE__; /* for tassert.h */
28: #include "tassert.h"
29:
30: STATIC void aewalk(elem **pn , vec_t ae);
31: STATIC elem * delcse(elem **pe);
32: STATIC void removecses(elem **pe);
33: STATIC void boundscheck(elem *e, vec_t ae);
34:
35: enum Aetype { AEcse, AEarraybounds };
36: static Aetype aetype;
37:
38: /*************************************
39: * Determine if floating point should be cse'd.
40: */
41:
42: inline int cse_float(elem *e)
43: {
44: #if TX86
45: // Don't CSE floating stuff if generating
46: // inline 8087 code, the code generator
47: // can't handle it yet
48: return !(tyfloating(e->Ety) && config.inline8087 &&
49: e->Eoper != OPvar && e->Eoper != OPconst);
50: #else
51: return 1;
52: #endif
53: }
54:
55: /************************************
56: * Build DAGs (basically find all the common subexpressions).
57: * Must be done after all other optimizations, because most
58: * of them depend on the trees being trees, not DAGs.
59: * The general strategy is:
60: * Compute available expressions (AEs)
61: * For each block
62: * stick together nodes that match, keeping AEs up to date
63: * For each block
64: * unstick unprofitable common subexpressions
65: * (this is generally target-dependent)
66: */
67:
68: void builddags()
69: { register unsigned i;
70: register vec_t aevec;
71:
72: cmes("builddags()\n");
73: assert(dfo);
74: flowae(); /* compute available expressions */
75: if (exptop <= 1) /* if no AEs */
76: return;
77: aetype = AEcse;
78: #ifdef DEBUG
79: for (i = 0; i < exptop; i++)
80: {
81: //dbg_printf("expnod[%d] = %p\n",i,expnod[i]);
82: if (expnod[i])
83: elem_debug(expnod[i]);
84: }
85: #endif
86: #if 0
87: dbg_printf("defkill "); vec_println(defkill,exptop);
88: dbg_printf("starkill "); vec_println(starkill,exptop);
89: dbg_printf("vptrkill "); vec_println(vptrkill,exptop);
90: #endif
91:
92: #if 0
93: /* This is the 'correct' algorithm for CSEs. We can't use it */
94: /* till we fix the code generator. */
95: for (i = 0; i < dfotop; i++)
96: { register block *b;
97:
98: b = dfo[i];
99: if (b->Belem)
100: {
101: #if 0
102: dbg_printf("dfo[%d] = %p\n",i,b);
103: dbg_printf("b->Bin "); vec_println(b->Bin,exptop);
104: dbg_printf("b->Bout "); vec_println(b->Bout,exptop);
105: aewalk(&(b->Belem),b->Bin);
106: dbg_printf("b->Bin "); vec_println(b->Bin,exptop);
107: dbg_printf("b->Bout "); vec_println(b->Bout,exptop);
108: #else
109: aewalk(&(b->Belem),b->Bin);
110: #endif
111: /* Bin and Bout would be equal at this point */
112: /* except that we deleted some elems from */
113: /* expnod[] and so it's a subset of Bout */
114: /* assert(veceq(b->Bin,b->Bout)); */
115: }
116: }
117: #else
118: /* Do CSEs across extended basic blocks only. This is because */
119: /* the code generator can only track register contents */
120: /* properly across extended basic blocks. */
121: aevec = vec_calloc(exptop);
122: for (i = 0; i < dfotop; i++)
123: { register block *b;
124:
125: b = dfo[i];
126: /* if not first block and (there are more than one */
127: /* predecessor or the only predecessor is not the */
128: /* previous block), then zero out the available */
129: /* expressions. */
130: if ((i != 0 &&
131: (list_block(b->Bpred) != dfo[i - 1] ||
132: list_next(b->Bpred) != NULL))
133: || b->BC == BCasm
134: || b->BC == BC_finally
135: #if SCPP
136: || b->BC == BCcatch
137: #endif
138: #if MARS
139: || b->BC == BCjcatch
140: #endif
141: )
142: vec_clear(aevec);
143: if (b->Belem) /* if there is an expression */
144: aewalk(&(b->Belem),aevec);
145:
146: }
147: vec_free(aevec);
148: #endif
149: // Need 2 passes to converge on solution
150: for (int j = 0; j < 2; j++)
151: for (i = 0; i < dfotop; i++)
152: { register block *b;
153:
154: b = dfo[i];
155: if (b->Belem)
156: {
157: #if 0
158: dbg_printf("b = 0x%x\n",b);
159: #endif
160: removecses(&(b->Belem));
161: }
162: }
163: }
164:
165: /**********************************
166: */
167:
168: STATIC void aeclear(elem *n,vec_t ae)
169: { int i;
170:
171: i = n->Eexp;
172: assert(i);
173: if (n->Ecount == 0)
174: {
175: expnod[i] = 0;
176: vec_clearbit(i,ae);
177: if (EUNA(n))
178: aeclear(n->E1,ae);
179: else if (EBIN(n))
180: { aeclear(n->E1,ae);
181: aeclear(n->E2,ae);
182: }
183: }
184: }
185:
186: /****************************
187: * Walk tree, building DAG as we go.
188: * ae = vector of available expressions
189: */
190:
191: STATIC void aewalk(register elem **pn,register vec_t ae)
192: { register vec_t aer;
193: register unsigned i,op;
194: register elem *n,*t;
195:
196: n = *pn;
197: assert(n && ae);
198: //printf("visiting %d: (",n->Eexp); WReqn(*pn); dbg_printf(")\n");
199: //chkvecdim(exptop);
200: op = n->Eoper;
201: if (n->Eexp) // if an AE
202: { // Try to find an equivalent AE, and point to it instead
203: assert(expnod[n->Eexp] == n);
204: if (aetype == AEcse)
205: {
206: foreach (i,exptop,ae)
207: { elem *e = expnod[i];
208:
209: // Attempt to replace n with e
210: if (e == NULL) // if elem no longer exists
211: vec_clearbit(i,ae); // it's not available
212: else if (n != e &&
213: el_match(n,e) &&
214: e->Ecount < 0xFF-1 && // must fit in unsigned char
215: cse_float(n)
216: )
217: {
218: *pn = e; // replace n with e
219: //dbg_printf("cse: %p (",n); WReqn(*pn); dbg_printf(")\n");
220: e->Ecount++;
221: #ifdef DEBUG
222: assert(e->Ecount != 0);
223: #endif
224: aeclear(n,ae);
225: el_free(n);
226: return;
227: }
228: }
229: }
230: }
231: switch (op)
232: { case OPcolon:
233: case OPcolon2:
234: // ae = ae & ael & aer
235: // AEs gened by ael and aer are mutually exclusive
236: aer = vec_clone(ae);
237: aewalk(&(n->E1),ae);
238: aewalk(&(n->E2),aer);
239: vec_andass(ae,aer);
240: vec_free(aer);
241: break;
242: case OPandand:
243: case OPoror:
244: aewalk(&(n->E1),ae);
245: /* ae &= aer */
246: aer = vec_clone(ae);
247: aewalk(&(n->E2),aer);
248: if (!el_noreturn(n->E2))
249: vec_andass(ae,aer);
250: vec_free(aer);
251: break;
252: case OPnegass:
253: t = Elvalue(n);
254: if (t->Eoper == OPind)
255: aewalk(&(t->E1),ae);
256: break;
257: case OPctor:
258: case OPdtor:
259: case OPdctor:
260: break;
261: case OPasm:
262: vec_clear(ae); // kill everything
263: return;
264:
265: default:
266: if (OTbinary(op))
267: { if (ERTOL(n))
268: {
269: // Don't CSE constants that will turn into
270: // an INC or DEC anyway
271: if (n->E2->Eoper == OPconst &&
272: n->E2->EV.Vint == 1 &&
273: (op == OPaddass || op == OPminass ||
274: op == OPpostinc || op == OPpostdec)
275: )
276: ;
277: else
278: aewalk(&(n->E2),ae);
279: }
280: if (OTassign(op))
281: { t = Elvalue(n);
282: if (t->Eoper == OPind)
283: aewalk(&(t->E1),ae);
284: }
285: else
286: aewalk(&(n->E1),ae);
287: if (!ERTOL(n))
288: aewalk(&(n->E2),ae);
289: }
290: else if (OTunary(op))
291: { assert(op != OPnegass);
292: aewalk(&(n->E1),ae);
293: }
294: }
295:
296: if (OTdef(op))
297: {
298: assert(n->Eexp == 0); // should not be an AE
299: /* remove all AEs that could be affected by this def */
300: if (Eunambig(n)) // if unambiguous definition
301: { symbol *s;
302:
303: assert(t->Eoper == OPvar);
304: s = t->EV.sp.Vsym;
305: if (!(s->Sflags & SFLunambig))
306: vec_subass(ae,starkill);
307: foreach (i,exptop,ae) /* for each ae elem */
308: { register elem *e = expnod[i];
309:
310: if (!e) continue;
311: if (OTunary(e->Eoper))
312: {
313: if (vec_testbit(e->E1->Eexp,ae))
314: continue;
315: }
316: else if (OTbinary(e->Eoper))
317: {
318: if (vec_testbit(e->E1->Eexp,ae) &&
319: vec_testbit(e->E2->Eexp,ae))
320: continue;
321: }
322: else if (e->Eoper == OPvar)
323: { if (e->EV.sp.Vsym != s)
324: continue;
325: }
326: else
327: continue;
328: vec_clearbit(i,ae);
329: }
330: }
331: else /* else ambiguous definition */
332: {
333: vec_subass(ae,defkill);
334: if (OTcalldef(op))
335: vec_subass(ae,vptrkill);
336: }
337:
338: // GEN the lvalue of an assignment operator
339: if (OTassign(op) && !OTpost(op) && t->Eexp)
340: vec_setbit(t->Eexp,ae);
341: }
342: if (n->Eexp) // if an AE
343: {
344: if (op == OPvptrfptr || op == OPcvptrfptr)
345: /* Invalidate all other OPvptrfptrs */
346: vec_subass(ae,vptrkill);
347:
348: /*dbg_printf("available: ("); WReqn(n); dbg_printf(")\n");
349: elem_print(n);*/
350: vec_setbit(n->Eexp,ae); /* mark this elem as available */
351: }
352: }
353:
354: /**************************
355: * Remove a CSE.
356: * Input:
357: * pe pointer to pointer to CSE
358: * Output:
359: * *pe new elem to replace the old
360: * Returns:
361: * *pe
362: */
363:
364: STATIC elem * delcse(elem **pe)
365: { elem *e;
366:
367: e = el_calloc();
368: el_copy(e,*pe);
369: #ifdef DEBUG
370: if (debugc)
371: { dbg_printf("deleting unprofitable CSE (");
372: WReqn(e);
373: dbg_printf(")\n");
374: }
375: #endif
376: assert(e->Ecount != 0);
377: if (EOP(e))
378: {
379: #if 1 || !TX86
380: if (e->E1->Ecount == 0xFF-1)
381: { elem *ereplace;
382: ereplace = el_calloc();
383: el_copy(ereplace,e->E1);
384: e->E1 = ereplace;
385: ereplace->Ecount = 0;
386: }
387: else
388: #endif
389: {
390: e->E1->Ecount++;
391: #ifdef DEBUG
392: assert(e->E1->Ecount != 0);
393: #endif
394: }
395: if (EBIN(e))
396: {
397: #if 1 || !TX86
398: if (e->E2->Ecount == 0xFF-1)
399: { elem *ereplace;
400: ereplace = el_calloc();
401: el_copy(ereplace,e->E2);
402: e->E2 = ereplace;
403: ereplace->Ecount = 0;
404: }
405: else
406: #endif
407: { e->E2->Ecount++;
408: #ifdef DEBUG
409: assert(e->E2->Ecount != 0);
410: #endif
411: }
412:
413: }
414: }
415: --(*pe)->Ecount;
416: #ifdef DEBUG
417: assert((*pe)->Ecount != 0xFF);
418: #endif
419: (*pe)->Nflags |= NFLdelcse; // not generating node
420: e->Ecount = 0;
421: #if FLOATS_IN_CODE
422: if (FLT_CODESEG_CELEM(e))
423: flt_record_const(e);
424: #endif
425: *pe = e;
426: return *pe;
427: }
428:
429: /******************************
430: * 'Unstick' CSEs that would be unprofitable to do. These are usually
431: * things like addressing modes, and are usually target-dependent.
432: */
433:
434: STATIC void removecses(elem **pe)
435: { unsigned op;
436: elem *e;
437:
438: L1: e = *pe;
439: assert(e);
440: elem_debug(e);
441: if (e->Nflags & NFLdelcse && e->Ecount)
442: {
443: delcse(pe);
444: goto L1;
445: }
446: op = e->Eoper;
447: if (OTunary(op))
448: {
449: if (op == OPind)
450: { elem *e1;
451:
452: e1 = e->E1;
453: if (e1->Eoper == OPadd &&
454: e1->Ecount // == 1
455: )
456: {
457: if (I32)
458: {
459: e1 = delcse(&e->E1);
460: if (e1->E1->Ecount) // == 1)
461: delcse(&e1->E1);
462: if (e1->E2->Ecount && e1->E2->Eoper != OPind)
463: delcse(&e1->E2);
464: }
465: // Look for *(var + const). The + and the const
466: // shouldn't be CSEs.
467: else if (e1->E2->Eoper == OPconst &&
468: (e1->E1->Eoper == OPvar || (e1->E1->Eoper == OPind && e1->E1->Ety & (mTYconst | mTYimmutable)))
469: )
470: {
471: e1 = delcse(&e->E1);
472: }
473: }
474:
475: if (I32 && e1->Eoper == OPadd &&
476: e1->E1->Eoper == OPadd &&
477: e1->E1->E1->Ecount &&
478: e1->E1->E1->Eoper == OPshl &&
479: e1->E1->E1->E2->Eoper == OPconst &&
480: e1->E1->E1->E2->EV.Vuns <= 3
481: )
482: {
483: delcse(&e1->E1->E1);
484: }
485:
486: if (I32 && e1->Eoper == OPadd &&
487: e1->E1->Eoper == OPadd &&
488: e1->E1->Ecount &&
489: e1->E1->E1->Eoper == OPshl &&
490: e1->E1->E1->E2->Eoper == OPconst &&
491: e1->E1->E1->E2->EV.Vuns <= 3
492: )
493: {
494: delcse(&e1->E1);
495: }
496:
497: else if (I32 && e1->Eoper == OPadd &&
498: e1->E1->Ecount &&
499: e1->E1->Eoper == OPshl &&
500: e1->E1->E2->Eoper == OPconst &&
501: e1->E1->E2->EV.Vuns <= 3
502: )
503: {
504: delcse(&e1->E1);
505: }
506:
507: // Remove *e1 where it's a double
508: if (e->Ecount &&
509: #if 1
510: tyfloating(e->Ety)
511: #else
512: // Why not TYfloat? Same issue in cgcs.c
513: (tybasic(e->Ety) == TYdouble ||
514: tybasic(e->Ety) == TYdouble_alias ||
515: tybasic(e->Ety) == TYldouble)
516: #endif
517: )
518: e = delcse(pe);
519:
520: }
521: #if TX86
522: // This CSE is too easy to regenerate
523: else if (op == OPushtlng && !I32 && e->Ecount)
524: e = delcse(pe);
525: #endif
526: }
527: else if (OTbinary(op))
528: {
529: if (e->Ecount > 0 && OTrel(op) && e->Ecount < 4
530: #if TX86
531: /* Don't CSE floating stuff if generating */
532: /* inline 8087 code, the code generator */
533: /* can't handle it yet */
534: && !(tyfloating(e->E1->Ety) && config.inline8087)
535: #endif
536: )
537: e = delcse(pe);
538: removecses(&(e->E2));
539: }
540: else /* leaf node */
541: {
542: return;
543: }
544: pe = &(e->E1);
545: goto L1;
546: }
547:
548: /*****************************************
549: * Do optimizations based on if we know an expression is
550: * 0 or !=0, even though we don't know anything else.
551: */
552:
553: STATIC void abewalk(elem *n,vec_t ae,vec_t aeval);
554: STATIC void abeboolres(elem *n,vec_t abe,vec_t abeval);
555: STATIC void abefree(elem *e,vec_t abe);
556: STATIC void abeset(elem *n,vec_t abe,vec_t abeval,int flag);
557:
558: void boolopt()
559: { unsigned i;
560: vec_t aevec;
561: vec_t aevecval;
562:
563: cmes("boolopt()\n");
564: if (!dfo)
565: compdfo();
566: flowae(); /* compute available expressions */
567: if (exptop <= 1) /* if no AEs */
568: return;
569: #if 0
570: for (i = 0; i < exptop; i++)
571: dbg_printf("expnod[%d] = 0x%x\n",i,expnod[i]);
572: dbg_printf("defkill "); vec_println(defkill,exptop);
573: dbg_printf("starkill "); vec_println(starkill,exptop);
574: dbg_printf("vptrkill "); vec_println(vptrkill,exptop);
575: #endif
576:
577: /* Do CSEs across extended basic blocks only. This is because */
578: /* the code generator can only track register contents */
579: /* properly across extended basic blocks. */
580: aevec = vec_calloc(exptop);
581: aevecval = vec_calloc(exptop);
582:
583: // Mark each expression that we know starts off with a non-zero value
584: for (i = 0; i < exptop; i++)
585: { elem *e = expnod[i];
586:
587: if (e)
588: { elem_debug(e);
589: if (e->Eoper == OPvar && e->EV.sp.Vsym->Sflags & SFLtrue)
590: { vec_setbit(i,aevec);
591: vec_setbit(i,aevecval);
592: }
593: }
594: }
595:
596: for (i = 0; i < dfotop; i++)
597: { register block *b;
598:
599: b = dfo[i];
warning C6011: Dereferencing NULL pointer 'struct block * * dfo': Lines: 559, 560, 561, 564, 565, 566, 567, 580, 581, 584, 585, 587, 589, 584, 585, 587, 589, 584, 585, 587, 589, 584, 596, 597, 599
600: /* if not first block and (there are more than one */
601: /* predecessor or the only predecessor is not the */
602: /* previous block), then zero out the available */
603: /* expressions. */
604: if ((i != 0 &&
605: (list_block(b->Bpred) != dfo[i - 1] ||
606: list_next(b->Bpred) != NULL))
607: || b->BC == BCasm
608: )
609: vec_clear(aevec);
610: if (b->Belem) /* if there is an expression */
611: abewalk(b->Belem,aevec,aevecval);
612:
613: }
614: vec_free(aevec);
615: vec_free(aevecval);
616: }
617:
618: /****************************
619: * Walk tree, replacing bool expressions that we know
620: * ae = vector of available boolean expressions
621: * aeval = parallel vector of values corresponding to whether bool
622: * value is 1 or 0
623: * n = elem tree to look at
624: */
625:
626: STATIC void abewalk(elem *n,vec_t ae,vec_t aeval)
627: { vec_t aer,aerval;
628: unsigned i,op;
629: unsigned i1,i2;
630: elem *t;
631:
632: assert(n && ae);
633: elem_debug(n);
634: /*dbg_printf("visiting: ("); WReqn(*pn); dbg_printf("), Eexp = %d\n",n->Eexp);*/
635: /*chkvecdim(exptop);*/
636: op = n->Eoper;
637: switch (op)
638: { case OPcolon:
639: case OPcolon2:
640: /* ae = ae & ael & aer */
641: /* AEs gened by ael and aer are mutually exclusive */
642: aer = vec_clone(ae);
643: aerval = vec_clone(aeval);
644: abewalk(n->E1,ae,aeval);
645: goto L1;
646: case OPandand:
647: case OPoror:
648: abewalk(n->E1,ae,aeval);
649: abeboolres(n->E1,ae,aeval);
650: /* ae &= aer */
651: aer = vec_clone(ae);
652: aerval = vec_clone(aeval);
653: abeset(n->E1,aer,aerval,(op == OPandand));
654: L1:
655: abewalk(n->E2,aer,aerval);
656: if (!el_noreturn(n->E2))
657: { vec_xorass(aerval,aeval);
658: vec_subass(aer,aerval);
659: vec_andass(ae,aer);
660: }
661: vec_free(aer);
662: vec_free(aerval);
663: break;
664: case OPbool:
665: case OPnot:
666: abewalk(n->E1,ae,aeval);
667: abeboolres(n->E1,ae,aeval);
668: break;
669: case OPnegass:
670: t = Elvalue(n);
671: if (t->Eoper == OPind)
672: abewalk(t->E1,ae,aeval);
673: break;
674:
675: case OPasm:
676: vec_clear(ae); // kill everything
677: return;
678:
679: default:
680: if (OTbinary(op))
681: { if (ERTOL(n))
682: abewalk(n->E2,ae,aeval);
683: if (OTassign(op))
684: { t = Elvalue(n);
685: if (t->Eoper == OPind)
686: abewalk(t->E1,ae,aeval);
687: }
688: else
689: abewalk(n->E1,ae,aeval);
690: if (!ERTOL(n))
691: abewalk(n->E2,ae,aeval);
692: }
693: else if (OTunary(op))
694: abewalk(n->E1,ae,aeval);
695: break;
696: }
697:
698: if (OTdef(op))
699: { assert(n->Eexp == 0); // should not be an AE
700: /* remove all AEs that could be affected by this def */
701: if (Eunambig(n)) /* if unambiguous definition */
702: { symbol *s;
703:
704: assert(t->Eoper == OPvar);
705: s = t->EV.sp.Vsym;
706: if (!(s->Sflags & SFLunambig))
707: vec_subass(ae,starkill);
708: foreach (i,exptop,ae) /* for each ae elem */
709: { register elem *e = expnod[i];
710:
711: if (!e) continue;
712: if (OTunary(e->Eoper))
713: {
714: if (vec_testbit(e->E1->Eexp,ae))
715: continue;
716: }
717: else if (OTbinary(e->Eoper))
718: {
719: if (vec_testbit(e->E1->Eexp,ae) &&
720: vec_testbit(e->E2->Eexp,ae))
721: continue;
722: }
723: else if (e->Eoper == OPvar)
724: { if (e->EV.sp.Vsym != s)
725: continue;
726: }
727: else
728: continue;
729: vec_clearbit(i,ae);
730: }
731: }
732: else /* else ambiguous definition */
733: {
734: vec_subass(ae,defkill);
735: if (OTcalldef(op))
736: vec_subass(ae,vptrkill);
737: }
738: /* GEN the lvalue of an assignment operator */
739: #if 1
740: if (op == OPeq && (i1 = t->Eexp) != 0 && (i2 = n->E2->Eexp) != 0)
741: {
742: if (vec_testbit(i2,ae))
743: {
744: vec_setbit(i1,ae);
745: if (vec_testbit(i2,aeval))
746: vec_setbit(i1,aeval);
747: else
748: vec_clearbit(i1,aeval);
749: }
750: }
751: #else
752: if ((OTopeq(op) || op == OPeq || op == OPnegass) && n->E1->Eexp)
753: { vec_setbit(t->Eexp,ae);
754: if (n->E1->Eoper == OPbit)
755: vec_setbit(n->E1->Eexp,ae);
756: }
757: #endif
758: }
759: else if (n->Eexp) /* if an AE */
760: {
761: if (op == OPvptrfptr || op == OPcvptrfptr)
762: /* Invalidate all other OPvptrfptrs */
763: vec_subass(ae,vptrkill);
764:
765: /*dbg_printf("available: ("); WReqn(n); dbg_printf(")\n");
766: elem_print(n);*/
767: // vec_setbit(n->Eexp,ae); /* mark this elem as available */
768: }
769: }
770:
771: /************************************
772: * Elem e is to be evaluated for a boolean result.
773: * See if we already know its value.
774: */
775:
776: STATIC void abeboolres(elem *n,vec_t ae,vec_t aeval)
777: { unsigned i;
778:
779: elem_debug(n);
780: if (n->Eexp)
781: { /* Try to find an equivalent AE, and point to it instead */
782: assert(expnod[n->Eexp] == n);
783: foreach (i,exptop,ae)
784: { elem *e = expnod[i];
785:
786: // Attempt to replace n with e
787: //dbg_printf("Looking at expnod[%d] = %p\n",i,e);
788: assert(e);
789: elem_debug(e);
790: if (n != e && el_match(n,e))
791: {
792: #ifdef DEBUG
793: if (debugc)
794: { dbg_printf("Elem %p: ",n);
795: WReqn(n);
796: dbg_printf(" is replaced by %d\n",vec_testbit(i,aeval) != 0);
797: }
798: #endif
799: abefree(n,ae);
800: n->EV.Vlong = vec_testbit(i,aeval) != 0;
801: n->Eoper = OPconst;
802: n->Ety = TYint;
803: changes++;
804: break;
805: }
806: }
807: }
808: }
809:
810: /****************************
811: * Remove e from available expressions, and its children.
812: */
813:
814: STATIC void abefree(elem *e,vec_t ae)
815: {
816: //dbg_printf("abefree %p: "); WReqn(e); dbg_printf("\n");
817: assert(e->Eexp);
818: vec_clearbit(e->Eexp,ae);
819: expnod[e->Eexp] = NULL;
820: if (EOP(e))
821: { if (EBIN(e))
822: { abefree(e->E2,ae);
823: el_free(e->E2);
824: e->E2 = NULL;
825: }
826: abefree(e->E1,ae);
827: el_free(e->E1);
828: e->E1 = NULL;
829: }
830: }
831:
832: /************************************
833: * Elem e is to be evaluated for a boolean result.
834: * Set its result according to flag.
835: */
836:
837: STATIC void abeset(elem *e,vec_t ae,vec_t aeval,int flag)
838: { unsigned i;
839:
840: while (1)
841: {
842: i = e->Eexp;
843: if (i && expnod[i])
844: {
845: //dbg_printf("abeset for expnod[%d] = %p: ",i,e); WReqn(e); dbg_printf("\n");
846: vec_setbit(i,ae);
847: if (flag)
848: vec_setbit(i,aeval);
849: else
850: vec_clearbit(i,aeval);
851: }
852: switch (e->Eoper)
853: { case OPnot:
854: flag ^= 1;
855: case OPbool:
856: case OPeq:
857: e = e->E1;
858: continue;
859: }
860: break;
861: }
862: }
863:
864: #endif
865: