1: // Copyright (C) 1985-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: #if !SPP
14:
15: #include <stdio.h>
16: #include <string.h>
17: #include <time.h>
18: #include "cc.h"
19: #include "oper.h"
20: #include "global.h"
21: #include "el.h"
22: #include "dt.h"
23: #include "code.h"
24: #include "type.h"
25:
26: static char __file__[] = __FILE__; /* for tassert.h */
27: #include "tassert.h"
28:
29: extern void error(const char *filename, unsigned linnum, const char *format, ...);
30:
31: STATIC elem * optelem(elem *,HINT);
32: STATIC elem * elarray(elem *e);
33: STATIC elem * eldiv(elem *);
34:
35: CEXTERN elem * evalu8(elem *);
36:
37: static int expgoal;
38: static int again;
39: static int cgelem_goal;
40:
41: /*****************************
42: */
43:
44: STATIC elem * cgel_lvalue(elem *e)
45: { elem *e1;
46: elem *e11;
47: int op;
48:
49: //printf("cgel_lvalue()\n"); elem_print(e);
50: e1 = e->E1;
51: op = e->Eoper;
52: if (e1->Eoper == OPbit)
53: {
54: e11 = e1->E1;
55:
56: if (e11->Eoper == OPcomma)
57: {
58: // Replace (((e,v) bit x) op e2) with (e,((v bit x) op e2))
59: e1->E1 = e11->E2;
60: e11->E2 = e;
61: e11->Ety = e->Ety;
62: e11->ET = e->ET;
63: e = e11;
64: goto L1;
65: }
66: else if (OTassign(e11->Eoper))
67: {
68: // Replace (((e op= v) bit x) op e2) with ((e op= v) , ((e bit x) op e2))
69: e1->E1 = el_copytree(e11->E1);
70: e = el_bin(OPcomma,e->Ety,e11,e);
71: goto L1;
72: }
73: }
74: else if (e1->Eoper == OPcomma)
75: {
76: // Replace ((e,v) op e2) with (e,(v op e2))
77: e->Eoper = OPcomma;
78: e1->Eoper = op;
79: e1->Ety = e->Ety;
80: e1->ET = e->ET;
81: e->E1 = e1->E1;
82: e1->E1 = e1->E2;
83: e1->E2 = e->E2;
84: e->E2 = e1;
85: goto L1;
86: }
87: else if (OTassign(e1->Eoper))
88: {
89: // Replace ((e op= v) op e2) with ((e op= v) , (e op e2))
90: e->E1 = el_copytree(e1->E1);
91: e = el_bin(OPcomma,e->Ety,e1,e);
92: L1:
93: e = optelem(e,TRUE);
94: }
95: return e;
96: }
97:
98:
99: /******************************
100: * Scan down commas.
101: */
102:
103: STATIC elem * elscancommas(elem *e)
104: {
105: while (e->Eoper == OPcomma
106: #if SCPP
107: || e->Eoper == OPinfo
108: #endif
109: )
110: e = e->E2;
111: return e;
112: }
113:
114: /*************************
115: * Return TRUE if elem is the constant 1.
116: */
117:
118: int elemisone(elem *e)
119: {
120: if (e->Eoper == OPconst)
121: { switch (tybasic(e->Ety))
122: {
123: case TYchar:
124: case TYuchar:
125: case TYschar:
126: case TYchar16:
127: case TYshort:
128: case TYushort:
129: case TYint:
130: case TYuint:
131: case TYlong:
132: case TYulong:
133: case TYllong:
134: case TYullong:
135: case TYnullptr:
136: #if TX86
137: #if JHANDLE
138: case TYjhandle:
139: #endif
140: case TYnptr:
141: case TYsptr:
142: case TYcptr:
143: case TYhptr:
144: #endif
145: case TYfptr:
146: case TYvptr:
147: case TYbool:
148: case TYwchar_t:
149: case TYdchar:
150: if (el_tolong(e) != 1)
151: goto nomatch;
152: break;
153: case TYldouble:
154: case TYildouble:
155: if (e->EV.Vldouble != 1)
156: goto nomatch;
157: break;
158: case TYdouble:
159: case TYidouble:
160: case TYdouble_alias:
161: if (e->EV.Vdouble != 1)
162: goto nomatch;
163: break;
164: case TYfloat:
165: case TYifloat:
166: if (e->EV.Vfloat != 1)
167: goto nomatch;
168: break;
169: default:
170: goto nomatch;
171: }
172: return TRUE;
173: }
174:
175: nomatch:
176: return FALSE;
177: }
178:
179: /*************************
180: * Return TRUE if elem is the constant -1.
181: */
182:
183: int elemisnegone(elem *e)
184: {
185: if (e->Eoper == OPconst)
186: { switch (tybasic(e->Ety))
187: {
188: case TYchar:
189: case TYuchar:
190: case TYschar:
191: case TYchar16:
192: case TYshort:
193: case TYushort:
194: case TYint:
195: case TYuint:
196: case TYlong:
197: case TYulong:
198: case TYllong:
199: case TYullong:
200: case TYnullptr:
201: #if TX86
202: #if JHANDLE
203: case TYjhandle:
204: #endif
205: case TYnptr:
206: case TYsptr:
207: case TYcptr:
208: case TYhptr:
209: #endif
210: case TYfptr:
211: case TYvptr:
212: case TYbool:
213: case TYwchar_t:
214: case TYdchar:
215: if (el_tolong(e) != -1)
216: goto nomatch;
217: break;
218: case TYldouble:
219: //case TYildouble:
220: if (e->EV.Vldouble != -1)
221: goto nomatch;
222: break;
223: case TYdouble:
224: //case TYidouble:
225: case TYdouble_alias:
226: if (e->EV.Vdouble != -1)
227: goto nomatch;
228: break;
229: case TYfloat:
230: //case TYifloat:
231: if (e->EV.Vfloat != -1)
232: goto nomatch;
233: break;
234: default:
235: goto nomatch;
236: }
237: return TRUE;
238: }
239:
240: nomatch:
241: return FALSE;
242: }
243:
244: /**********************************
245: * Swap relational operators (like if we swapped the leaves).
246: */
247:
248: unsigned swaprel(unsigned op)
249: {
250: assert(op < (unsigned) OPMAX);
251: if (OTrel(op))
252: op = rel_swap(op);
253: return op;
254: }
255:
256: /**************************
257: * Replace e1 by t=e1, replace e2 by t.
258: */
259:
260: STATIC void fixside(elem **pe1,elem **pe2)
261: { tym_t tym;
262: elem *tmp,*e2;
263:
264: tym = (*pe1)->Ety;
265: tmp = el_alloctmp(tym);
266: *pe1 = el_bin(OPeq,tym,tmp,*pe1);
267: e2 = el_copytree(tmp);
268: el_free(*pe2);
269: *pe2 = e2;
270: }
271:
272:
273:
274: /****************************
275: * Compute the 'cost' of evaluating a elem. Could be done
276: * as Sethi-Ullman numbers, but that ain't worth the bother.
277: * We'll fake it.
278: */
279:
280: #define cost(n) (opcost[n->Eoper])
281:
282: /*******************************
283: * For floating point expressions, the cost would be the number
284: * of registers in the FPU stack needed.
285: */
286:
287: int fcost(elem *e)
288: {
289: int cost;
290: int cost1;
291: int cost2;
292:
293: //printf("fcost()\n");
294: switch (e->Eoper)
295: {
296: case OPadd:
297: case OPmin:
298: case OPmul:
299: case OPdiv:
300: cost1 = fcost(e->E1);
301: cost2 = fcost(e->E2);
302: cost = cost2 + 1;
303: if (cost1 > cost)
304: cost = cost1;
305: break;
306:
307: case OPcall:
308: case OPucall:
309: cost = 8;
310: break;
311:
312: case OPneg:
313: case OPabs:
314: return fcost(e->E1);
315:
316: case OPvar:
317: case OPconst:
318: case OPind:
319: default:
320: return 1;
321: }
322: if (cost > 8)
323: cost = 8;
324: return cost;
325: }
326:
327: /*******************************
328: * The lvalue of an op= is a conversion operator. Since the code
329: * generator cannot handle this, we will have to fix it here. The
330: * general strategy is:
331: * (conv) e1 op= e2 => e1 = (conv) e1 op e2
332: * Since e1 can only be evaluated once, if it is an expression we
333: * must use a temporary.
334: */
335:
336: STATIC elem *fixconvop(elem *e)
337: { elem *e1,*e2,*ed,*T;
338: elem *ex;
339: elem **pe;
340: unsigned cop,icop,op;
341: tym_t tycop,tym,tyme;
342: static char invconvtab[] =
343: {
344: OPbool, // OPb_8
345: OPs32_d, // OPd_s32
346: OPd_s32, // OPs32_d
347: OPs16_d, /* OPd_s16 */
348: OPd_s16, /* OPs16_d */
349: OPu16_d, // OPd_u16
350: OPd_u16, // OPu16_d
351: OPu32_d, /* OPd_u32 */
352: OPd_u32, /* OPu32_d */
353: OPs64_d, // OPd_s64
354: OPd_s64, // OPs64_d
355: OPu64_d, // OPd_u64
356: OPd_u64, // OPu64_d
357: OPf_d, // OPd_f
358: OPd_f, // OPf_d
359: 0, /* OPvptrfptr */
360: 0, /* OPcvptrfptr */
361: OP32_16, // OPs16_32
362: OP32_16, // OPu16_32
363: OPs16_32, // OP32_16
364: OP16_8, // OPu8_16
365: OP16_8, // OPs8_16
366: OPs8_16, // OP16_8
367: OP64_32, // OPu32_64
368: OP64_32, // OPs32_64
369: OPs32_64, // OP64_32
370: OP128_64, // OPu64_128
371: OP128_64, // OPs64_128
372: OPs64_128, // OP128_64
373: OPptrlptr, /* OPoffset */
374: OPoffset, /* OPptrlptr */
375: OPfromfar16, /* OPtofar16 */
376: OPtofar16, /* OPfromfar16 */
377: OPd_ld, // OPld_d
warning C4305: 'initializing' : truncation from 'OPER' to 'char'
warning C4309: 'initializing' : truncation of constant value
378: OPld_d, // OPd_ld
379: OPu64_d, // OPld_u64
380: };
381:
382: //dbg_printf("fixconvop before\n");
383: //elem_print(e);
384: assert(arraysize(invconvtab) == CNVOPMAX - CNVOPMIN + 1);
385: assert(e);
386: tyme = e->Ety;
387: cop = e->E1->Eoper; /* the conversion operator */
388: assert(cop <= CNVOPMAX);
389:
390: if (e->E1->E1->Eoper == OPcomma)
391: { /* conv(a,b) op= e2
392: * =>
393: * a, (conv(b) op= e2)
394: */
395: elem *ecomma = e->E1->E1;
396: e->E1->E1 = ecomma->E2;
397: e->E1->E1->Ety = ecomma->Ety;
398: ecomma->E2 = e;
399: ecomma->Ety = e->Ety;
400: return optelem(ecomma, TRUE);
401: }
402:
403: tycop = e->E1->Ety;
404: tym = e->E1->E1->Ety;
405: e->E1 = el_selecte1(e->E1); /* dump it for now */
406: e1 = e->E1;
407: e1->Ety = tym;
408: e2 = e->E2;
409: assert(e1 && e2);
410: /* select inverse conversion operator */
411: icop = invconvtab[convidx(cop)];
412:
413: /* First, let's see if we can just throw it away. */
414: /* (unslng or shtlng) e op= e2 => e op= (lngsht) e2 */
415: if (OTwid(e->Eoper) &&
416: (cop == OPshtlng || cop == OPu16_32 ||
417: cop == OPu8int || cop == OPs8int))
418: { if (e->Eoper != OPshlass && e->Eoper != OPshrass && e->Eoper != OPashrass)
419: e->E2 = el_una(icop,tym,e2);
420: //dbg_printf("after1\n");
421: //elem_print(e);
422: return e;
423: }
424:
425: /* Oh well, just split up the op and the =. */
426: op = opeqtoop(e->Eoper); /* convert op= to op */
427: e->Eoper = OPeq; /* just plain = */
428: ed = el_copytree(e1); /* duplicate e1 */
429: /* make: e1 = (icop) ((cop) ed op e2)*/
430: e->E2 = el_una(icop,e1->Ety,
431: el_bin(op,tycop,el_una(cop,tycop,ed),
432: e2));
433:
434: //printf("after1\n");
435: //elem_print(e);
436:
437: if (op == OPdiv &&
438: tybasic(e2->Ety) == TYcdouble)
439: {
440: if (tycop == TYdouble)
441: {
442: e->E2->E1->Ety = tybasic(e2->Ety);
443: e->E2->E1 = el_una(OPc_r, tycop, e->E2->E1);
444: }
445: else if (tycop == TYidouble)
446: {
447: e->E2->E1->Ety = tybasic(e2->Ety);
448: e->E2->E1 = el_una(OPc_i, tycop, e->E2->E1);
449: }
450: }
451:
452: if (op == OPdiv &&
453: tybasic(e2->Ety) == TYcfloat)
454: {
455: if (tycop == TYfloat)
456: {
457: e->E2->E1->Ety = tybasic(e2->Ety);
458: e->E2->E1 = el_una(OPc_r, tycop, e->E2->E1);
459: }
460: else if (tycop == TYifloat)
461: {
462: e->E2->E1->Ety = tybasic(e2->Ety);
463: e->E2->E1 = el_una(OPc_i, tycop, e->E2->E1);
464: }
465: }
466:
467: /* Handle case of multiple conversion operators on lvalue */
468: /* (such as (intdbl 8int char += double)) */
469: ex = e;
470: pe = &e;
471: while (OTconv(ed->Eoper))
472: { unsigned copx = ed->Eoper;
473: tym_t tymx;
474:
475: icop = invconvtab[convidx(copx)];
476: tymx = ex->E1->E1->Ety;
477: ex->E1 = el_selecte1(ex->E1); // dump it for now
478: e1 = ex->E1;
479: e1->Ety = tymx;
480: ex->E2 = el_una(icop,e1->Ety,ex->E2);
481: ex->Ety = tymx;
482: tym = tymx;
483:
484: if (ex->Ety != tyme)
485: { *pe = el_una(copx, ed->Ety, ex);
486: pe = &(*pe)->E1;
487: }
488:
489: ed = ed->E1;
490: }
491: //dbg_printf("after2\n");
492: //elem_print(e);
493:
494: e->Ety = tym;
495: if (tym != tyme &&
496: !(tyintegral(tym) && tyintegral(tyme) && tysize(tym) == tysize(tyme)))
497: e = el_una(cop, tyme, e);
498:
499: if (ed->Eoper == OPbit) /* special handling */
500: {
501: ed = ed->E1;
502: e1 = e1->E1; /* go down one */
503: }
504: /* If we have a *, must assign a temporary to the expression */
505: /* underneath it (even if it's a var, as e2 may modify the var). */
506: if (ed->Eoper == OPind)
507: { T = el_alloctmp(ed->E1->Ety); /* make temporary */
508: ed->E1 = el_bin(OPeq,T->Ety,T,ed->E1); /* ed: *(T=e) */
509: el_free(e1->E1);
510: e1->E1 = el_copytree(T);
511: }
512: //dbg_printf("after3\n");
513: //elem_print(e);
514: return e;
515: }
516:
517: STATIC elem * elerr(elem *e)
518: {
519: #ifdef DEBUG
520: elem_print(e);
521: #endif
522: assert(0);
523: return (elem *)NULL;
524: }
525:
526: /* For ops with no optimizations */
527:
528: STATIC elem * elzot(elem *e)
529: { return e; }
530:
531: /****************************
532: */
533:
534: STATIC elem * elstring(elem *e)
535: {
536: #if 0 // now handled by el_convert()
537: if (!OPTIMIZER)
538: el_convstring(e); // convert string to OPrelconst
539: #endif
540: return e;
541: }
542:
543: /************************
544: */
545:
546: #if TX86
547:
548: /************************
549: * Convert far pointer to pointer.
550: */
551:
552: STATIC void eltonear(elem **pe)
553: { tym_t ty;
554: elem *e = *pe;
555:
556: ty = e->E1->Ety;
557: e = el_selecte1(e);
558: e->Ety = ty;
559: *pe = optelem(e,TRUE);
560: }
561:
562: /************************
563: */
564:
565: STATIC elem * elstrcpy(elem *e)
566: { tym_t ty;
warning C4101: 'ty' : unreferenced local variable
567:
568: elem_debug(e);
569: switch (e->E2->Eoper)
570: {
571: #if TX86
572: case OPptrlptr:
573: if (OPTIMIZER)
574: {
575: eltonear(&e->E2);
576: e = optelem(e,TRUE);
577: }
578: break;
579: #endif
580: case OPstring:
581: /* Replace strcpy(e1,"string") with memcpy(e1,"string",sizeof("string")) */
582: #if 0
583: // As memcpy
584: e->Eoper = OPmemcpy;
585: elem *en = el_long(TYsize_t, strlen(e->E2->EV.ss.Vstring) + 1);
586: e->E2 = el_bin(OPparam,TYvoid,e->E2,en);
587: #else
588: // As streq
589: e->Eoper = OPstreq;
590: type *t = type_allocn(TYarray, tschar);
591: t->Tdim = strlen(e->E2->EV.ss.Vstring) + 1;
592: e->ET = t;
593: t->Tcount++;
594: e->E1 = el_una(OPind,TYstruct,e->E1);
595: e->E2 = el_una(OPind,TYstruct,e->E2);
596:
597: e = el_bin(OPcomma,e->Ety,e,el_copytree(e->E1->E1));
598: if (el_sideeffect(e->E2))
599: fixside(&e->E1->E1->E1,&e->E2);
600: #endif
601: e = optelem(e,TRUE);
602: break;
603: }
604: return e;
605: }
606:
607: /************************
608: */
609:
610: STATIC elem * elstrcmp(elem *e)
611: {
612: elem_debug(e);
613: if (OPTIMIZER)
614: {
615: if (e->E1->Eoper == OPptrlptr)
616: eltonear(&e->E1);
617: switch (e->E2->Eoper)
618: {
619: case OPptrlptr:
620: eltonear(&e->E2);
621: break;
622:
623: case OPstring:
624: // Replace strcmp(e1,"string") with memcmp(e1,"string",sizeof("string"))
625: e->Eoper = OPparam;
626: e = el_bin(OPmemcmp,e->Ety,e,el_long(TYint,strlen(e->E2->EV.ss.Vstring) + 1));
627: e = optelem(e,TRUE);
628: break;
629: }
630: }
631: return e;
632: }
633:
634: /****************************
635: * For OPmemcmp, OPmemcpy, OPmemset.
636: */
637:
638: STATIC elem * elmemxxx(elem *e)
639: {
640: elem_debug(e);
641: if (OPTIMIZER)
642: { elem *ex;
643:
644: ex = e->E1;
645: switch (e->Eoper)
646: { case OPmemcmp:
647: if (ex->E1->Eoper == OPptrlptr)
648: eltonear(&ex->E1);
649: if (ex->E2->Eoper == OPptrlptr)
650: eltonear(&ex->E2);
651: break;
652:
653: case OPmemset:
654: if (ex->Eoper == OPptrlptr)
655: eltonear(&ex);
656: else
657: {
658: // lvalue OPmemset (nbytes param value)
659: elem *enbytes = e->E2->E1;
660: elem *evalue = e->E2->E2;
661:
662: #if MARS && TX86
663: if (enbytes->Eoper == OPconst && evalue->Eoper == OPconst
664: /* && tybasic(e->E1->Ety) == TYstruct*/)
665: { tym_t tym;
666: tym_t ety;
667: int nbytes = el_tolong(enbytes);
warning C4244: 'initializing' : conversion from 'targ_llong' to 'int', possible loss of data
668: targ_llong value = el_tolong(evalue);
669: elem *e1 = e->E1;
670: elem *tmp;
671:
672: if (e1->Eoper == OPcomma || OTassign(e1->Eoper))
673: return cgel_lvalue(e); // replace (e,v)op=e2 with e,(v op= e2)
674:
675: switch (nbytes)
676: {
677: case CHARSIZE: tym = TYchar; goto L1;
678: case SHORTSIZE: tym = TYshort; goto L1;
679: case LONGSIZE: tym = TYlong; goto L1;
680: #if LONGLONG
681: case LLONGSIZE: if (intsize == 2)
682: goto Ldefault;
683: tym = TYllong; goto L1;
684: #endif
685: L1:
686: ety = e->Ety;
687: memset(&value, value & 0xFF, sizeof(value));
688: evalue->EV.Vullong = value;
689: evalue->Ety = tym;
690: e->Eoper = OPeq;
691: e->Ety = (e->Ety & ~mTYbasic) | tym;
692: if (tybasic(e1->Ety) == TYstruct)
693: e1->Ety = tym;
694: else
695: e->E1 = el_una(OPind, tym, e1);
696: tmp = el_same(&e->E1);
697: tmp = el_una(OPaddr, ety, tmp);
698: e->E2->Ety = tym;
699: e->E2 = el_selecte2(e->E2);
700: e = el_combine(e, tmp);
701: e = optelem(e,TRUE);
702: break;
703:
704: default:
705: Ldefault:
706: break;
707: }
708: }
709: #endif
710: }
711: break;
712:
713: case OPmemcpy:
714: if (ex->Eoper == OPptrlptr)
715: eltonear(&e->E1);
716: ex = e->E2;
717: if (ex->E1->Eoper == OPptrlptr)
718: eltonear(&ex->E1);
719: if (ex->E2->Eoper == OPconst)
720: {
721: if (!boolres(ex->E2))
722: { // Copying 0 bytes, so remove memcpy
723: e->E2 = e->E1;
724: e->E1 = ex->E1;
725: ex->E1 = NULL;
726: e->Eoper = OPcomma;
727: el_free(ex);
728: return optelem(e, TRUE);
729: }
730: #if 1
731: // Convert OPmemcpy to OPstreq
732: e->Eoper = OPstreq;
733: type *t = type_allocn(TYarray, tschar);
734: t->Tdim = el_tolong(ex->E2);
warning C4244: '=' : conversion from 'targ_llong' to 'targ_size_t', possible loss of data
735: e->ET = t;
736: t->Tcount++;
737: e->E1 = el_una(OPind,TYstruct,e->E1);
738: e->E2 = el_una(OPind,TYstruct,ex->E1);
739: ex->E1 = NULL;
740: el_free(ex);
741: ex = el_copytree(e->E1->E1);
742: if (tysize(e->Ety) > tysize(ex->Ety))
743: ex = el_una(OPptrlptr,e->Ety,ex);
744: e = el_bin(OPcomma,e->Ety,e,ex);
745: if (el_sideeffect(e->E2))
746: fixside(&e->E1->E1->E1,&e->E2);
747: return optelem(e,TRUE);
748: #endif
749: }
750: break;
751:
752: default:
753: assert(0);
754: }
755: }
756: return e;
757: }
758:
759: #endif
760:
761: /***********************
762: * + # (combine offsets with addresses)
763: * / \ => |
764: * # c v,c
765: * |
766: * v
767: */
768:
769: STATIC elem * eladd(elem *e)
770: { elem *e1,*e2;
771: int sz;
772:
773: //printf("eladd(%p)\n",e);
774: targ_size_t ptrmask = ~(targ_size_t)0;
775: if (NPTRSIZE <= 4)
776: ptrmask = 0xFFFFFFFF;
777: L1:
778: e1 = e->E1;
779: e2 = e->E2;
780: if (e2->Eoper == OPconst)
781: {
782: #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
783: if (e1->Eoper == OPrelconst && e1->EV.sp.Vsym->Sfl == FLgot)
784: goto ret;
785: #endif
786: if (e1->Eoper == OPrelconst /* if (&v) + c */
787: || e1->Eoper == OPstring
788: )
789: {
790: e1->EV.sp.Voffset += e2->EV.Vpointer;
791: e1->EV.sp.Voffset &= ptrmask;
792: e = el_selecte1(e);
793: goto ret;
794: }
795: }
796: else if (e1->Eoper == OPconst)
797: {
798: #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
799: if (e2->Eoper == OPrelconst && e2->EV.sp.Vsym->Sfl == FLgot)
800: goto ret;
801: #endif
802: if (e2->Eoper == OPrelconst /* if c + (&v) */
803: || e2->Eoper == OPstring
804: )
805: {
806: e2->EV.sp.Voffset += e1->EV.Vpointer;
807: e2->EV.sp.Voffset &= ptrmask;
808: e = el_selecte2(e);
809: goto ret;
810: }
811: }
812:
813: if (!OPTIMIZER)
814: goto ret;
815:
816: /* Replace ((e + &v) + c) with (e + (&v+c)) */
817: if (e2->Eoper == OPconst && e1->Eoper == OPadd &&
818: (e1->E2->Eoper == OPrelconst || e1->E2->Eoper == OPstring))
819: {
820: e1->E2->EV.sp.Voffset += e2->EV.Vpointer;
821: e1->E2->EV.sp.Voffset &= ptrmask;
822: e = el_selecte1(e);
823: goto L1;
824: }
825: /* Replace ((e + c) + &v) with (e + (&v+c)) */
826: else if ((e2->Eoper == OPrelconst || e2->Eoper == OPstring) &&
827: e1->Eoper == OPadd && cnst(e1->E2))
828: {
829: e2->EV.sp.Voffset += e1->E2->EV.Vpointer;
830: e2->EV.sp.Voffset &= ptrmask;
831: e->E1 = el_selecte1(e1);
832: goto L1; /* try and find some more */
833: }
834: /* Replace (e1 + -e) with (e1 - e) */
835: else if (e2->Eoper == OPneg)
836: { e->E2 = el_selecte1(e2);
837: e->Eoper = OPmin;
838: again = 1;
839: return e;
840: }
841: /* Replace (-v + e) with (e + -v) */
842: else if (e1->Eoper == OPneg && OTleaf(e1->E1->Eoper))
843: { e->E1 = e2;
844: e->E2 = e1; /* swap leaves */
845: goto L1;
846: }
847: /* Replace ((e - e2) + e2) with (e) */
848: /* The optimizer sometimes generates this case */
849: else if (!tyfloating(e->Ety) && /* no floating bugs */
850: e1->Eoper == OPmin &&
851: el_match(e1->E2,e2) &&
852: !el_sideeffect(e2))
853: { tym_t tym = e->Ety;
854:
855: e = el_selecte1(el_selecte1(e));
856: e->Ety = tym; /* retain original type */
857: return e;
858: }
859: /* Replace ((e - #v+c1) + #v+c2) with ((e - c1) + c2) */
860: else if (e2->Eoper == OPrelconst &&
861: e1->Eoper == OPmin &&
862: e1->E2->Eoper == OPrelconst &&
863: e1->E2->EV.sp.Vsym == e2->EV.sp.Vsym)
864: { e2->Eoper = OPconst;
865: e2->Ety = TYint;
866: e1->Ety = e1->E1->Ety;
867: e1->E2->Eoper = OPconst;
868: e1->E2->Ety = TYint;
869: {
870: #if TX86
871: /* Watch out for pointer types changing, requiring a conversion */
872: tym_t ety,e11ty;
873:
874: ety = tybasic(e->Ety);
875: e11ty = tybasic(e1->E1->Ety);
876: if (typtr(ety) && typtr(e11ty) &&
877: tysize[ety] != tysize[e11ty])
878: {
879: e = el_una((tysize[ety] > tysize[e11ty]) ? OPptrlptr : OPoffset,
880: e->Ety,e);
881: e->E1->Ety = e1->Ety;
882: }
883: #endif
884: }
885: again = 1;
886: return e;
887: }
888: /* Replace (e + e) with (e * 2) */
889: else if (el_match(e1,e2) && !el_sideeffect(e1) && !tyfloating(e->Ety))
890: {
891: e->Eoper = OPmul;
892: el_free(e2);
893: e->E2 = el_long(e->Ety,2);
894: again = 1;
895: return e;
896: }
897: // Replace ((e11 + c) + e2) with ((e11 + e2) + c)
898: if (e1->Eoper == OPadd && e1->E2->Eoper == OPconst &&
899: (e2->Eoper == OPvar || !OTleaf(e2->Eoper)) &&
900: tysize(e1->Ety) == tysize(e2->Ety) &&
901: tysize(e1->E2->Ety) == tysize(e2->Ety))
902: {
903: e->E2 = e1->E2;
904: e1->E2 = e2;
905: e1->Ety = e->Ety;
906: goto ret;
907: }
908:
909: // Replace ((e11 - e12) + e2) with ((e11 + e2) - e12)
910: // (this should increase the number of LEA possibilities)
911: sz = tysize(e->Ety);
912: if (e1->Eoper == OPmin &&
913: tysize(e1->Ety) == sz &&
914: tysize(e2->Ety) == sz &&
915: tysize(e1->E1->Ety) == sz &&
916: tysize(e1->E2->Ety) == sz &&
917: !tyfloating(e->Ety)
918: )
919: {
920: e->Eoper = OPmin;
921: e->E2 = e1->E2;
922: e1->E2 = e2;
923: e1->Eoper = OPadd;
924: }
925:
926: ret:
927: return e;
928: }
929:
930:
931: /************************
932: * Multiply (for OPmul && OPmulass)
933: * e * (c**2) => e << c ;replace multiply by power of 2 with shift
934: */
935:
936: STATIC elem * elmul(elem *e)
937: {
938: tym_t tym = e->Ety;
939:
940: if (OPTIMIZER)
941: {
942: // Replace -a*-b with a*b.
943: // This is valid for all floating point types as well as integers.
944: if (tyarithmetic(tym) && e->E2->Eoper == OPneg && e->E1->Eoper == OPneg)
945: {
946: e->E1 = el_selecte1(e->E1);
947: e->E2 = el_selecte1(e->E2);
948: }
949: }
950:
951: elem *e2 = e->E2;
952: if (e2->Eoper == OPconst) /* try to replace multiplies with shifts */
953: {
954: if (OPTIMIZER)
955: {
956: elem *e1 = e->E1;
957: unsigned op1 = e1->Eoper;
958:
959: if (tyintegral(tym) && // skip floating types
960: OTbinary(op1) &&
961: e1->E2->Eoper == OPconst
962: )
963: {
964: /* Attempt to replace ((e + c1) * c2) with (e * c2 + (c1 * c2))
965: * because the + can be frequently folded out (merged into an
966: * array offset, for example.
967: */
968: if (op1 == OPadd)
969: {
970: e->Eoper = OPadd;
971: e1->Eoper = OPmul;
972: e->E2 = el_bin(OPmul,tym,e1->E2,e2);
973: e1->E2 = el_copytree(e2);
974: again = 1;
975: return e;
976: }
977:
978: // ((e << c1) * c2) => e * ((1 << c1) * c2)
979: if (op1 == OPshl)
980: {
981: e2->EV.Vullong *= (targ_ullong)1 << el_tolong(e1->E2);
982: e1->E2->EV.Vullong = 0;
983: again = 1;
984: return e;
985: }
986: }
987:
988: if (elemisnegone(e2))
989: {
990: e->Eoper = (e->Eoper == OPmul) ? OPneg : OPnegass;
991: e->E2 = NULL;
992: el_free(e2);
993: return e;
994: }
995: }
996:
997: if (tyintegral(tym))
998: { int i;
999:
1000: i = ispow2(el_tolong(e2)); /* check for power of 2 */
1001: if (i != -1) /* if it is a power of 2 */
1002: { e2->EV.Vint = i;
1003: e2->Ety = TYint;
1004: e->Eoper = (e->Eoper == OPmul) /* convert to shift left */
1005: ? OPshl : OPshlass;
1006: again = 1;
1007: return e;
1008: }
1009: else if (el_allbits(e2,-1))
1010: goto Lneg;
1011: }
1012: else if (elemisnegone(e2) && !tycomplex(e->E1->Ety))
1013: {
1014: goto Lneg;
1015: }
1016: }
1017: return e;
1018:
1019: Lneg:
1020: e->Eoper = (e->Eoper == OPmul) /* convert to negate */
1021: ? OPneg : OPnegass;
1022: el_free(e->E2);
1023: e->E2 = NULL;
1024: again = 1;
1025: return e;
1026: }
1027:
1028: /************************
1029: * Subtract
1030: * - +
1031: * / \ => / \ (propagate minuses)
1032: * e c e -c
1033: */
1034:
1035: STATIC elem * elmin(elem *e)
1036: { elem *e2;
1037:
1038: L1:
warning C4102: 'L1' : unreferenced label
1039: e2 = e->E2;
1040:
1041: if (OPTIMIZER)
1042: {
1043: elem *e1;
1044: tym_t tym;
1045:
1046: tym = e->Ety;
1047: e1 = e->E1;
1048: if (e2->Eoper == OPrelconst)
1049: { if (e1->Eoper == OPrelconst && e1->EV.sp.Vsym == e2->EV.sp.Vsym)
1050: { e->Eoper = OPconst;
1051: e->EV.Vint = e1->EV.sp.Voffset - e2->EV.sp.Voffset;
1052: el_free(e1);
1053: el_free(e2);
1054: return e;
1055: }
1056: }
1057:
1058: /* Convert subtraction of long pointers to subtraction of integers */
1059: if (tyfv(e2->Ety) && tyfv(e1->Ety))
1060: { e->E1 = el_una(OPlngsht,tym,e1);
1061: e->E2 = el_una(OPlngsht,tym,e2);
1062: return optelem(e,TRUE);
1063: }
1064:
1065: /* Replace (0 - e2) with (-e2) */
1066: if (cnst(e1) && !boolres(e1))
1067: { el_free(e1);
1068: e->E1 = e2;
1069: e->E2 = NULL;
1070: e->Eoper = OPneg;
1071: return optelem(e,TRUE);
1072: }
1073:
1074: /* Replace (e - e) with (0) */
1075: if (el_match(e1,e2) && !el_sideeffect(e1))
1076: { el_free(e);
1077: e = el_calloc();
1078: e->Eoper = OPconst;
1079: e->Ety = tym;
1080: return e;
1081: }
1082:
1083: /* Replace (e1 + c1) - (e2 + c2) with (e1 - e2) + (c1 - c2), but not */
1084: /* for floating or far or huge pointers! */
1085: if (e1->Eoper == OPadd && e2->Eoper == OPadd &&
1086: cnst(e1->E2) && cnst(e2->E2) &&
1087: (tyintegral(tym) || tybasic(tym) == TYjhandle || tybasic(tym) == TYnptr || tybasic(tym) == TYsptr ))
1088: { elem *tmp;
1089:
1090: e->Eoper = OPadd;
1091: e1->Eoper = OPmin;
1092: e2->Eoper = OPmin;
1093: tmp = e1->E2;
1094: e1->E2 = e2->E1;
1095: e2->E1 = tmp;
1096: return optelem(e,TRUE);
1097: }
1098: }
1099:
1100: #if TX86 && !(MARS)
1101: if (tybasic(e2->Ety) == TYhptr && tybasic(e->E1->Ety) == TYhptr)
1102: { // Convert to _aNahdiff(e1,e2)
1103: static symbol hdiff = SYMBOLY(FLfunc,mBX|mCX|mSI|mDI|mBP|mES,"_aNahdiff",0);
1104:
1105: if (LARGECODE)
1106: hdiff.Sident[2] = 'F';
1107: hdiff.Stype = tsclib;
1108: e->Eoper = OPcall;
1109: e->E2 = el_bin(OPparam,TYint,e2,e->E1);
1110: e->E1 = el_var(&hdiff);
1111: return e;
1112: }
1113: #endif
1114:
1115: /* Disallow the optimization on doubles. The - operator is not */
1116: /* rearrangable by K+R, and can cause floating point problems if */
1117: /* converted to an add ((a + 1.0) - 1.0 shouldn't be folded). */
1118: if (cnst(e2) && !tyfloating(e2->Ety))
1119: { e->E2 = el_una(OPneg,e2->Ety,e2);
1120: e->Eoper = OPadd;
1121: return optelem(e,TRUE);
1122: }
1123: return e;
1124: }
1125:
1126: /*****************************
1127: * Attempt to 'shrink' bitwise expressions.
1128: * Good for & | ^.
1129: * This should be expanded to include long type stuff.
1130: */
1131:
1132: STATIC elem * elbitwise(elem *e)
1133: { elem *e1,*e2;
1134: targ_short i;
1135: targ_ulong ul;
1136: int op;
1137: unsigned sz;
1138:
1139: e2 = e->E2;
1140: e1 = e->E1;
1141: op = e1->Eoper;
1142: if (e2->Eoper == OPconst)
1143: {
1144: sz = tysize(e2->Ety);
1145: switch (sz)
1146: {
1147: tym_t tym;
1148: case CHARSIZE:
1149: /* Replace (c & 0xFF) with (c) */
1150: if (OPTIMIZER && e2->EV.Vuchar == CHARMASK)
1151: {
1152: L1:
1153: switch (e->Eoper)
1154: { case OPand: /* (c & 0xFF) => (c) */
1155: return el_selecte1(e);
1156: case OPor: /* (c | 0xFF) => (0xFF) */
1157: return el_selecte2(e);
1158: case OPxor: /* (c ^ 0xFF) => (~c) */
1159: tym = e->Ety;
1160: return el_una(OPcom,tym,el_selecte1(e));
1161: default:
1162: assert(0);
1163: }
1164: }
1165: break;
1166:
1167: case LONGSIZE:
1168: if (!OPTIMIZER)
1169: break;
1170: ul = e2->EV.Vulong;
1171:
1172: if (ul == 0xFFFFFFFF) /* if e1 & 0xFFFFFFFF */
1173: goto L1;
1174: /* (x >> 16) & 0xFFFF => ((unsigned long)x >> 16) */
1175: if (ul == 0xFFFF && e->Eoper == OPand && (op == OPshr || op == OPashr) &&
1176: e1->E2->Eoper == OPconst && el_tolong(e1->E2) == 16)
1177: { elem *e11 = e1->E1;
1178:
1179: e11->Ety = touns(e11->Ety) | (e11->Ety & ~mTYbasic);
1180: goto L1;
1181: }
1182:
1183: /* Replace (L & 0x0000XXXX) with (unslng)((lngsht) & 0xXXXX) */
1184: if (intsize < LONGSIZE &&
1185: e->Eoper == OPand &&
1186: ul <= SHORTMASK)
1187: { tym = e->Ety;
1188: e->E1 = el_una(OPlngsht,TYushort,e->E1);
1189: e->E2 = el_una(OPlngsht,TYushort,e->E2);
1190: e->Ety = TYushort;
1191: e = el_una(OPu16_32,tym,e);
1192: goto Lopt;
1193: }
1194:
1195: // Replace ((s8sht)L & 0xFF) with (u8sht)L
1196: if (ul == 0xFF && intsize == LONGSIZE && e->Eoper == OPand &&
1197: (op == OPs8int || op == OPu8int)
1198: )
1199: {
1200: e1->Eoper = OPu8int;
1201: e = el_selecte1(e);
1202: goto Lopt;
1203: }
1204:
1205: break;
1206:
1207: case SHORTSIZE:
1208: i = e2->EV.Vshort;
1209: if (i == (targ_short)SHORTMASK) // e2 & 0xFFFF
1210: goto L1;
1211:
1212: /* (x >> 8) & 0xFF => ((unsigned short)x >> 8) */
1213: if (OPTIMIZER && i == 0xFF && e->Eoper == OPand &&
1214: (op == OPshr || op == OPashr) && e1->E2->Eoper == OPconst && e1->E2->EV.Vint == 8)
1215: { elem *e11 = e1->E1;
1216:
1217: e11->Ety = touns(e11->Ety) | (e11->Ety & ~mTYbasic);
1218: goto L1;
1219: }
1220:
1221: // (s8_16(e) & 0xFF) => u8_16(e)
1222: if (OPTIMIZER && op == OPs8_16 && e->Eoper == OPand &&
1223: i == 0xFF)
1224: {
1225: e1->Eoper = OPu8_16;
1226: e = el_selecte1(e);
1227: goto Lopt;
1228: }
1229:
1230: if (
1231: /* OK for unsigned if AND or high bits of i are 0 */
1232: op == OPu8int && (e->Eoper == OPand || !(i & ~0xFF)) ||
1233: /* OK for signed if i is 'sign-extended' */
1234: op == OPs8int && (targ_short)(targ_schar)i == i
1235: )
1236: {
1237: /* Convert ((u8int) e) & i) to (u8int)(e & (int8) i) */
1238: /* or similar for s8int */
1239: e = el_una(e1->Eoper,e->Ety,e);
1240: e->E1->Ety = e1->Ety = e1->E1->Ety;
1241: e->E1->E1 = el_selecte1(e1);
1242: e->E1->E2 = el_una(OPint8,e->E1->Ety,e->E1->E2);
1243: goto Lopt;
1244: }
1245: break;
1246:
1247: #if __INTSIZE == 4
1248: case LLONGSIZE:
1249: if (OPTIMIZER)
1250: {
1251: if (e2->EV.Vullong == LLONGMASK)
1252: goto L1;
1253: }
1254: break;
1255: #endif
1256: }
1257: if (OPTIMIZER)
1258: { targ_ullong ul = el_tolong(e2);
warning C6246: Local declaration of 'ul' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '1135' of 'c:\projects\extern\d\dmd\src\backend\cgelem.c': Lines: 1135
1259:
1260: if (e->Eoper == OPor && op == OPand && e1->E2->Eoper == OPconst)
1261: {
1262: // ((x & c1) | c2) => (x | c2)
1263: targ_ullong c3;
1264:
1265: c3 = ul | e1->E2->EV.Vullong;
1266: switch (sz)
1267: { case CHARSIZE:
1268: if ((c3 & CHARMASK) == CHARMASK)
1269: goto L2;
1270: break;
1271: case SHORTSIZE:
1272: if ((c3 & SHORTMASK) == SHORTMASK)
1273: goto L2;
1274: break;
1275: case LONGSIZE:
1276: if ((c3 & LONGMASK) == LONGMASK)
1277: {
1278: L2:
1279: e1->E2->EV.Vullong = c3;
1280: e->E1 = elbitwise(e1);
1281: goto Lopt;
1282: }
1283: break;
1284: #if __INTSIZE == 4
1285: case LLONGSIZE:
1286: if ((c3 & LLONGMASK) == LLONGMASK)
1287: goto L2;
1288: break;
1289: #endif
1290: default:
1291: assert(0);
1292: }
1293: }
1294:
1295: #if __INTSIZE == 4
1296: if (op == OPshtlng && (ul & 0xFFFFFFFFFFFF8000LL) == 0 ||
1297: op == OPu16_32 && (ul & 0xFFFFFFFFFFFF0000LL) == 0 ||
1298: op == OPs8int && (ul & 0xFFFFFFFFFFFFFF80LL) == 0 ||
1299: op == OPu8int && (ul & 0xFFFFFFFFFFFFFF00LL) == 0 ||
1300: op == OPlngllng && (ul & 0xFFFFFFFF80000000LL) == 0 ||
1301: op == OPu32_64&& (ul & 0xFFFFFFFF00000000LL) == 0
1302: )
1303: #else
1304: if (op == OPshtlng && (ul & 0xFFFF8000) == 0 ||
1305: op == OPu16_32 && (ul & 0xFFFF0000) == 0 ||
1306: op == OPs8int && (ul & 0xFFFFFF80) == 0 ||
1307: op == OPu8int && (ul & 0xFFFFFF00) == 0)
1308: #endif
1309: {
1310: if (e->Eoper == OPand)
1311: { if (op == OPshtlng && (ul & 0x8000) == 0)
1312: e1->Eoper = OPu16_32;
1313: else if (op == OPs8int && (ul & 0x80) == 0)
1314: e1->Eoper = OPu8int;
1315: #if __INTSIZE == 4
1316: else if (op == OPlngllng && (ul & 0x80000000) == 0)
1317: e1->Eoper = OPu32_64;
1318: #endif
1319: }
1320:
1321: // ((shtlng)s & c) => ((shtlng)(s & c)
1322: e1->Ety = e->Ety;
1323: e->Ety = e2->Ety = e1->E1->Ety;
1324: e->E1 = e1->E1;
1325: e1->E1 = e;
1326: e = e1;
1327: goto Lopt;
1328: }
1329:
1330: // Replace (((a & b) ^ c) & d) with ((a ^ c) & e), where
1331: // e is (b&d).
1332: if (e->Eoper == OPand && op == OPxor && e1->E1->Eoper == OPand &&
1333: e1->E1->E2->Eoper == OPconst)
1334: {
1335: e2->EV.Vullong &= e1->E1->E2->EV.Vullong;
1336: e1->E1 = el_selecte1(e1->E1);
1337: goto Lopt;
1338: }
1339: }
1340: }
1341: return e;
1342:
1343: Lopt:
1344: #ifdef DEBUG
1345: static int nest;
1346: nest++;
1347: if (nest > 100)
1348: { elem_print(e);
1349: assert(0);
1350: }
1351: e = optelem(e,TRUE);
1352: nest--;
1353: return e;
1354: #endif
1355: return optelem(e,TRUE);
1356: }
1357:
1358:
1359: /*************************************
1360: * Replace shift|shift with rotate.
1361: */
1362:
1363: STATIC elem *elor(elem *e)
1364: {
1365: /* ROL: (a << shift) | (a >> (sizeof(a) * 8 - shift))
1366: * ROR: (a >> shift) | (a << (sizeof(a) * 8 - shift))
1367: */
1368: elem *e1 = e->E1;
1369: elem *e2 = e->E2;
1370: unsigned sz = tysize(e->Ety);
1371: if (sz <= intsize)
warning C4018: '<=' : signed/unsigned mismatch
1372: {
1373: if (e1->Eoper == OPshl && e2->Eoper == OPshr &&
1374: tyuns(e2->E1->Ety) && e2->E2->Eoper == OPmin &&
1375: e2->E2->E1->Eoper == OPconst &&
1376: el_tolong(e2->E2->E1) == sz * 8 &&
1377: el_match5(e1->E1, e2->E1) &&
1378: el_match5(e1->E2, e2->E2->E2) &&
1379: !el_sideeffect(e)
1380: )
1381: {
1382: e1->Eoper = OProl;
1383: return el_selecte1(e);
1384: }
1385: if (e1->Eoper == OPshr && e2->Eoper == OPshl &&
1386: tyuns(e1->E1->Ety) && e2->E2->Eoper == OPmin &&
1387: e2->E2->E1->Eoper == OPconst &&
1388: el_tolong(e2->E2->E1) == sz * 8 &&
1389: el_match5(e1->E1, e2->E1) &&
1390: el_match5(e1->E2, e2->E2->E2) &&
1391: !el_sideeffect(e)
1392: )
1393: {
1394: e1->Eoper = OPror;
1395: return el_selecte1(e);
1396: }
1397: }
1398: return elbitwise(e);
1399: }
1400:
1401: /*************************************
1402: */
1403:
1404: STATIC elem *elxor(elem *e)
1405: {
1406: if (OPTIMIZER)
1407: {
1408: elem *e1 = e->E1;
1409: elem *e2 = e->E2;
1410:
1411: /* Recognize:
1412: * (a & c) ^ (b & c) => (a ^ b) & c
1413: */
1414: if (e1->Eoper == OPand && e2->Eoper == OPand &&
1415: el_match5(e1->E2, e2->E2) &&
1416: (e2->E2->Eoper == OPconst || (!el_sideeffect(e2->E1) && !el_sideeffect(e2->E2))))
1417: {
1418: el_free(e1->E2);
1419: e1->E2 = e2->E1;
1420: e1->Eoper = OPxor;
1421: e->Eoper = OPand;
1422: e->E2 = e2->E2;
1423: e2->E1 = NULL;
1424: e2->E2 = NULL;
1425: el_free(e2);
1426: return optelem(e, TRUE);
1427: }
1428: }
1429: return elbitwise(e);
1430: }
1431:
1432: /**************************
1433: * Optimize nots.
1434: * ! ! e => bool e
1435: * ! bool e => ! e
1436: * ! OTrel => !OTrel (invert the condition)
1437: * ! OTconv => !
1438: */
1439:
1440: STATIC elem * elnot(elem *e)
1441: { elem *e1;
1442: unsigned op;
1443:
1444: e1 = e->E1;
1445: op = e1->Eoper;
1446: switch (op)
1447: { case OPnot: // ! ! e => bool e
1448: case OPbool: // ! bool e => ! e
1449: e1->Eoper = op ^ (OPbool ^ OPnot);
1450: /* That was a clever substitute for the following: */
1451: /* e->Eoper = (op == OPnot) ? OPbool : OPnot; */
1452: goto L1;
1453:
1454: default:
1455: if (OTrel(op)) /* ! OTrel => !OTrel */
1456: {
1457: /* Find the logical negation of the operator */
1458: op = rel_not(op);
1459: if (!tyfloating(e1->E1->Ety))
1460: { op = rel_integral(op);
1461: assert(OTrel(op));
1462: }
1463: e1->Eoper = op;
1464:
1465: L1: e = optelem(el_selecte1(e),TRUE);
1466: }
1467: else if (tybasic(e1->Ety) == TYbool && tysize(e->Ety) == 1)
1468: {
1469: // !e1 => (e1 ^ 1)
1470: e->Eoper = OPxor;
1471: e->E2 = el_long(e1->Ety,1);
1472: e = optelem(e,TRUE);
1473: }
1474: #if 0
1475: // Can't use this because what if OPd_s32?
1476: // Note: !(long)(.1) != !(.1)
1477: else if (OTconv(op)) // don't use case because of differ target
1478: { // conversion operators
1479: e1->Eoper = e->Eoper;
1480: goto L1;
1481: }
1482: #endif
1483: break;
1484:
1485: case OPs32_d:
1486: case OPs16_d:
1487: case OPu16_d:
1488: case OPu32_d:
1489: case OPf_d:
1490: case OPvptrfptr:
1491: case OPcvptrfptr:
1492: case OPshtlng:
1493: case OPu16_32:
1494: case OPu8int:
1495: case OPs8int:
1496: case OPu32_64:
1497: case OPlngllng:
1498: case OPptrlptr:
1499: e1->Eoper = e->Eoper;
1500: goto L1;
1501:
1502: case OPcomma:
1503: /* !(a,b) => (a,!b) */
1504: e->Eoper = OPcomma;
1505: e->E1 = e1->E1; // a
1506: e->E2 = e1; // !
1507: e1->Eoper = OPnot;
1508: e1->Ety = e->Ety;
1509: e1->E1 = e1->E2; // b
1510: e1->E2 = NULL;
1511: e = optelem(e,TRUE);
1512: break;
1513: }
1514: return e;
1515: }
1516:
1517: /*************************
1518: * Complement
1519: * ~ ~ e => e
1520: */
1521:
1522: STATIC elem * elcom(elem *e)
1523: { elem *e1;
1524:
1525: e1 = e->E1;
1526: if (e1->Eoper == OPcom) /* ~ ~ e => e */
1527: /* Typing problem here */
1528: e = el_selecte1(el_selecte1(e));
1529: return e;
1530: }
1531:
1532: /*************************
1533: * If it is a conditional of a constant
1534: * then we know which exp to evaluate.
1535: * BUG:
1536: * doesn't detect ("string" ? et : ef)
1537: */
1538:
1539: STATIC elem * elcond(elem *e)
1540: { elem *e1;
1541: elem *ex;
1542:
1543: e1 = e->E1;
1544: switch (e1->Eoper)
1545: { case OPconst:
1546: if (boolres(e1))
1547: L1:
1548: e = el_selecte1(el_selecte2(e));
1549: else
1550: e = el_selecte2(el_selecte2(e));
1551: break;
1552: case OPrelconst:
1553: case OPstring:
1554: goto L1;
1555:
1556: case OPcomma:
1557: // ((a,b) ? c) => (a,(b ? c))
1558: e->Eoper = OPcomma;
1559: e->E1 = e1->E1;
1560: e1->E1 = e1->E2;
1561: e1->E2 = e->E2;
1562: e->E2 = e1;
1563: e1->Eoper = OPcond;
1564: e1->Ety = e->Ety;
1565: return optelem(e,TRUE);
1566:
1567: case OPnot:
1568: // (!a ? b : c) => (a ? c : b)
1569: ex = e->E2->E1;
1570: e->E2->E1 = e->E2->E2;
1571: e->E2->E2 = ex;
1572: goto L2;
1573:
1574: default:
1575: if (OTboolnop(e1->Eoper))
warning C6385: Invalid data: accessing 'unsigned char const * const optab3', the readable size is '183' bytes, but '1143' bytes might be read: Lines: 1540, 1541, 1543, 1544, 1574, 1575
1576: {
1577: L2:
1578: e->E1 = e1->E1;
1579: e1->E1 = NULL;
1580: el_free(e1);
1581: return elcond(e);
1582: }
1583: {
1584: if (OPTIMIZER)
1585: {
1586: elem *ec1,*ec2;
1587: tym_t ty = e->Ety;
1588:
1589: ec1 = e->E2->E1;
1590: ec2 = e->E2->E2;
1591: if (tyintegral(ty) && ec1->Eoper == OPconst && ec2->Eoper == OPconst)
1592: { targ_llong i1,i2;
1593: targ_llong b;
1594:
1595: i1 = el_tolong(ec1);
1596: i2 = el_tolong(ec2);
1597:
1598: /* If b is an integer with only 1 bit set then */
1599: /* replace ((a & b) ? b : 0) with (a & b) */
1600: /* replace ((a & b) ? 0 : b) with ((a & b) ^ b) */
1601: if (e1->Eoper == OPand && e1->E2->Eoper == OPconst &&
1602: tysize(ty) == tysize(ec1->Ety))
1603: {
1604: b = el_tolong(e1->E2);
1605: if (ispow2(b) != -1) /* if only 1 bit is set */
1606: {
1607: if (b == i1 && i2 == 0)
1608: { e = el_selecte1(e);
1609: e->E1->Ety = ty;
1610: e->E2->Ety = ty;
1611: e->E2->EV.Vllong = b;
1612: return optelem(e,TRUE);
1613: }
1614: else if (i1 == 0 && b == i2)
1615: {
1616: e1->Ety = ty;
1617: e1->E1->Ety = ty;
1618: e1->E2->Ety = ty;
1619: e1->E2->EV.Vllong = b;
1620: e->E1 = el_bin(OPxor,ty,e1,el_long(ty,b));
1621: e = el_selecte1(e);
1622: return optelem(e,TRUE);
1623: }
1624: }
1625: }
1626:
1627: /* Replace ((a relop b) ? 1 : 0) with (a relop b) */
1628: else if (OTrel(e1->Eoper) &&
1629: tysize(ty) <= tysize[TYint])
1630: {
1631: if (i1 == 1 && i2 == 0)
1632: e = el_selecte1(e);
1633: else if (i1 == 0 && i2 == 1)
1634: {
1635: e->E1 = el_una(OPnot,ty,e1);
1636: e = optelem(el_selecte1(e),TRUE);
1637: }
1638: }
1639: #if TX86
1640: // The next two optimizations attempt to replace with an
1641: // unsigned compare, which the code generator can generate
1642: // code for without using jumps.
1643:
1644: // Try to replace (!e1) with (e1 < 1)
1645: else if (e1->Eoper == OPnot && !OTrel(e1->E1->Eoper))
1646: {
1647: e->E1 = el_bin(OPlt,TYint,e1->E1,el_long(touns(e1->E1->Ety),1));
1648: e1->E1 = NULL;
1649: el_free(e1);
1650: }
1651: // Try to replace (e1) with (e1 >= 1)
1652: else if (!OTrel(e1->Eoper))
1653: {
1654: if (tyfv(e1->Ety))
1655: {
1656: if (tysize(e->Ety) == tysize[TYint])
1657: {
1658: if (i1 == 1 && i2 == 0)
1659: { e->Eoper = OPbool;
1660: el_free(e->E2);
1661: e->E2 = NULL;
1662: }
1663: else if (i1 == 0 && i2 == 1)
1664: { e->Eoper = OPnot;
1665: el_free(e->E2);
1666: e->E2 = NULL;
1667: }
1668: }
1669: }
1670: else
1671: e->E1 = el_bin(OPge,TYint,e1,el_long(touns(e1->Ety),1));
1672: }
1673: #endif
1674: }
1675:
1676: // Try to detect absolute value expression
1677: // (a < 0) -a : a
1678: if ((e1->Eoper == OPlt || e1->Eoper == OPle) &&
1679: e1->E2->Eoper == OPconst &&
1680: !boolres(e1->E2) &&
1681: !tyuns(e1->E1->Ety) &&
1682: !tyuns(e1->E2->Ety) &&
1683: ec1->Eoper == OPneg &&
1684: !el_sideeffect(ec2) &&
1685: el_match(e->E1->E1,ec2) &&
1686: el_match(ec1->E1,ec2) &&
1687: tysize(ty) >= intsize
1688: )
1689: { e->E2->E2 = NULL;
1690: el_free(e);
1691: e = el_una(OPabs,ty,ec2);
1692: }
1693: // (a >= 0) a : -a
1694: else if ((e1->Eoper == OPge || e1->Eoper == OPgt) &&
1695: e1->E2->Eoper == OPconst &&
1696: !boolres(e1->E2) &&
1697: !tyuns(e1->E1->Ety) &&
1698: !tyuns(e1->E2->Ety) &&
1699: ec2->Eoper == OPneg &&
1700: !el_sideeffect(ec1) &&
1701: el_match(e->E1->E1,ec1) &&
1702: el_match(ec2->E1,ec1) &&
1703: tysize(ty) >= intsize
1704: )
1705: { e->E2->E1 = NULL;
1706: el_free(e);
1707: e = el_una(OPabs,ty,ec1);
1708: }
1709: break;
1710: }
1711: }
1712: }
1713: return e;
1714: }
1715:
1716:
1717: /****************************
1718: * Comma operator.
1719: * , e
1720: * / \ => expression with no effect
1721: * c e
1722: * , ,
1723: * / \ => / \ operators with no effect
1724: * + e , e
1725: * / \ / \
1726: * e e e e
1727: */
1728:
1729: STATIC elem * elcomma(elem *e)
1730: { register elem *e1,**pe1;
1731: elem *e2;
1732: int e1op;
1733: int changes;
1734:
1735: changes = -1;
1736: L1:
1737: changes++;
1738: L2:
1739: //printf("elcomma()\n");
1740: e2 = e->E2;
1741: pe1 = &(e->E1);
1742: e1 = *pe1;
1743: e1op = e1->Eoper;
1744:
1745: /* c,e => e */
1746: if (OTleaf(e1op) && !OTsideff(e1op) && !(e1->Ety & mTYvolatile))
1747: { e2->Ety = e->Ety;
1748: e = el_selecte2(e);
1749: goto Lret;
1750: }
1751:
1752: /* ((a op b),e2) => ((a,b),e2) if op has no side effects */
1753: if (!el_sideeffect(e1) && e1op != OPcomma && e1op != OPandand &&
1754: e1op != OPoror && e1op != OPcond)
1755: {
1756: if (OTunary(e1op))
1757: *pe1 = el_selecte1(e1); /* get rid of e1 */
1758: else
1759: { e1->Eoper = OPcomma;
1760: e1->Ety = e1->E2->Ety;
1761: }
1762: goto L1;
1763: }
1764:
1765: if (!OPTIMIZER)
1766: goto Lret;
1767:
1768: /* Replace (a,b),e2 with a,(b,e2) */
1769: if (e1op == OPcomma)
1770: {
1771: e1->Ety = e->Ety;
1772: e->E1 = e1->E1;
1773: e1->E1 = e1->E2;
1774: e1->E2 = e2;
1775: e->E2 = elcomma(e1);
1776: goto L2;
1777: }
1778:
1779: if ((OTopeq(e1op) || e1op == OPeq) &&
1780: (e1->E1->Eoper == OPvar || e1->E1->Eoper == OPind) &&
1781: !el_sideeffect(e1->E1)
1782: )
1783: {
1784: if (el_match(e1->E1,e2))
1785: // ((a = b),a) => (a = b)
1786: e = el_selecte1(e);
1787: else if (OTrel(e2->Eoper) &&
1788: OTleaf(e2->E2->Eoper) &&
1789: el_match(e1->E1,e2->E1)
1790: )
1791: { // ((a = b),(a < 0)) => ((a = b) < 0)
1792: e1->Ety = e2->E1->Ety;
1793: e->E1 = e2->E1;
1794: e2->E1 = e1;
1795: goto L1;
1796: }
1797: else if ((e2->Eoper == OPandand ||
1798: e2->Eoper == OPoror ||
1799: e2->Eoper == OPcond) &&
1800: el_match(e1->E1,e2->E1)
1801: )
1802: {
1803: /* ((a = b),(a || c)) => ((a = b) || c) */
1804: e1->Ety = e2->E1->Ety;
1805: e->E1 = e2->E1;
1806: e2->E1 = e1;
1807: e = el_selecte2(e);
1808: changes++;
1809: goto Lret;
1810: }
1811: else if (e1op == OPeq)
1812: {
1813: /* Replace ((a = b),(c = a)) with a,(c = (a = b)) */
1814: for (; e2->Eoper == OPcomma; e2 = e2->E1)
1815: ;
1816: if ((OTopeq(e2->Eoper) || e2->Eoper == OPeq) &&
1817: el_match(e1->E1,e2->E2) &&
1818: #if 0
1819: !(e1->E1->Eoper == OPvar && el_appears(e2->E1,e1->E1->EV.sp.Vsym)) &&
1820: #endif
1821: ERTOL(e2))
1822: {
1823: e->E1 = e2->E2;
1824: e1->Ety = e2->E2->Ety;
1825: e2->E2 = e1;
1826: goto L1;
1827: }
1828: }
1829: else
1830: {
1831: #if 1 // This optimization is undone in eleq().
1832: // Replace ((a op= b),(a op= c)) with (0,a = (a op b) op c)
1833: for (; e2->Eoper == OPcomma; e2 = e2->E1)
1834: ;
1835: if ((OTopeq(e2->Eoper)) &&
1836: el_match(e1->E1,e2->E1))
1837: { elem *ex;
warning C4101: 'ex' : unreferenced local variable
1838:
1839: e->E1 = el_long(TYint,0);
1840: e1->Eoper = opeqtoop(e1op);
1841: e2->E2 = el_bin(opeqtoop(e2->Eoper),e2->Ety,e1,e2->E2);
1842: e2->Eoper = OPeq;
1843: goto L1;
1844: }
1845: #endif
1846: }
1847: }
1848: Lret:
1849: again = changes != 0;
1850: return e;
1851: }
1852:
1853: /********************************
1854: */
1855:
1856: STATIC elem * elremquo(elem *e)
1857: {
1858: #if 0 && MARS
1859: if (cnst(e->E2) && !boolres(e->E2))
1860: error(e->Esrcpos.Sfilename, e->Esrcpos.Slinnum, "divide by zero\n");
1861: #endif
1862: return e;
1863: }
1864:
1865: /********************************
1866: */
1867:
1868: STATIC elem * elmod(elem *e)
1869: {
1870: elem *e1;
warning C4101: 'e1' : unreferenced local variable
1871: elem *e2;
warning C4101: 'e2' : unreferenced local variable
1872: tym_t tym;
1873:
1874: tym = e->E1->Ety;
1875: if (!tyfloating(tym))
1876: return eldiv(e);
1877: return e;
1878: }
1879:
1880: /*****************************
1881: * Convert divides to >> if power of 2.
1882: * Can handle OPdiv, OPdivass, OPmod.
1883: */
1884:
1885: STATIC elem * eldiv(elem *e)
1886: { elem *e2;
1887: tym_t tym;
1888: int uns;
1889:
1890: e2 = e->E2;
1891: tym = e->E1->Ety;
1892: uns = tyuns(tym) | tyuns(e2->Ety);
1893: if (cnst(e2))
1894: {
1895: #if 0 && MARS
1896: if (!boolres(e2))
1897: error(e->Esrcpos.Sfilename, e->Esrcpos.Slinnum, "divide by zero\n");
1898: #endif
1899: if (uns)
1900: { int i;
1901:
1902: e2->Ety = touns(e2->Ety);
1903: i = ispow2(el_tolong(e2));
1904: if (i != -1)
1905: { int op;
1906:
1907: switch (e->Eoper)
1908: { case OPdiv:
1909: op = OPshr;
1910: goto L1;
1911: case OPdivass:
1912: op = OPshrass;
1913: L1:
1914: e2->EV.Vint = i;
1915: e2->Ety = TYint;
1916: e->E1->Ety = touns(tym);
1917: break;
1918:
1919: case OPmod:
1920: op = OPand;
1921: goto L3;
1922: case OPmodass:
1923: op = OPandass;
1924: L3:
1925: e2->EV.Vullong = el_tolong(e2) - 1;
1926: break;
1927:
1928: default:
1929: assert(0);
1930: }
1931: e->Eoper = op;
1932: return optelem(e,TRUE);
1933: }
1934: }
1935: }
1936:
1937: if (OPTIMIZER)
1938: {
1939: if (tyintegral(tym) && (e->Eoper == OPdiv || e->Eoper == OPmod))
1940: { int sz = tysize(tym);
1941:
1942: // See if we can replace with OPremquo
1943: if (sz == REGSIZE /*&& !I64*/) // need cent and ucent working for I64 to work
1944: {
1945: // Don't do it if there are special code sequences in the
1946: // code generator (see cdmul())
1947: int pow2;
1948: if (e->E2->Eoper == OPconst &&
1949: sz == REGSIZE && !uns &&
1950: (pow2 = ispow2(el_tolong(e->E2))) != -1 &&
1951: !(config.target_cpu < TARGET_80286 && pow2 != 1 && e->Eoper == OPdiv)
1952: )
1953: ;
1954: else
1955: {
1956: assert(sz == 2 || sz == 4 || sz == 8);
1957: int op = OPmsw;
1958: if (e->Eoper == OPdiv)
1959: {
1960: op = (sz == 2) ? OP32_16 : (sz == 4) ? OP64_32 : OP128_64;
1961: }
1962: e->Eoper = OPremquo;
1963: e = el_una(op, tym, e);
1964: e->E1->Ety = (sz == 2) ? TYlong : (sz == 4) ? TYllong : TYcent;
1965: }
1966: }
1967: }
1968: }
1969:
1970: return e;
1971: }
1972:
1973: /**************************
1974: * Convert (a op b) op c to a op (b op c).
1975: */
1976:
1977: STATIC elem * swaplog(elem *e)
1978: { elem *e1;
1979:
1980: e1 = e->E1;
1981: e->E1 = e1->E2;
1982: e1->E2 = e;
1983: return optelem(e1,TRUE);
1984: }
1985:
1986: STATIC elem * eloror(elem *e)
1987: { elem *e1,*e2;
1988: tym_t t;
1989: tym_t ty1,ty2;
1990:
1991: e1 = e->E1;
1992: if (OTboolnop(e1->Eoper))
1993: {
1994: e->E1 = e1->E1;
1995: e1->E1 = NULL;
1996: el_free(e1);
1997: return eloror(e);
1998: }
1999: e2 = e->E2;
2000: if (OTboolnop(e2->Eoper))
2001: {
2002: e->E2 = e2->E1;
2003: e2->E1 = NULL;
2004: el_free(e2);
2005: return eloror(e);
2006: }
2007: if (OPTIMIZER)
2008: {
2009: if (e1->Eoper == OPbool)
2010: { ty1 = e1->E1->Ety;
2011: e1 = e->E1 = el_selecte1(e1);
2012: e1->Ety = ty1;
2013: }
2014: if (e1->Eoper == OPoror)
2015: { /* convert (a||b)||c to a||(b||c). This will find more CSEs. */
2016: return swaplog(e);
2017: }
2018: e2 = elscancommas(e2);
2019: e1 = elscancommas(e1);
2020: }
2021:
2022: t = e->Ety;
2023: if (e2->Eoper == OPconst || e2->Eoper == OPrelconst || e2->Eoper == OPstring)
2024: {
2025: if (boolres(e2)) /* e1 || 1 => e1 , 1 */
2026: { if (e->E2 == e2)
2027: goto L2;
2028: }
2029: else /* e1 || 0 => bool e1 */
2030: { if (e->E2 == e2)
2031: {
2032: el_free(e->E2);
2033: e->E2 = NULL;
2034: e->Eoper = OPbool;
2035: goto L3;
2036: }
2037: }
2038: }
2039:
2040: if (e1->Eoper == OPconst || e1->Eoper == OPrelconst || e1->Eoper == OPstring)
2041: {
2042: if (boolres(e1)) /* (x,1) || e2 => (x,1),1 */
2043: {
2044: L2:
2045: e->Eoper = OPcomma;
2046: el_free(e->E2);
2047: e->E2 = el_int(t,1);
2048: }
2049: else /* (x,0) || e2 => (x,0),(bool e2) */
2050: { e->Eoper = OPcomma;
2051: if (tybasic(e->E2->Ety) != TYvoid)
2052: e->E2 = el_una(OPbool,t,e->E2);
2053: }
2054: }
2055: else if (OPTIMIZER &&
2056: e->E2->Eoper == OPvar &&
2057: !OTlogical(e1->Eoper) &&
2058: tysize(ty2 = e2->Ety) == tysize(ty1 = e1->Ety) &&
2059: tysize(ty1) <= intsize &&
2060: !tyfloating(ty2) &&
2061: !tyfloating(ty1) &&
2062: !(ty2 & mTYvolatile))
2063: { /* Convert (e1 || e2) => (e1 | e2) */
2064: e->Eoper = OPor;
2065: e->Ety = ty1;
2066: e = el_una(OPbool,t,e);
2067: }
2068: else if (OPTIMIZER &&
2069: e1->Eoper == OPand && e2->Eoper == OPand &&
2070: tysize(e1->Ety) == tysize(e2->Ety) &&
2071: el_match(e1->E1,e2->E1) && !el_sideeffect(e1->E1) &&
2072: !el_sideeffect(e2->E2)
2073: )
2074: { // Convert ((a & b) || (a & c)) => bool(a & (b | c))
2075: e->Eoper = OPbool;
2076: e->E2 = NULL;
2077: e2->Eoper = OPor;
2078: el_free(e2->E1);
2079: e2->E1 = e1->E2;
2080: e1->E2 = e2;
2081: }
2082: else
2083: goto L1;
2084: L3:
2085: e = optelem(e,TRUE);
2086: L1:
2087: return e;
2088: }
2089:
2090: STATIC elem * elandand(elem *e)
2091: {
2092: elem *e1 = e->E1;
2093: if (OTboolnop(e1->Eoper))
2094: {
2095: e->E1 = e1->E1;
2096: e1->E1 = NULL;
2097: el_free(e1);
2098: return elandand(e);
2099: }
2100: elem *e2 = e->E2;
2101: if (OTboolnop(e2->Eoper))
2102: {
2103: e->E2 = e2->E1;
2104: e2->E1 = NULL;
2105: el_free(e2);
2106: return elandand(e);
2107: }
2108: if (OPTIMIZER)
2109: {
2110: /* Recognize: (a >= c1 && a < c2)
2111: */
2112: if ((e1->Eoper == OPge || e1->Eoper == OPgt) &&
2113: (e2->Eoper == OPlt || e2->Eoper == OPle) &&
2114: e1->E2->Eoper == OPconst && e2->E2->Eoper == OPconst &&
2115: !el_sideeffect(e1->E1) && el_match(e1->E1, e2->E1) &&
2116: tyintegral(e1->E1->Ety) &&
2117: tybasic(e1->E2->Ety) == tybasic(e2->E2->Ety) &&
2118: tysize(e1->E1->Ety) == NPTRSIZE)
2119: {
2120: /* Replace with: ((a - c1) < (c2 - c1))
2121: */
2122: targ_llong c1 = el_tolong(e1->E2);
2123: if (e1->Eoper == OPgt)
2124: ++c1;
2125: targ_llong c2 = el_tolong(e2->E2);
2126: if (0 <= c1 && c1 <= c2)
2127: {
2128: e1->Eoper = OPmin;
2129: e1->Ety = e1->E1->Ety;
2130: e1->E2->EV.Vllong = c1;
2131: e->E2 = el_long(touns(e2->E2->Ety), c2 - c1);
2132: e->Eoper = e2->Eoper;
2133: el_free(e2);
2134: return optelem(e, TRUE);
2135: }
2136: }
2137:
2138: // Look for (!(e >>> c) && ...)
2139: if (e1->Eoper == OPnot && e1->E1->Eoper == OPshr &&
2140: e1->E1->E2->Eoper == OPconst)
2141: {
2142: // Replace (e >>> c) with (e & x)
2143: elem *e11 = e1->E1;
2144:
2145: targ_ullong shift = el_tolong(e11->E2);
2146: if (shift < intsize * 8)
2147: { targ_ullong m;
2148:
2149: m = ~0LL << (int)shift;
2150: e11->Eoper = OPand;
2151: e11->E2->EV.Vullong = m;
2152: e11->E2->Ety = e11->Ety;
2153: return optelem(e,TRUE);
2154: }
2155: }
2156:
2157: if (e1->Eoper == OPbool)
2158: { tym_t t = e1->E1->Ety;
2159: e1 = e->E1 = el_selecte1(e1);
2160: e1->Ety = t;
2161: }
2162: if (e1->Eoper == OPandand)
2163: { /* convert (a&&b)&&c to a&&(b&&c). This will find more CSEs. */
2164: return swaplog(e);
2165: }
2166: e2 = elscancommas(e2);
2167:
2168: while (1)
2169: { e1 = elscancommas(e1);
2170: if (e1->Eoper == OPeq)
2171: e1 = e1->E2;
2172: else
2173: break;
2174: }
2175: }
2176:
2177: if (e2->Eoper == OPconst || e2->Eoper == OPrelconst || e2->Eoper == OPstring)
2178: { if (boolres(e2)) /* e1 && (x,1) => e1 ? ((x,1),1) : 0 */
2179: {
2180: if (e2 == e->E2) /* if no x, replace e with (bool e1) */
2181: { el_free(e2);
2182: e->E2 = NULL;
2183: e->Eoper = OPbool;
2184: goto L3;
2185: }
2186: }
2187: else /* e1 && (x,0) => e1 , (x,0) */
2188: { if (e2 == e->E2)
2189: { e->Eoper = OPcomma;
2190: goto L3;
2191: }
2192: }
2193: }
2194:
2195: if (e1->Eoper == OPconst || e1->Eoper == OPrelconst || e1->Eoper == OPstring)
2196: {
2197: e->Eoper = OPcomma;
2198: if (boolres(e1)) /* (x,1) && e2 => (x,1),bool e2 */
2199: {
2200: e->E2 = el_una(OPbool,e->Ety,e->E2);
2201: }
2202: else /* (x,0) && e2 => (x,0),0 */
2203: {
2204: el_free(e->E2);
2205: e->E2 = el_int(e->Ety,0);
2206: }
2207: }
2208: else
2209: goto L1;
2210: L3:
2211: e = optelem(e,TRUE);
2212: L1:
2213: return e;
2214: }
2215:
2216: /**************************
2217: * Reference to bit field
2218: * bit
2219: * / \ => ((e << c) >> b) & m
2220: * e w,b
2221: *
2222: * Note that this routine can handle long bit fields, though this may
2223: * not be supported later on.
2224: */
2225:
2226: STATIC elem * elbit(elem *e)
2227: { unsigned wb,w,b,c;
2228: targ_ullong m;
2229: elem *e2;
2230: tym_t tym1;
2231: unsigned sz;
2232:
2233: tym1 = e->E1->Ety;
2234: sz = tysize(tym1) * 8;
2235: e2 = e->E2;
2236: wb = e2->EV.Vuns;
2237:
2238: w = (wb >> 8) & 0xFF; /* width in bits of field */
2239: m = ((targ_ullong)1 << w) - 1; // mask w bits wide
2240: b = wb & 0xFF; /* bits to right of field */
2241: c = 0;
2242: assert(w + b <= sz);
2243:
2244: if (tyuns(tym1)) /* if unsigned bit field */
2245: {
2246: #if 1 /* Should use a more general solution to this */
2247: if (w == 8 && sz == 16 && b == 0)
2248: {
2249: e->E1 = el_una(OPint8,TYuchar,e->E1);
2250: e->Eoper = OPu8int;
2251: e->E2 = NULL;
2252: el_free(e2);
2253: goto L1;
2254: }
2255: #endif
2256: if (w + b == sz) /* if field is left-justified */
2257: m = ~(targ_ullong)0; // no need to mask
2258: }
2259: else /* signed bit field */
2260: {
2261: if (w == 8 && sz == 16 && b == 0)
2262: {
2263: #if 1
2264: e->E1 = el_una(OPint8,TYschar,e->E1);
2265: e->Eoper = OPs8int;
2266: e->E2 = NULL;
2267: el_free(e2);
2268: goto L1;
2269: #endif
2270: }
2271: m = ~(targ_ullong)0;
2272: c = sz - (w + b);
2273: b = sz - w;
2274: }
2275:
2276: e->Eoper = OPand;
2277:
2278: e2->EV.Vullong = m; /* mask w bits wide */
2279: e2->Ety = e->Ety;
2280:
2281: e->E1 = el_bin(OPshr,tym1,
2282: el_bin(OPshl,tym1,e->E1,el_int(TYint,c)),
2283: el_int(TYint,b));
2284: L1:
2285: return optelem(e,TRUE); /* optimize result */
2286: }
2287:
2288: /*****************
2289: * Indirection
2290: * * & e => e
2291: */
2292:
2293: STATIC elem * elind(elem *e)
2294: { elem *e1;
2295: tym_t tym;
2296:
2297: tym = e->Ety;
2298: e1 = e->E1;
2299: switch (e1->Eoper)
2300: { case OPrelconst:
2301: {
2302: e->E1->ET = e->ET;
2303: e = el_selecte1(e);
2304: e->Eoper = OPvar;
2305: e->Ety = tym; /* preserve original type */
2306: }
2307: break;
2308: case OPadd:
2309: #if TX86
2310: if (OPTIMIZER)
2311: { /* Try to convert far pointer to stack pointer */
2312: elem *e12 = e1->E2;
2313:
2314: if (e12->Eoper == OPrelconst &&
2315: tybasic(e12->Ety) == TYfptr &&
2316: /* If symbol is located on the stack */
2317: sytab[e12->EV.sp.Vsym->Sclass] & SCSS)
2318: { e1->Ety = (e1->Ety & (mTYconst | mTYvolatile | mTYimmutable | mTYshared | mTYLINK)) | TYsptr;
2319: e12->Ety = (e12->Ety & (mTYconst | mTYvolatile | mTYimmutable | mTYshared | mTYLINK)) | TYsptr;
2320: }
2321: }
2322: #endif
2323: break;
2324: case OPcomma:
2325: // Replace (*(ea,eb)) with (ea,*eb)
2326: e->E1->ET = e->ET;
2327: type *t = e->ET;
2328: e = el_selecte1(e);
2329: e->Ety = tym;
2330: e->E2 = el_una(OPind,tym,e->E2);
2331: e->E2->ET = t;
2332: again = 1;
2333: return e;
2334: }
2335: return e;
2336: }
2337:
2338: /*****************
2339: * Address of.
2340: * & v => &v
2341: * & * e => e
2342: * & (v1 = v2) => ((v1 = v2), &v1)
2343: */
2344:
2345: STATIC elem * eladdr(elem *e)
2346: { elem *e1;
2347: tym_t tym;
2348:
2349: tym = e->Ety;
2350: e1 = e->E1;
2351: elem_debug(e1);
2352: switch (e1->Eoper)
2353: {
2354: case OPvar:
2355: e1->Eoper = OPrelconst;
2356: e1->EV.sp.Vsym->Sflags &= ~(SFLunambig | GTregcand);
2357: e1->Ety = tym;
2358: e = optelem(el_selecte1(e),TRUE);
2359: break;
2360: case OPind:
2361: { tym_t tym2;
2362: int sz;
2363:
2364: tym2 = e1->E1->Ety;
2365:
2366: #if TX86
2367: /* Watch out for conversions between near and far pointers */
2368: sz = tysize(tym) - tysize(tym2);
2369: if (sz != 0)
2370: { int op;
2371:
2372: if (sz > 0) /* if &far * near */
2373: op = OPptrlptr;
2374: else /* else &near * far */
2375: op = OPoffset;
2376: e->Ety = tym2;
2377: e = el_una(op,tym,e);
2378: goto L1;
2379: }
2380: #endif
2381: e = el_selecte1(el_selecte1(e));
2382: e->Ety = tym;
2383: break;
2384: }
2385: case OPcomma:
2386: /* Replace (&(ea,eb)) with (ea,&eb) */
2387: e = el_selecte1(e);
2388: e->Ety = tym;
2389: e->E2 = el_una(OPaddr,tym,e->E2);
2390: L1:
2391: e = optelem(e,TRUE);
2392: break;
2393: case OPnegass:
2394: assert(0);
2395: default:
2396: if (OTassign(e1->Eoper))
warning C6385: Invalid data: accessing 'unsigned char const * const optab2', the readable size is '183' bytes, but '1145' bytes might be read: Lines: 2346, 2347, 2349, 2350, 2352, 2395, 2396
2397: {
2398: case OPstreq:
2399: // & (v1 = e) => ((v1 = e), &v1)
2400: if (e1->E1->Eoper == OPvar)
2401: { elem *ex;
warning C4101: 'ex' : unreferenced local variable
2402:
2403: e->Eoper = OPcomma;
2404: e->E2 = el_una(OPaddr,tym,el_copytree(e1->E1));
2405: goto L1;
2406: }
2407: // & (*p1 = e) => ((*(t = p1) = e), t)
2408: else if (e1->E1->Eoper == OPind)
2409: { tym_t tym;
warning C6246: Local declaration of 'tym' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '2347' of 'c:\projects\extern\d\dmd\src\backend\cgelem.c': Lines: 2347
2410: elem *tmp;
2411:
2412: tym = e1->E1->E1->Ety;
2413: tmp = el_alloctmp(tym);
2414: e1->E1->E1 = el_bin(OPeq,tym,tmp,e1->E1->E1);
2415: e->Eoper = OPcomma;
2416: e->E2 = el_copytree(tmp);
2417: goto L1;
2418: }
2419: }
2420: break;
2421: case OPcond:
2422: { /* Replace &(x ? y : z) with (x ? &y : &z) */
2423: elem *ecolon;
2424:
2425: ecolon = e1->E2;
2426: ecolon->Ety = tym;
2427: ecolon->E1 = el_una(OPaddr,tym,ecolon->E1);
2428: ecolon->E2 = el_una(OPaddr,tym,ecolon->E2);
2429: e = el_selecte1(e);
2430: e = optelem(e,TRUE);
2431: break;
2432: }
2433: }
2434: return e;
2435: }
2436:
2437: STATIC elem * elneg(elem *e)
2438: {
2439: if (e->E1->Eoper == OPneg)
2440: { e = el_selecte1(e);
2441: e = el_selecte1(e);
2442: }
2443: else
2444: e = evalu8(e);
2445: return e;
2446: }
2447:
2448: STATIC elem * elcall(elem *e)
2449: {
2450: if (e->E1->Eoper == OPcomma || OTassign(e->E1->Eoper))
2451: e = cgel_lvalue(e);
2452: return e;
2453: }
2454:
2455: /***************************
2456: * Walk tree, converting types to tym.
2457: */
2458:
2459: STATIC void elstructwalk(elem *e,tym_t tym)
2460: {
2461: tym_t ety;
2462:
2463: while ((ety = tybasic(e->Ety)) == TYstruct ||
2464: ety == TYarray)
2465: { elem_debug(e);
2466: e->Ety = (e->Ety & ~mTYbasic) | tym;
2467: switch (e->Eoper)
2468: { case OPcomma:
2469: case OPcond:
2470: case OPinfo:
2471: break;
2472: case OPeq:
2473: case OPcolon:
2474: case OPcolon2:
2475: elstructwalk(e->E1,tym);
2476: break;
2477: default:
2478: return;
2479: }
2480: e = e->E2;
2481: }
2482: }
2483:
2484: /*******************************
2485: * See if we can replace struct operations with simpler ones.
2486: * For OPstreq and OPstrpar.
2487: */
2488:
2489: CEXTERN elem * elstruct(elem *e)
2490: { tym_t tym;
2491: elem *e2;
2492: elem **pe2;
2493:
2494: //printf("elstruct(%p)\n", e);
2495: if (e->Eoper == OPstreq && (e->E1->Eoper == OPcomma || OTassign(e->E1->Eoper)))
2496: return cgel_lvalue(e);
2497: //printf("\tnumbytes = %d\n", (int)e->Enumbytes);
2498: if (e->ET)
2499: switch ((int) type_size(e->ET))
2500: {
2501: #if TX86
2502: case CHARSIZE: tym = TYchar; goto L1;
2503: case SHORTSIZE: tym = TYshort; goto L1;
2504: case LONGSIZE: tym = TYlong; goto L1;
2505: #if LONGLONG
2506: case LLONGSIZE: if (intsize == 2)
2507: goto Ldefault;
2508: tym = TYllong; goto L1;
2509: #endif
2510: L1:
2511: switch (e->Eoper)
2512: { case OPstreq:
2513: e->Eoper = OPeq;
2514: e->Ety = (e->Ety & ~mTYbasic) | tym;
2515: elstructwalk(e->E1,tym);
2516: elstructwalk(e->E2,tym);
2517: e = optelem(e,TRUE);
2518: break;
2519: case OPstrpar:
2520: e = el_selecte1(e);
2521: /* FALL-THROUGH */
2522: default: /* called by doptelem() */
2523: e2 = e;
2524: elstructwalk(e2,tym);
2525: break;
2526: }
2527: break;
2528: #endif
2529: case 0:
2530: if (e->Eoper == OPstreq)
2531: { e->Eoper = OPcomma;
2532: e = optelem(e,TRUE);
2533: again = 1;
2534: }
2535: else
2536: goto Ldefault;
2537: break;
2538:
2539: default:
2540: Ldefault:
2541: if (e->Eoper == OPstreq)
2542: pe2 = &e->E2;
2543: else if (e->Eoper == OPstrpar)
2544: pe2 = &e->E1;
2545: else
2546: break;
2547: while ((*pe2)->Eoper == OPcomma)
2548: pe2 = &(*pe2)->E2;
2549: e2 = *pe2;
2550:
2551: // Convert (x streq (a?y:z)) to (x streq *(a ? &y : &z))
2552: if (e2->Eoper == OPcond)
2553: { tym_t ty2 = e2->Ety;
2554: tym_t typ;
2555:
2556: /* We should do the analysis to see if we can use
2557: something simpler than TYfptr.
2558: */
2559: typ = (intsize == LONGSIZE) ? TYnptr : TYfptr;
2560: e2 = el_una(OPaddr,typ,e2);
2561: e2 = optelem(e2,TRUE); /* distribute & to x and y leaves */
2562: *pe2 = el_una(OPind,ty2,e2);
2563: break;
2564: }
2565: break;
2566: }
2567: return e;
2568: }
2569:
2570: /**************************
2571: * Assignment. Replace bit field assignment with
2572: * equivalent tree.
2573: * =
2574: * / \
2575: * / r
2576: * bit
2577: * / \
2578: * l w,b
2579: *
2580: * becomes:
2581: * ,
2582: * / \
2583: * = (r&m)
2584: * / \
2585: * l |
2586: * / \
2587: * (r&m)<<b &
2588: * / \
2589: * l ~(m<<b)
2590: * Note:
2591: * This depends on the expression (r&m)<<b before l. This is because
2592: * of expressions like (l.a = l.b = n). It is an artifact of the way
2593: * we do things that this works (cost() will rate the << as more
2594: * expensive than the &, and so it will wind up on the left).
2595: */
2596:
2597: STATIC elem * eleq(elem *e)
2598: { targ_ullong m;
warning C4101: 'm' : unreferenced local variable
2599: unsigned t,w,b;
warning C4101: 'w' : unreferenced local variable
warning C4101: 'b' : unreferenced local variable
warning C4101: 't' : unreferenced local variable
2600: unsigned sz;
warning C4101: 'sz' : unreferenced local variable
2601: elem *l,*l2,*r,*r2,*e1,*eres;
warning C4101: 'eres' : unreferenced local variable
warning C4101: 'r2' : unreferenced local variable
warning C4101: 'l' : unreferenced local variable
warning C4101: 'r' : unreferenced local variable
warning C4101: 'l2' : unreferenced local variable
2602: tym_t tyl;
warning C4101: 'tyl' : unreferenced local variable
2603:
2604: #if SCPP
2605: int wantres = expgoal;
2606: #endif
2607: e1 = e->E1;
2608:
2609: if (e1->Eoper == OPcomma || OTassign(e1->Eoper))
2610: return cgel_lvalue(e);
2611:
2612: #if 0 // Doesn't work too well, removed
2613: // Replace (*p++ = e2) with ((*p = e2),*p++)
2614: if (OPTIMIZER && e1->Eoper == OPind &&
2615: (e1->E1->Eoper == OPpostinc || e1->E1->Eoper == OPpostdec) &&
2616: !el_sideeffect(e1->E1->E1)
2617: )
2618: {
2619: e = el_bin(OPcomma,e->Ety,e,e1);
2620: e->E1->E1 = el_una(OPind,e1->Ety,el_copytree(e1->E1->E1));
2621: return optelem(e,TRUE);
2622: }
2623: #endif
2624:
2625: #if 0 && LNGDBLSIZE == 12
2626: /* On Linux, long doubles are 12 bytes rather than 10.
2627: * This means, on assignment, we need to set 12 bytes,
2628: * so that garbage doesn't creep into the extra 2 bytes
2629: * and throw off compares.
2630: */
2631: tyl = tybasic(e1->Ety);
2632: if (e1->Eoper == OPvar && (tyl == TYldouble || tyl == TYildouble || tyl == TYcldouble))
2633: {
2634: #if 1
2635: elem *ex = el_copytree(e1);
2636: ex->EV.sp.Voffset += 10;
2637: ex = el_bin(OPeq, TYshort, ex, el_long(TYshort, 0));
2638: e = el_combine(ex, e);
2639: if (tyl == TYcldouble)
2640: {
2641: ex = el_copytree(e1);
2642: ex->EV.sp.Voffset += 10 + 12;
2643: ex = el_bin(OPeq, TYshort, ex, el_long(TYshort, 0));
2644: e = el_combine(ex, e);
2645: }
2646: return optelem(e, TRUE);
2647: #else
2648: e->Eoper = OPstreq;
2649: e->Enumbytes = tysize(tyl);
2650: return elstruct(e);
2651: #endif
2652: }
2653: #endif
2654:
2655: if (OPTIMIZER)
2656: { elem *e2 = e->E2;
2657: elem *ei;
2658: int op2 = e2->Eoper;
2659:
2660: // Replace (e1 = *p++) with (e1 = *p, p++, e1)
2661: ei = e2;
2662: if (e1->Eoper == OPvar &&
2663: (op2 == OPind || (OTunary(op2) && (ei = e2->E1)->Eoper == OPind)) &&
2664: (ei->E1->Eoper == OPpostinc || ei->E1->Eoper == OPpostdec) &&
2665: !el_sideeffect(e1) &&
2666: !el_sideeffect(ei->E1->E1)
2667: )
2668: {
2669: e = el_bin(OPcomma,e->Ety,
2670: e,
2671: el_bin(OPcomma,e->Ety,ei->E1,el_copytree(e1)));
2672: ei->E1 = el_copytree(ei->E1->E1); // copy p
2673: return optelem(e,TRUE);
2674: }
2675:
2676: /* Replace (e = e) with (e,e) */
2677: if (el_match(e1,e2))
2678: { e->Eoper = OPcomma;
2679: L1:
2680: return optelem(e,TRUE);
2681: }
2682:
2683: // Replace (e1 = (e21 , e22)) with (e21 , (e1 = e22))
2684: if (op2 == OPcomma)
2685: {
2686: e2->Ety = e->Ety;
2687: e->E2 = e2->E2;
2688: e2->E2 = e;
2689: e = e2;
2690: goto L1;
2691: }
2692:
2693: if (OTop(op2) && !el_sideeffect(e1)
2694: && op2 != OPdiv && op2 != OPmod
2695: )
2696: { tym_t ty;
2697: int op3;
warning C4101: 'op3' : unreferenced local variable
2698:
2699: // Replace (e1 = e1 op e) with (e1 op= e)
2700: if (el_match(e1,e2->E1))
2701: { ty = e2->E2->Ety;
2702: e->E2 = el_selecte2(e2);
2703: L2:
2704: e->E2->Ety = ty;
2705: e->Eoper = optoopeq(op2);
2706: goto L1;
2707: }
2708: if (OTcommut(op2))
2709: {
2710: /* Replace (e1 = e op e1) with (e1 op= e) */
2711: if (el_match(e1,e2->E2))
2712: { ty = e2->E1->Ety;
2713: e->E2 = el_selecte1(e2);
2714: goto L2;
2715: }
2716: }
2717:
2718: #if 0
2719: // Note that this optimization is undone in elcomma(), this results in an
2720: // infinite loop. This optimization is preferable if e1 winds up a register
2721: // variable, the inverse in elcomma() is preferable if e1 winds up in memory.
2722: // Replace (e1 = (e1 op3 ea) op2 eb) with (e1 op3= ea),(e1 op2= eb)
2723: op3 = e2->E1->Eoper;
2724: if (OTop(op3) && el_match(e1,e2->E1->E1) && !el_depends(e1,e2->E2))
2725: {
2726: e->Eoper = OPcomma;
2727: e->E1 = e2->E1;
2728: e->E1->Eoper = optoopeq(op3);
2729: e2->E1 = e1;
2730: e1->Ety = e->E1->Ety;
2731: e2->Eoper = optoopeq(op2);
2732: e2->Ety = e->Ety;
2733: goto L1;
2734: }
2735: #endif
2736: }
2737:
2738: if (op2 == OPneg && el_match(e1,e2->E1) && !el_sideeffect(e1))
2739: { int offset;
warning C4101: 'offset' : unreferenced local variable
2740:
2741: Ldef:
warning C4102: 'Ldef' : unreferenced label
2742: // Replace (i = -i) with (negass i)
2743: e->Eoper = OPnegass;
2744: e->E2 = NULL;
2745: el_free(e2);
2746: return optelem(e, TRUE);
2747: }
2748:
2749: // Replace (x = (y ? z : x)) with ((y && (x = z)),x)
2750: if (op2 == OPcond && el_match(e1,e2->E2->E2))
2751: { elem *e22 = e2->E2; // e22 is the OPcond
2752:
2753: e->Eoper = OPcomma;
2754: e->E2 = e1;
2755: e->E1 = e2;
2756: e2->Eoper = OPandand;
2757: e2->Ety = TYint;
2758: e22->Eoper = OPeq;
2759: e22->Ety = e->Ety;
2760: e1 = e22->E1;
2761: e22->E1 = e22->E2;
2762: e22->E2 = e1;
2763: return optelem(e,TRUE);
2764: }
2765:
2766: // Replace (x = (y ? x : z)) with ((y || (x = z)),x)
2767: if (op2 == OPcond && el_match(e1,e2->E2->E1))
2768: { elem *e22 = e2->E2; // e22 is the OPcond
2769:
2770: e->Eoper = OPcomma;
2771: e->E2 = e1;
2772: e->E1 = e2;
2773: e2->Eoper = OPoror;
2774: e2->Ety = TYint;
2775: e22->Eoper = OPeq;
2776: e22->Ety = e->Ety;
2777: return optelem(e,TRUE);
2778: }
2779:
2780: // If floating point, replace (x = -y) with (x = y ^ signbit)
2781: if (op2 == OPneg && (tyreal(e2->Ety) || tyimaginary(e2->Ety)) &&
2782: (e2->E1->Eoper == OPvar || e2->E1->Eoper == OPind))
2783: { elem *es;
2784: tym_t ty;
2785:
2786: es = el_calloc();
2787: es->Eoper = OPconst;
2788: switch (tysize(e2->Ety))
2789: {
2790: case FLOATSIZE:
2791: ty = TYlong;
2792: es->EV.Vlong = 0x80000000;
2793: break;
2794: case DOUBLESIZE:
2795: #if LONGLONG
2796: if (I32)
2797: { ty = TYllong;
2798: es->EV.Vllong = 0x8000000000000000LL;
2799: break;
2800: }
2801: #endif
2802: default:
2803: el_free(es);
2804: goto L8;
2805: }
2806: es->Ety = ty;
2807: e1->Ety = ty;
2808: e2->Ety = ty;
2809: e2->E1->Ety = ty;
2810: e2->E2 = es;
2811: e2->Eoper = OPxor;
2812: return optelem(e,TRUE);
2813: }
2814: L8: ;
2815: }
2816:
2817: if (e1->Eoper == OPcomma)
2818: return cgel_lvalue(e);
2819: #if MARS
2820: // No bit fields to deal with
2821: return e;
2822: #else
2823: if (e1->Eoper != OPbit)
2824: return e;
2825: if (e1->E1->Eoper == OPcomma || OTassign(e1->E1->Eoper))
2826: return cgel_lvalue(e);
2827: t = e->Ety;
2828: l = e1->E1; /* lvalue */
2829: r = e->E2;
2830: tyl = l->Ety;
2831: sz = tysize(tyl) * 8;
2832: w = (e1->E2->EV.Vuns >> 8); /* width in bits of field */
2833: m = ((targ_ullong)1 << w) - 1; // mask w bits wide
2834: b = e1->E2->EV.Vuns & 0xFF; /* bits to shift */
2835:
2836: eres = el_bin(OPeq,t,
2837: l,
2838: el_bin(OPor,t,
2839: el_bin(OPshl,t,
2840: (r2 = el_bin(OPand,t,r,el_long(t,m))),
2841: el_int(TYint,b)
2842: ),
2843: el_bin(OPand,t,
2844: (l2 = el_copytree(l)),
2845: el_long(t,~(m << b))
2846: )
2847: )
2848: );
2849: eres->Esrcpos = e->Esrcpos; // save line information
2850: if (OPTIMIZER && w + b == sz)
2851: r2->E2->EV.Vllong = ~ZEROLL; // no need to mask if left justified
2852: if (wantres)
2853: { unsigned c;
2854: elem **pe;
2855: elem *e2;
2856:
2857: r = el_copytree(r);
2858: if (tyuns(tyl)) /* unsigned bit field */
2859: {
2860: e2 = el_bin(OPand,t,r,el_long(t,m));
2861: pe = &e2->E1;
2862: }
2863: else /* signed bit field */
2864: {
2865: c = sz - w; /* e2 = (r << c) >> c */
2866: e2 = el_bin(OPshr,t,el_bin(OPshl,tyl,r,el_long(TYint,c)),el_long(TYint,c));
2867: pe = &e2->E1->E1;
2868: }
2869: eres = el_bin(OPcomma,t,eres,e2);
2870: if (EOP(r))
2871: fixside(&(r2->E1),pe);
2872: }
2873:
2874: if (EOP(l) && EOP(l->E1))
2875: fixside(&(l2->E1),&(l->E1));
2876: e1->E1 = e->E2 = NULL;
2877: el_free(e);
2878: return optelem(eres,TRUE);
2879: #endif
2880: }
2881:
2882: /**********************************
2883: */
2884:
2885: STATIC elem * elnegass(elem *e)
2886: {
2887: e = cgel_lvalue(e);
2888: return e;
2889: }
2890:
2891: /**************************
2892: * Add assignment. Replace bit field assignment with
2893: * equivalent tree.
2894: * +=
2895: * / \
2896: * / r
2897: * bit
2898: * / \
2899: * l w,b
2900: *
2901: * becomes:
2902: * =
2903: * / \
2904: * l |
2905: * / \
2906: * << \
2907: * / \ \
2908: * & b &
2909: * / \ / \
2910: * op m l ~(m<<b)
2911: * / \
2912: * & r
2913: * / \
2914: * >> m
2915: * / \
2916: * l b
2917: */
2918:
2919: STATIC elem * elopass(elem *e)
2920: { targ_llong m;
warning C4101: 'm' : unreferenced local variable
2921: unsigned w,b,op;
warning C4101: 'w' : unreferenced local variable
warning C4101: 'b' : unreferenced local variable
warning C4101: 'op' : unreferenced local variable
2922: tym_t t;
warning C4101: 't' : unreferenced local variable
2923: tym_t tyl;
warning C4101: 'tyl' : unreferenced local variable
2924: elem *l,*r,*e1,*l2,*l3,*op2,*eres;
warning C4101: 'l3' : unreferenced local variable
warning C4101: 'eres' : unreferenced local variable
warning C4101: 'op2' : unreferenced local variable
warning C4101: 'l' : unreferenced local variable
warning C4101: 'r' : unreferenced local variable
warning C4101: 'l2' : unreferenced local variable
2925:
2926: e1 = e->E1;
2927: if (OTconv(e1->Eoper))
2928: { e = fixconvop(e);
2929: return optelem(e,TRUE);
2930: }
2931: #if SCPP // have bit fields to worry about?
2932: int wantres = expgoal;
2933: if (e1->Eoper == OPbit)
2934: {
2935: op = opeqtoop(e->Eoper);
2936:
2937: // Make sure t is unsigned
2938: // so >> doesn't have to be masked
2939: t = touns(e->Ety);
2940:
2941: assert(tyintegral(t));
2942: l = e1->E1; // lvalue
2943: tyl = l->Ety;
2944: r = e->E2;
2945: w = (e1->E2->EV.Vuns >> 8) & 0xFF; // width in bits of field
2946: m = ((targ_llong)1 << w) - 1; // mask w bits wide
2947: b = e1->E2->EV.Vuns & 0xFF; // bits to shift
2948:
2949: if (tyuns(tyl))
2950: {
2951: eres = el_bin(OPeq,t,
2952: l,
2953: el_bin(OPor,t,
2954: (op2=el_bin(OPshl,t,
2955: el_bin(OPand,t,
2956: el_bin(op,t,
2957: el_bin(OPand,t,
2958: el_bin(OPshr,t,
2959: (l2=el_copytree(l)),
2960: el_long(TYint,b)
2961: ),
2962: el_long(t,m)
2963: ),
2964: r
2965: ),
2966: el_long(t,m)
2967: ),
2968: el_long(TYint,b)
2969: )),
2970: el_bin(OPand,t,
2971: l3=el_copytree(l),
2972: el_long(t,~(m << b))
2973: )
2974: )
2975: );
2976:
2977: if (wantres)
2978: { eres = el_bin(OPcomma,t,eres,el_copytree(op2->E1));
2979: fixside(&(op2->E1),&(eres->E2));
2980: }
2981: }
2982: else
2983: { /* signed bit field
2984: rewrite to: (l bit w,b) = ((l bit w,b) op r)
2985: */
2986: e->Eoper = OPeq;
2987: e->E2 = el_bin(op,t,el_copytree(e1),r);
2988: if (l->Eoper == OPind)
2989: fixside(&e->E2->E1->E1->E1,&l->E1);
2990: eres = e;
2991: goto ret;
2992: }
2993:
2994: if (EOP(l) && EOP(l->E1))
2995: { fixside(&(l2->E1),&(l->E1));
2996: el_free(l3->E1);
2997: l3->E1 = el_copytree(l->E1);
2998: }
2999:
3000: e1->E1 = e->E2 = NULL;
3001: el_free(e);
3002: ret:
3003: e = optelem(eres,TRUE);
3004: }
3005: else
3006: #endif
3007: {
3008: if (e1->Eoper == OPcomma || OTassign(e1->Eoper))
3009: e = cgel_lvalue(e); // replace (e,v)op=e2 with e,(v op= e2)
3010: else
3011: {
3012: switch (e->Eoper)
3013: { case OPmulass:
3014: e = elmul(e);
3015: break;
3016: case OPdivass:
3017: // Replace r/=c with r=r/c
3018: if (tycomplex(e->E2->Ety) && !tycomplex(e1->Ety))
3019: { elem *ed;
3020:
3021: e->Eoper = OPeq;
3022: if (e1->Eoper == OPind)
3023: { // ed: *(tmp=e1->E1)
3024: // e1: *tmp
3025: elem *tmp;
3026:
3027: tmp = el_alloctmp(e1->E1->Ety);
3028: ed = el_bin(OPeq, tmp->Ety, tmp, e1->E1);
3029: e1->E1 = el_copytree(tmp);
3030: ed = el_una(OPind, e1->Ety, ed);
3031: }
3032: else
3033: ed = el_copytree(e1);
3034: // e: e1=ed/e2
3035: e->E2 = el_bin(OPdiv, e->E2->Ety, ed, e->E2);
3036: if (tyreal(e1->Ety))
3037: e->E2 = el_una(OPc_r, e1->Ety, e->E2);
3038: else
3039: e->E2 = el_una(OPc_i, e1->Ety, e->E2);
3040: return optelem(e, TRUE);
3041: }
3042: // Repace x/=y with x=x/y
3043: if (OPTIMIZER &&
3044: tyintegral(e->E1->Ety) &&
3045: e->E1->Eoper == OPvar &&
3046: !el_sideeffect(e->E1))
3047: {
3048: e->Eoper = OPeq;
3049: e->E2 = el_bin(OPdiv, e->E2->Ety, el_copytree(e->E1), e->E2);
3050: return optelem(e, TRUE);
3051: }
3052: e = eldiv(e);
3053: break;
3054:
3055: case OPmodass:
3056: // Repace x%=y with x=x%y
3057: if (OPTIMIZER &&
3058: tyintegral(e->E1->Ety) &&
3059: e->E1->Eoper == OPvar &&
3060: !el_sideeffect(e->E1))
3061: {
3062: e->Eoper = OPeq;
3063: e->E2 = el_bin(OPmod, e->E2->Ety, el_copytree(e->E1), e->E2);
3064: return optelem(e, TRUE);
3065: }
3066: break;
3067: }
3068: }
3069: }
3070: return e;
3071: }
3072:
3073: /**************************
3074: * Add assignment. Replace bit field post assignment with
3075: * equivalent tree.
3076: * (l bit w,b) ++ r
3077: * becomes:
3078: * (((l bit w,b) += r) - r) & m
3079: */
3080:
3081: STATIC elem * elpost(elem *e)
3082: { targ_llong r;
3083: tym_t ty;
3084: elem *e1;
3085: targ_llong m;
3086: unsigned w,b;
warning C4101: 'b' : unreferenced local variable
3087:
3088: e1 = e->E1;
3089: if (e1->Eoper != OPbit)
3090: { if (e1->Eoper == OPcomma || OTassign(e1->Eoper))
3091: return cgel_lvalue(e); // replace (e,v)op=e2 with e,(v op= e2)
3092: return e;
3093: }
3094:
3095: assert(e->E2->Eoper == OPconst);
3096: r = el_tolong(e->E2);
3097:
3098: w = (e1->E2->EV.Vuns >> 8) & 0xFF; /* width in bits of field */
3099: m = ((targ_llong)1 << w) - 1; /* mask w bits wide */
3100:
3101: ty = e->Ety;
3102: e->Eoper = (e->Eoper == OPpostinc) ? OPaddass : ((r = -r), OPminass);
3103: e = el_bin(OPmin,ty,e,el_long(ty,r));
3104: if (tyuns(e1->E1->Ety)) /* if unsigned bit field */
3105: e = el_bin(OPand,ty,e,el_long(ty,m));
3106: return optelem(e,TRUE);
3107: }
3108:
3109: /***************************
3110: * Take care of compares.
3111: * (e == 0) => (!e)
3112: * (e != 0) => (bool e)
3113: */
3114:
3115: STATIC elem * elcmp(elem *e)
3116: { elem *e2 = e->E2;
3117: elem *e1 = e->E1;
3118: int uns;
3119:
3120: //printf("elcmp(%p)\n",e); elem_print(e);
3121:
3122: L1:
warning C4102: 'L1' : unreferenced label
3123: if (OPTIMIZER)
3124: {
3125: int op = e->Eoper;
3126:
3127: /* Convert comparison of OPrelconsts of the same symbol to comparisons */
3128: /* of their offsets. */
3129: if (e1->Eoper == OPrelconst && e2->Eoper == OPrelconst &&
3130: e1->EV.sp.Vsym == e2->EV.sp.Vsym)
3131: {
3132: e1->Eoper = OPconst;
3133: e1->Ety = TYptrdiff;
3134: e2->Eoper = OPconst;
3135: e2->Ety = TYptrdiff;
3136: return optelem(e,TRUE);
3137: }
3138:
3139: // Convert comparison of long pointers to comparison of integers
3140: if ((op == OPlt || op == OPle || op == OPgt || op == OPge) &&
3141: tyfv(e2->Ety) && tyfv(e1->Ety))
3142: {
3143: e->E1 = el_una(OPlngsht,e->Ety,e1);
3144: e->E2 = el_una(OPlngsht,e->Ety,e2);
3145: return optelem(e,TRUE);
3146: }
3147:
3148: // Convert ((e & 1) == 1) => (e & 1)
3149: if (op == OPeqeq && e2->Eoper == OPconst && e1->Eoper == OPand)
3150: { elem *e12 = e1->E2;
3151:
3152: if (e12->Eoper == OPconst && el_tolong(e2) == 1 && el_tolong(e12) == 1)
3153: { tym_t ty1;
3154: tym_t ty;
3155: int sz1;
3156: int sz;
3157:
3158: ty = e->Ety;
3159: ty1 = e1->Ety;
3160: e = el_selecte1(e);
3161: e->Ety = ty1;
3162: sz = tysize(ty);
3163: for (sz1 = tysize(ty1); sz1 != sz; sz1 = tysize(e->Ety))
3164: {
3165: switch (sz1)
3166: {
3167: case 1:
3168: e = el_una(OPu8_16,TYshort,e);
3169: break;
3170: case 2:
3171: if (sz > 2)
3172: e = el_una(OPu16_32,TYlong,e);
3173: else
3174: e = el_una(OP16_8,TYuchar,e);
3175: break;
3176: case 4:
3177: if (sz > 2)
3178: e = el_una(OPu32_64,TYshort,e);
3179: else
3180: e = el_una(OP32_16,TYshort,e);
3181: break;
3182: case 8:
3183: e = el_una(OP64_32,TYlong,e);
3184: break;
3185: default:
3186: assert(0);
3187: }
3188: }
3189: e->Ety = ty;
3190: return optelem(e,TRUE);
3191: }
3192: }
3193: }
3194:
3195: uns = tyuns(e1->Ety) | tyuns(e2->Ety);
3196: if (cnst(e2))
3197: {
3198: tym_t tym;
3199: int sz;
3200:
3201: if (e1->Eoper == OPu16_32 && e2->EV.Vulong <= (targ_ulong) SHORTMASK ||
3202: e1->Eoper == OPshtlng &&
3203: e2->EV.Vlong == (targ_short) e2->EV.Vlong)
3204: {
3205: tym = (uns || e1->Eoper == OPu16_32) ? TYushort : TYshort;
3206: e->E2 = el_una(OPlngsht,tym,e2);
3207: goto L2;
3208: }
3209:
3210: /* Try to convert to byte/word comparison for ((x & c)==d)
3211: when mask c essentially casts x to a smaller type
3212: */
3213: if (OPTIMIZER &&
3214: e1->Eoper == OPand &&
3215: e1->E2->Eoper == OPconst &&
3216: (sz = tysize(e2->Ety)) > CHARSIZE)
3217: { int op;
3218:
3219: assert(tyintegral(e2->Ety) || typtr(e2->Ety));
3220: #if TX86 /* ending up with byte ops in A regs */
3221: if (!(el_tolong(e2) & ~CHARMASK) &&
3222: !(el_tolong(e1->E2) & ~CHARMASK)
3223: )
3224: {
3225: if (sz == LLONGSIZE)
3226: { e1->E1 = el_una(OP64_32,TYulong,e1->E1);
3227: e1->E1 = el_una(OP32_16,TYushort,e1->E1);
3228: }
3229: else if (sz == LONGSIZE)
3230: e1->E1 = el_una(OP32_16,TYushort,e1->E1);
3231: tym = TYuchar;
3232: op = OPint8;
3233: goto L4;
3234: }
3235: #endif
3236: if (
3237: #if TX86
3238: intsize == SHORTSIZE && /* not a win when regs are long */
3239: #endif
3240: sz == LONGSIZE &&
3241: !(e2->EV.Vulong & ~SHORTMASK) &&
3242: !(e1->E2->EV.Vulong & ~SHORTMASK)
3243: )
3244: {
3245: tym = TYushort;
3246: op = OPlngsht;
3247: L4:
3248: e2->Ety = tym;
3249: e1->Ety = tym;
3250: e1->E2->Ety = tym;
3251: e1->E1 = el_una(op,tym,e1->E1);
3252: e = optelem(e,TRUE);
3253: goto ret;
3254: }
3255: }
3256:
3257: if (e1->Eoper == OPu8int && e2->EV.Vuns < 256 ||
3258: e1->Eoper == OPs8int &&
3259: e2->EV.Vint == (targ_schar) e2->EV.Vint)
3260: {
3261: tym = (uns || e1->Eoper == OPu8int) ? TYuchar : TYschar;
3262: e->E2 = el_una(OPint8,tym,e2);
3263: L2:
3264: tym |= e1->Ety & ~mTYbasic;
3265: e->E1 = el_selecte1(e1);
3266: e->E1->Ety = tym;
3267: e = optelem(e,TRUE);
3268: }
3269: else if (!boolres(e2))
3270: {
3271: switch (e->Eoper)
3272: {
3273: targ_int i;
3274:
3275: case OPle: /* (u <= 0) becomes (u == 0) */
3276: if (!uns)
3277: break;
3278: /* FALL-THROUGH */
3279: case OPeqeq:
3280: e->Eoper = OPnot;
3281: goto L5;
3282: case OPgt: /* (u > 0) becomes (u != 0) */
3283: if (!uns)
3284: break;
3285: /* FALL-THROUGH */
3286: case OPne:
3287: e->Eoper = OPbool;
3288: L5: el_free(e2);
3289: e->E2 = NULL;
3290: e = optelem(e,TRUE);
3291: break;
3292:
3293: case OPge:
3294: i = 1; /* (u >= 0) becomes (u,1) */
3295: goto L3;
3296: case OPlt: /* (u < 0) becomes (u,0) */
3297: i = 0;
3298: L3:
3299: if (uns)
3300: {
3301: e2->EV.Vint = i;
3302: e2->Ety = TYint;
3303: e->Eoper = OPcomma;
3304: e = optelem(e,TRUE);
3305: }
3306: break;
3307: }
3308: }
3309: else if (OPTIMIZER && uns && tysize(e2->Ety) == 2 &&
3310: (unsigned short)e2->EV.Vuns == 0x8000 &&
3311: (e->Eoper == OPlt || e->Eoper == OPge)
3312: )
3313: { // Convert to signed comparison against 0
3314: tym_t ty;
3315:
3316: ty = tybasic(e2->Ety);
3317: switch (tysize[ty])
3318: { case 1: ty = TYschar; break;
3319: case 2: ty = TYshort; break;
3320: default: assert(0);
3321: }
3322: e->Eoper ^= (OPlt ^ OPge); // switch between them
3323: e2->EV.Vuns = 0;
3324: e2->Ety = ty | (e2->Ety & ~mTYbasic);
3325: e1->Ety = ty | (e1->Ety & ~mTYbasic);
3326: }
3327: else if (OPTIMIZER && e1->Eoper == OPeq &&
3328: e1->E2->Eoper == OPconst)
3329: { // Convert ((x = c1) rel c2) to ((x = c1),(c1 rel c2)
3330: elem *ec;
3331:
3332: ec = el_copytree(e1->E2);
3333: ec->Ety = e1->Ety;
3334: e->E1 = ec;
3335: e = el_bin(OPcomma,e->Ety,e1,e);
3336: e = optelem(e,TRUE);
3337: }
3338: }
3339: else if ((
3340: (e1->Eoper == OPu8int || e1->Eoper == OPs8int)
3341: || (e1->Eoper == OPu16_32 || e1->Eoper == OPshtlng)
3342: ) && e1->Eoper == e2->Eoper)
3343: { if (uns)
3344: { e1->E1->Ety = touns(e1->E1->Ety);
3345: e2->E1->Ety = touns(e2->E1->Ety);
3346: }
3347: e1->Ety = e1->E1->Ety;
3348: e2->Ety = e2->E1->Ety;
3349: e->E1 = el_selecte1(e1);
3350: e->E2 = el_selecte1(e2);
3351: e = optelem(e,TRUE);
3352: }
3353: ret:
3354: return e;
3355: }
3356:
3357: /*****************************
3358: * Boolean operator.
3359: * bool c => (bool c)
3360: * bool logical_operator e => logical_operator e
3361: */
3362:
3363: STATIC elem * elbool(elem *e)
3364: {
3365: if (OTlogical(e->E1->Eoper) ||
3366: (tybasic(e->E1->Ety) == TYbool && tysize(e->Ety) == 1)
3367: )
3368: return el_selecte1(e);
3369: if (OPTIMIZER)
3370: { elem *e1;
3371:
3372: /* Replace bool(x,1) with (x,1),1 */
3373: e1 = elscancommas(e->E1);
3374: if (cnst(e1) || e1->Eoper == OPrelconst)
3375: { int i;
3376:
3377: i = boolres(e1) != 0;
3378: e->Eoper = OPcomma;
3379: e->E2 = el_int(e->Ety,i);
3380: e = optelem(e,TRUE);
3381: }
3382: }
3383: return e;
3384: }
3385:
3386:
3387: /*********************************
3388: * Conversions of pointers to far pointers.
3389: */
3390:
3391: STATIC elem * elptrlptr(elem *e)
3392: {
3393: if (e->E1->Eoper == OPrelconst || e->E1->Eoper == OPstring)
3394: {
3395: e->E1->Ety = e->Ety;
3396: e = el_selecte1(e);
3397: }
3398: return e;
3399: }
3400:
3401: /*********************************
3402: * Conversions of handle pointers to far pointers.
3403: */
3404:
3405: STATIC elem * elvptrfptr(elem *e)
3406: { elem *e1;
3407: elem *e12;
3408: int op;
3409:
3410: e1 = e->E1;
3411: if (e1->Eoper == OPadd || e1->Eoper == OPmin)
3412: {
3413: e12 = e1->E2;
3414: if (tybasic(e12->Ety) != TYvptr)
3415: {
3416: /* Rewrite (vtof(e11 + e12)) to (vtof(e11) + e12) */
3417: op = e->Eoper;
3418: e->Eoper = e1->Eoper;
3419: e->E2 = e12;
3420: e1->Ety = e->Ety;
3421: e1->Eoper = op;
3422: e1->E2 = NULL;
3423: e = optelem(e,TRUE);
3424: }
3425: }
3426: return e;
3427: }
3428:
3429: /************************
3430: * Optimize conversions of longs to ints.
3431: * Also used for (OPoffset) (TYfptr|TYvptr).
3432: * Also used for conversions of ints to bytes.
3433: */
3434:
3435: STATIC elem * ellngsht(elem *e)
3436: { elem *e1;
3437: tym_t ty;
3438:
3439: ty = e->Ety;
3440: e1 = e->E1;
3441: switch (e1->Eoper)
3442: { case OPshtlng:
3443: case OPu16_32:
3444: case OPu8int:
3445: case OPs8int:
3446: /* This fix is not quite right. For example, it fails */
3447: /* if e->Ety != e->E1->E1->Ety. The difference is when */
3448: /* one is unsigned and the other isn't. */
3449: if (tysize(ty) != tysize(e->E1->E1->Ety))
3450: break;
3451: e = el_selecte1(el_selecte1(e));
3452: e->Ety = ty;
3453: return e;
3454: case OPvar: /* simply paint type of variable */
3455: /* Do not paint type of ints into bytes, as this causes */
3456: /* many CSEs to be missed, resulting in bad code. */
3457: /* Loading a word anyway is just as fast as loading a byte. */
3458: /* for 68000 byte is swapped, load byte != load word */
3459: if (e->Eoper == OPint8)
3460: {
3461: /* Mark symbol as being used sometimes as a byte to */
3462: /* 80X86 - preclude using SI or DI */
3463: /* 68000 - preclude using An */
3464: e1->EV.sp.Vsym->Sflags |= GTbyte;
3465: }
3466: else
3467: e1->Ety = ty;
3468: e = el_selecte1(e);
3469: break;
3470: case OPind:
3471: e = el_selecte1(e);
3472: break;
3473:
3474: case OPptrlptr:
3475: if (e->Eoper != OPoffset)
3476: goto case_default;
3477: // Replace (offset)(ptrlptr)e11 with e11
3478: e = el_selecte1(el_selecte1(e));
3479: e->Ety = ty; // retain original type
3480: break;
3481:
3482: default: /* operator */
3483: case_default:
3484: /* Attempt to replace (lngsht)(a op b) with */
3485: /* ((lngsht)a op (lngsht)b). */
3486: /* op is now an integer op, which is cheaper. */
3487: if (OTwid(e1->Eoper) && !OTassign(e1->Eoper))
warning C6385: Invalid data: accessing 'unsigned char const * const optab2', the readable size is '183' bytes, but '1112' bytes might be read: Lines: 3436, 3437, 3439, 3440, 3441, 3482, 3483, 3487
3488: { tym_t ty1;
3489:
3490: ty1 = e1->E1->Ety;
3491: switch (e->Eoper)
3492: { case OPint8:
3493: /* Make sure e1->E1 is of the type we're converting from */
3494: if (tysize(ty1) <= intsize)
3495: {
3496: ty1 = (tyuns(ty1) ? TYuchar : TYschar) |
3497: (ty1 & ~mTYbasic);
3498: e1->E1 = el_una(e->Eoper,ty1,e1->E1);
3499: }
3500: /* Rvalue may be an int if it is a shift operator */
3501: if (OTbinary(e1->Eoper))
warning C6385: Invalid data: accessing 'unsigned char const * const optab1', the readable size is '183' bytes, but '1112' bytes might be read: Lines: 3436, 3437, 3439, 3440, 3441, 3482, 3483, 3487, 3488, 3490, 3491, 3492, 3494, 3501
3502: { tym_t ty2 = e1->E2->Ety;
3503:
3504: if (tysize(ty2) <= intsize)
3505: {
3506: ty2 = (tyuns(ty2) ? TYuchar : TYschar) |
3507: (ty2 & ~mTYbasic);
3508: e1->E2 = el_una(e->Eoper,ty2,e1->E2);
3509: }
3510: }
3511: break;
3512: #if TX86
3513: case OPoffset:
3514: if (intsize == LONGSIZE)
3515: {
3516: /* Make sure e1->E1 is of the type we're converting from */
3517: if (tysize(ty1) > LONGSIZE)
3518: {
3519: ty1 = (tyuns(ty1) ? TYuint : TYint) | (ty1 & ~mTYbasic);
3520: e1->E1 = el_una(e->Eoper,ty1,e1->E1);
3521: }
3522: /* Rvalue may be an int if it is a shift operator */
3523: if (OTbinary(e1->Eoper))
3524: { tym_t ty2 = e1->E2->Ety;
3525:
3526: if (tysize(ty2) > LONGSIZE)
3527: {
3528: ty2 = (tyuns(ty2) ? TYuint : TYint) |
3529: (ty2 & ~mTYbasic);
3530: e1->E2 = el_una(e->Eoper,ty2,e1->E2);
3531: }
3532: }
3533: break;
3534: }
3535: /* FALL-THROUGH */
3536: #endif
3537: case OPlngsht:
3538: /* Make sure e1->E1 is of the type we're converting from */
3539: if (tysize(ty1) == LONGSIZE)
3540: {
3541: ty1 = (tyuns(ty1) ? TYushort : TYshort) | (ty1 & ~mTYbasic);
3542: e1->E1 = el_una(e->Eoper,ty1,e1->E1);
3543: }
3544: /* Rvalue may be an int if it is a shift operator */
3545: if (OTbinary(e1->Eoper))
3546: { tym_t ty2 = e1->E2->Ety;
3547:
3548: if (tysize(ty2) == LONGSIZE)
3549: {
3550: ty2 = (tyuns(ty2) ? TYushort : TYshort) |
3551: (ty2 & ~mTYbasic);
3552: e1->E2 = el_una(e->Eoper,ty2,e1->E2);
3553: }
3554: }
3555: break;
3556: default:
3557: assert(0);
3558: }
3559: e1->Ety = ty;
3560: e = el_selecte1(e);
3561: again = 1;
3562: return e;
3563: }
3564: break;
3565: }
3566: return e;
3567: }
3568:
3569:
3570: /************************
3571: * Optimize conversions of long longs to ints.
3572: * OP64_32, OP128_64
3573: */
3574:
3575: STATIC elem * el64_32(elem *e)
3576: {
3577: tym_t ty = e->Ety;
3578: elem *e1 = e->E1;
3579: switch (e1->Eoper)
3580: {
3581: case OPs32_64:
3582: case OPu32_64:
3583: case OPs64_128:
3584: case OPu64_128:
3585: case OPpair:
3586: if (tysize(ty) != tysize(e->E1->E1->Ety))
3587: break;
3588: e = el_selecte1(el_selecte1(e));
3589: e->Ety = ty;
3590: break;
3591:
3592: case OPrpair:
3593: if (tysize(ty) != tysize(e->E1->E2->Ety))
3594: break;
3595: e = el_selecte2(el_selecte1(e));
3596: e->Ety = ty;
3597: break;
3598:
3599: case OPvar: // simply paint type of variable
3600: case OPind:
3601: e = el_selecte1(e);
3602: break;
3603:
3604: case OPshr: // OP64_32(x >> 32) => OPmsw(x)
3605: if (e1->E2->Eoper == OPconst &&
3606: (e->Eoper == OP64_32 && el_tolong(e1->E2) == 32 && !I64 ||
3607: e->Eoper == OP128_64 && el_tolong(e1->E2) == 64 && I64)
3608: )
3609: {
3610: e->Eoper = OPmsw;
3611: e->E1 = el_selecte1(e->E1);
3612: }
3613: break;
3614: }
3615: return e;
3616: }
3617:
3618:
3619: /*******************************
3620: * Convert complex to real.
3621: */
3622:
3623: STATIC elem *elc_r(elem *e)
3624: {
3625: elem *e1 = e->E1;
3626:
3627: if (e1->Eoper == OPvar || e1->Eoper == OPind)
3628: {
3629: e1->Ety = e->Ety;
3630: e = el_selecte1(e);
3631: }
3632: return e;
3633: }
3634:
3635: /*******************************
3636: * Convert complex to imaginary.
3637: */
3638:
3639: STATIC elem *elc_i(elem *e)
3640: {
3641: elem *e1 = e->E1;
3642:
3643: if (e1->Eoper == OPvar)
3644: {
3645: e1->Ety = e->Ety;
3646: e1->EV.sp.Voffset += tysize(e->Ety);
3647: e = el_selecte1(e);
3648: }
3649: else if (e1->Eoper == OPind)
3650: {
3651: e1->Ety = e->Ety;
3652: e = el_selecte1(e);
3653: e->E1 = el_bin(OPadd, e->E1->Ety, e->E1, el_long(TYint, tysize(e->Ety)));
3654: return optelem(e, TRUE);
3655: }
3656:
3657: return e;
3658: }
3659:
3660: /******************************
3661: * Handle OPu8int and OPs8int.
3662: */
3663:
3664: STATIC elem * elbyteint(elem *e)
3665: {
3666: if (OTlogical(e->E1->Eoper))
3667: {
3668: e->E1->Ety = e->Ety;
3669: e = el_selecte1(e);
3670: }
3671: return e;
3672: }
3673:
3674: /************************
3675: * Handle <<, OProl and OPror
3676: */
3677:
3678: STATIC elem *elshl(elem *e)
3679: {
3680: if (e->E1->Eoper == OPconst && !boolres(e->E1)) // if e1 is 0
3681: { e->E1->Ety = e->Ety;
3682: e = el_selecte1(e); // (0 << e2) => 0
3683: }
3684: return e;
3685: }
3686:
3687: /************************
3688: * Handle >>
3689: * OPshr, OPashr
3690: */
3691:
3692: STATIC elem * elshr(elem *e)
3693: {
3694: #if TX86
3695: tym_t ty = e->Ety;
3696: elem *e1 = e->E1;
3697: elem *e2 = e->E2;
3698:
3699: // (x >> 16) replaced with ((shtlng) x+2)
3700: if (OPTIMIZER &&
3701: e2->Eoper == OPconst && e2->EV.Vshort == SHORTSIZE * 8 &&
3702: tysize(ty) == LONGSIZE)
3703: {
3704: if (e1->Eoper == OPvar)
3705: {
3706: Symbol *s = e1->EV.sp.Vsym;
3707:
3708: if (s->Sclass != SCfastpar)
3709: {
3710: e1->EV.sp.Voffset += SHORTSIZE; // address high word in long
3711: if (I32)
3712: // Cannot independently address high word of register
3713: s->Sflags &= ~GTregcand;
3714: goto L1;
3715: }
3716: }
3717: else if (e1->Eoper == OPind)
3718: {
3719: /* Replace (*p >> 16) with (shtlng)(*(&*p + 2)) */
3720: e->E1 = el_una(OPind,TYshort,
3721: el_bin(OPadd,e1->E1->Ety,
3722: el_una(OPaddr,e1->E1->Ety,e1),
3723: el_int(TYint,SHORTSIZE)));
3724: L1:
3725: e->Eoper = tyuns(e1->Ety) ? OPu16_32 : OPshtlng;
3726: el_free(e2);
3727: e->E2 = NULL;
3728: e1->Ety = TYshort;
3729: e = optelem(e,TRUE);
3730: }
3731: }
3732:
3733: // (x >> 32) replaced with ((lngllng) x+4)
3734: if (e2->Eoper == OPconst && e2->EV.Vlong == LONGSIZE * 8 &&
3735: tysize(ty) == LLONGSIZE)
3736: {
3737: if (e1->Eoper == OPvar)
3738: {
3739: e1->EV.sp.Voffset += LONGSIZE; // address high dword in longlong
3740: if (I64)
3741: // Cannot independently address high word of register
3742: e1->EV.sp.Vsym->Sflags &= ~GTregcand;
3743: goto L2;
3744: }
3745: else if (e1->Eoper == OPind)
3746: {
3747: // Replace (*p >> 32) with (lngllng)(*(&*p + 4))
3748: e->E1 = el_una(OPind,TYlong,
3749: el_bin(OPadd,e1->E1->Ety,
3750: el_una(OPaddr,e1->E1->Ety,e1),
3751: el_int(TYint,LONGSIZE)));
3752: L2:
3753: e->Eoper = tyuns(e1->Ety) ? OPu32_64 : OPs32_64;
3754: el_free(e2);
3755: e->E2 = NULL;
3756: e1->Ety = TYlong;
3757: e = optelem(e,TRUE);
3758: }
3759: }
3760: #endif
3761: return e;
3762: }
3763:
3764: /***********************************
3765: * Handle OPpair, OPrpair.
3766: */
3767:
3768: elem *elpair(elem *e)
3769: {
3770: elem *e1;
3771:
3772: //printf("elpair()\n");
3773: e1 = e->E1;
3774: if (e1->Eoper == OPconst)
3775: {
3776: e->E1 = e->E2;
3777: e->E2 = e1;
3778: e->Eoper ^= OPpair ^ OPrpair;
3779: }
3780: return e;
3781: }
3782:
3783: /********************************
3784: * Handle OPddtor
3785: */
3786:
3787: elem *elddtor(elem *e)
3788: {
3789: return e;
3790: }
3791:
3792: /********************************
3793: * Handle OPinfo, OPmark, OPctor, OPdtor
3794: */
3795:
3796: STATIC elem * elinfo(elem *e)
3797: {
3798: //printf("elinfo()\n");
3799: #if NTEXCEPTIONS && SCPP
3800: if (funcsym_p->Sfunc->Fflags3 & Fnteh)
3801: { // Eliminate cleanup info if using NT structured EH
3802: if (e->Eoper == OPinfo)
3803: e = el_selecte2(e);
3804: else
3805: { el_free(e);
3806: e = el_long(TYint,0);
3807: }
3808: }
3809: #endif
3810: return e;
3811: }
3812:
3813: /********************************************
3814: */
3815:
3816: STATIC elem * elhstring(elem *e)
3817: {
3818: return e;
3819: }
3820:
3821: /********************************************
3822: */
3823:
3824: STATIC elem * elnullcheck(elem *e)
3825: {
3826: return e;
3827: }
3828:
3829:
3830: /********************************************
3831: */
3832:
3833: STATIC elem * elclassinit(elem *e)
3834: {
3835: return e;
3836: }
3837:
3838: /********************************************
3839: */
3840:
3841: STATIC elem * elnewarray(elem *e)
3842: {
3843: return e;
3844: }
3845:
3846: /********************************************
3847: */
3848:
3849: STATIC elem * elmultinewarray(elem *e)
3850: {
3851: return e;
3852: }
3853:
3854: /********************************************
3855: */
3856:
3857: STATIC elem * elinstanceof(elem *e)
3858: {
3859: return e;
3860: }
3861:
3862: /********************************************
3863: */
3864:
3865: STATIC elem * elfinalinstanceof(elem *e)
3866: {
3867: return e;
3868: }
3869:
3870: /********************************************
3871: */
3872:
3873: STATIC elem * elcheckcast(elem *e)
3874: {
3875: return e;
3876: }
3877:
3878: /********************************************
3879: */
3880:
3881: STATIC elem * elarraylength(elem *e)
3882: {
3883: return e;
3884: }
3885:
3886: /********************************************
3887: */
3888:
3889: STATIC elem * elarray(elem *e)
3890: {
3891: return e;
3892: }
3893:
3894: /********************************************
3895: */
3896:
3897: STATIC elem * elfield(elem *e)
3898: {
3899: return e;
3900: }
3901:
3902: /******************************************
3903: * OPparam
3904: */
3905:
3906: STATIC void elparamx(elem *e)
3907: {
3908: //printf("elparam()\n");
3909: if (e->E1->Eoper == OPrpair)
3910: {
3911: e->E1->Eoper = OPparam;
3912: }
3913: else if (e->E1->Eoper == OPpair && !el_sideeffect(e->E1))
3914: {
3915: e->E1->Eoper = OPparam;
3916: elem *ex = e->E1->E2;
3917: e->E1->E2 = e->E1->E1;
3918: e->E1->E1 = ex;
3919: }
3920: #if 0
3921: // Unfortunately, these don't work because if the last parameter
3922: // is a pair, and it is a D function, the last parameter will get
3923: // passed in EAX.
3924: else if (e->E2->Eoper == OPrpair)
3925: {
3926: e->E2->Eoper = OPparam;
3927: }
3928: else if (e->E2->Eoper == OPpair)
3929: {
3930: e->E2->Eoper = OPparam;
3931: elem *ex = e->E2->E2;
3932: e->E2->E2 = e->E2->E1;
3933: e->E2->E1 = ex;
3934: }
3935: #endif
3936: }
3937:
3938: STATIC elem * elparam(elem *e)
3939: {
3940: if (!OPTIMIZER)
3941: {
3942: if (!I64)
3943: elparamx(e);
3944: }
3945: return e;
3946: }
3947:
3948: /********************************
3949: * Optimize an element. This routine is recursive!
3950: * Be careful not to do this if VBEs have been done (else the VBE
3951: * work will be undone), or it DAGs have been built (will crash if
3952: * there is more than one parent for an elem).
3953: * If (goal)
3954: * we care about the result.
3955: */
3956:
3957: STATIC elem * optelem(elem *e,HINT goal)
3958: { elem *e1,*e2;
3959: unsigned op;
3960: #include "elxxx.c" /* jump table */
3961:
3962: beg:
3963: #if MARS
3964: util_progress();
3965: #else
3966: if (controlc_saw)
3967: util_exit(EXIT_BREAK);
3968: #endif
3969: //{ printf("xoptelem: %p ",e); WROP(e->Eoper); dbg_printf(" goal %d\n", goal); }
3970: assert(e);
3971: elem_debug(e);
3972: assert(e->Ecount == 0); // no CSEs
3973:
3974: if (OPTIMIZER)
3975: {
3976: if (goal)
3977: e->Nflags &= ~NFLnogoal;
3978: else
3979: e->Nflags |= NFLnogoal;
3980: }
3981:
3982: op = e->Eoper;
3983: if (OTleaf(op)) // if not an operator node
3984: {
3985: if (goal || OTsideff(op) || e->Ety & mTYvolatile)
3986: {
3987: return e;
3988: }
3989: else
3990: {
3991: retnull:
3992: el_free(e);
3993: return NULL;
3994: }
3995: }
3996: else if (OTbinary(op)) // if binary operator
3997: { HINT leftgoal = 1;
3998: HINT rightgoal;
3999:
4000: /* Determine goals for left and right subtrees */
4001: rightgoal = (goal || OTsideff(op));
4002: switch (op)
4003: { case OPcomma:
4004: e1 = e->E1 = optelem(e->E1,FALSE);
4005: // if (e1 && !OTsideff(e1->Eoper))
4006: // e1 = e->E1 = optelem(e1, FALSE);
4007: e2 = e->E2 = optelem(e->E2,rightgoal);
4008: if (!e1)
4009: { if (!e2)
4010: goto retnull;
4011: if (!goal)
4012: e->Ety = e->E2->Ety;
4013: e = el_selecte2(e);
4014: return e;
4015: }
4016: if (!e2)
4017: { e->Ety = e->E1->Ety;
4018: return el_selecte1(e);
4019: }
4020: if (!goal)
4021: e->Ety = e2->Ety;
4022: return e;
4023:
4024: case OPcond:
4025: if (!goal)
4026: { // Transform x?y:z into x&&y or x||z
4027: if (!el_sideeffect(e->E2->E1))
4028: { e->Eoper = OPoror;
4029: e->E2 = el_selecte2(e->E2);
4030: e->Ety = TYint;
4031: goto beg;
4032: }
4033: else if (!el_sideeffect(e->E2->E2))
4034: { e->Eoper = OPandand;
4035: e->E2 = el_selecte1(e->E2);
4036: e->Ety = TYint;
4037: goto beg;
4038: }
4039: }
4040: goto Llog;
4041:
4042: case OPandand:
4043: case OPoror: /* case (c || f()) with no goal */
4044: Llog:
4045: if (goal || el_sideeffect(e->E2))
4046: leftgoal = TRUE;
4047: break;
4048:
4049: default:
4050: leftgoal = rightgoal;
4051: break;
4052: case OPcolon:
4053: case OPcolon2:
4054: if (!goal && !el_sideeffect(e))
4055: goto retnull;
4056: leftgoal = rightgoal;
4057: break;
4058: #if TX86
4059: case OPmemcmp:
4060: if (!goal)
4061: { // So OPmemcmp is removed cleanly
4062: assert(e->E1->Eoper == OPparam);
4063: e->E1->Eoper = OPcomma;
4064: }
4065: leftgoal = rightgoal;
4066: break;
4067: #endif
4068: }
4069:
4070: e1 = e->E1;
4071: if (OTassign(op))
4072: { elem *ex = e1;
4073:
4074: while (OTconv(ex->Eoper))
4075: ex = ex->E1;
4076: if (ex->Eoper == OPbit)
4077: ex->E1 = optelem(ex->E1, leftgoal);
4078: else
4079: e1 = e->E1 = optelem(e1,leftgoal);
4080: }
4081: else
4082: e1 = e->E1 = optelem(e1,leftgoal);
4083:
4084: e2 = e->E2 = optelem(e->E2,rightgoal);
4085: if (!e1)
4086: { if (!e2)
4087: goto retnull;
4088: return el_selecte2(e);
4089: }
4090: if (!e2)
4091: {
4092: if (!leftgoal)
4093: e->Ety = e1->Ety;
4094: return el_selecte1(e);
4095: }
4096:
4097: if (cnst(e1) && cnst(e2))
4098: {
4099: e = evalu8(e);
4100: return e;
4101: }
4102: if (OPTIMIZER)
4103: {
4104: if (OTassoc(op))
4105: {
4106: /* Replace (a op1 (b op2 c)) with ((a op2 b) op1 c)
4107: (this must come before the leaf swapping, or we could cause
4108: infinite loops)
4109: */
4110: if (e2->Eoper == op &&
4111: e2->E2->Eoper == OPconst &&
4112: tysize(e2->E1->Ety) == tysize(e2->E2->Ety) &&
4113: (!tyfloating(e1->Ety) || e1->Ety == e2->Ety)
4114: )
4115: {
4116: e->E1 = e2;
4117: e->E2 = e2->E2;
4118: e2->E2 = e2->E1;
4119: e2->E1 = e1;
4120: if (op == OPadd) /* fix types */
4121: {
4122: e1 = e->E1;
4123: if (typtr(e1->E2->Ety))
4124: e1->Ety = e1->E2->Ety;
4125: else
4126: /* suppose a and b are ints, and c is a pointer */
4127: /* then this will fix the type of op2 to be int */
4128: e1->Ety = e1->E1->Ety;
4129: }
4130: goto beg;
4131: }
4132:
4133: // Replace ((a op c1) op c2) with (a op (c2 op c1))
4134: if (e1->Eoper == op &&
4135: e2->Eoper == OPconst &&
4136: e1->E2->Eoper == OPconst &&
4137: e1->E1->Eoper != OPconst &&
4138: tysize(e2->Ety) == tysize(e1->E2->Ety))
4139: {
4140: e->E1 = e1->E1;
4141: e1->E1 = e2;
4142: e1->Ety = e2->Ety;
4143: e->E2 = e1;
4144:
4145: if (tyfloating(e1->Ety))
4146: {
4147: e1 = evalu8(e1);
4148: if (EOP(e1)) // if failed to fold the constants
4149: { // Undo the changes so we don't infinite loop
4150: e->E2 = e1->E1;
4151: e1->E1 = e->E1;
4152: e->E1 = e1;
4153: }
4154: else
4155: { e->E2 = e1;
4156: goto beg;
4157: }
4158: }
4159: else
4160: goto beg;
4161: }
4162: }
4163:
4164: if (!OTrtol(op) && op != OPparam && op != OPcolon && op != OPcolon2 &&
4165: e1->Eoper == OPcomma)
4166: { // Convert ((a,b) op c) to (a,(b op c))
4167: e1->Ety = e->Ety;
4168: e1->ET = e->ET;
4169: e->E1 = e1->E2;
4170: e1->E2 = e;
4171: e = e1;
4172: goto beg;
4173: }
4174: }
4175:
4176: if (OTcommut(op)) // if commutative
4177: {
4178: /* see if we should swap the leaves */
4179: #if 0
4180: if (tyfloating(e1->Ety))
4181: {
4182: if (fcost(e2) > fcost(e1))
4183: { e->E1 = e2;
4184: e2 = e->E2 = e1;
4185: e1 = e->E1; // reverse the leaves
4186: op = e->Eoper = swaprel(op);
4187: }
4188: }
4189: else
4190: #endif
4191: if (
4192: #if MARS
4193: cost(e2) > cost(e1)
4194: /* Swap only if order of evaluation can be proved
4195: * to not matter, as we must evaluate Left-to-Right
4196: */
4197: && (e1->Eoper == OPconst ||
4198: e1->Eoper == OPrelconst ||
4199: /* Local variables that are not aliased
4200: * and are not assigned to in e2
4201: */
4202: (e1->Eoper == OPvar && e1->EV.sp.Vsym->Sflags & SFLunambig && !el_appears(e2,e1->EV.sp.Vsym)) ||
4203: !(el_sideeffect(e1) || el_sideeffect(e2))
4204: )
4205: #else
4206: cost(e2) > cost(e1)
4207: #endif
4208: )
4209: {
4210: e->E1 = e2;
4211: e2 = e->E2 = e1;
4212: e1 = e->E1; // reverse the leaves
4213: op = e->Eoper = swaprel(op);
4214: }
4215: if (OTassoc(op)) // if commutative and associative
4216: {
4217: if (EOP(e1) &&
4218: op == e1->Eoper &&
4219: e1->E2->Eoper == OPconst &&
4220: e->Ety == e1->Ety &&
4221: tysize(e1->E2->Ety) == tysize(e2->Ety)
4222: #if MARS
4223: // Reordering floating point can change the semantics
4224: && !tyfloating(e1->Ety)
4225: #endif
4226: )
4227: {
4228: // look for ((e op c1) op c2),
4229: // replace with (e op (c1 op c2))
4230: if (e2->Eoper == OPconst)
4231: {
4232: e->E1 = e1->E1;
4233: e->E2 = e1;
4234: e1->E1 = e1->E2;
4235: e1->E2 = e2;
4236: e1->Ety = e2->Ety;
4237:
4238: e1 = e->E1;
4239: e2 = e->E2 = evalu8(e->E2);
4240: }
4241: else
4242: { // Replace ((e op c) op e2) with ((e op e2) op c)
4243: e->E2 = e1->E2;
4244: e1->E2 = e2;
4245: e2 = e->E2;
4246: }
4247: }
4248: }
4249: }
4250:
4251: if (e2->Eoper == OPconst && // if right operand is a constant
4252: !(OTopeq(op) && OTconv(e1->Eoper))
4253: )
4254: {
4255: #ifdef DEBUG
4256: assert(!(OTeop0e(op) && (OTeop00(op))));
4257: #endif
4258: if (OTeop0e(op)) /* if e1 op 0 => e1 */
4259: {
4260: if (!boolres(e2)) /* if e2 is 0 */
4261: {
4262: // Don't do it for ANSI floating point
4263: if (tyfloating(e1->Ety) && !(config.flags4 & CFG4fastfloat))
4264: ;
4265: // Don't do it if we're assembling a complex value
4266: else if ((tytab[e->E1->Ety & 0xFF] ^
4267: tytab[e->E2->Ety & 0xFF]) == (TYFLreal | TYFLimaginary))
4268: ;
4269: else
4270: return optelem(el_selecte1(e),goal);
4271: }
4272: }
4273: else if (OTeop00(op) && !boolres(e2) && !tyfloating(e->Ety))
4274: { if (OTassign(op))
4275: op = e->Eoper = OPeq;
4276: else
4277: op = e->Eoper = OPcomma;
4278: }
4279: if (OTeop1e(op)) /* if e1 op 1 => e1 */
4280: {
4281: if (elemisone(e2) && !tyimaginary(e2->Ety))
4282: return optelem(el_selecte1(e),goal);
4283: }
4284: }
4285:
4286: if (OTpost(op) && !goal)
4287: {
4288: op = e->Eoper = (op == OPpostinc) ? OPaddass : OPminass;
4289: }
4290: }
4291: else /* unary operator */
4292: {
4293: assert(!e->E2 || op == OPinfo || op == OParraylength || op == OPddtor);
4294: if (!goal && !OTsideff(op))
4295: {
4296: tym_t tym = e->E1->Ety;
4297:
4298: e = el_selecte1(e);
4299: e->Ety = tym;
4300: return optelem(e,FALSE);
4301: }
4302:
4303: e1 = e->E1 = optelem(e->E1,TRUE);
4304: if (e1->Eoper == OPconst)
4305: {
4306: #if TX86
4307: if (!(op == OPptrlptr && el_tolong(e1) != 0))
4308: #endif
4309: return evalu8(e);
4310: }
4311: e2 = NULL;
4312: }
4313:
4314: L1:
warning C4102: 'L1' : unreferenced label
4315: #ifdef DEBUG
4316: // if (debugb)
4317: // { dbg_printf("optelem: %p ",e); WROP(op); dbg_printf("\n"); }
4318: #endif
4319:
4320: expgoal = goal;
4321: #if 0
4322: { dbg_printf("xoptelem: %p ",e); WROP(e->Eoper); dbg_printf("\n"); }
4323: elem_print(e);
4324: e = (*elxxx[op])(e);
4325: printf("After:\n");
4326: elem_print(e);
4327: return e;
4328: #else
4329: return (*elxxx[op])(e);
warning C6385: Invalid data: accessing 'struct elem * (__cdecl** `struct elem * __cdecl optelem(struct elem *,int)'::`2'::elxxx)(struct elem *)', the readable size is '732' bytes, but '100476' bytes might be read: Lines: 3958, 3959, c:\projects\extern\d\dmd\src\elxxx.c:1, c:\projects\extern\d\dmd\src\backend\cgelem.c:3962, 3964, 3970, 3972, 3974, 3976, 3977, 3982, 3983, 3996, 3997, 3998, 4001, 4002, 4024, 4025, 4040, 4042, 4043, 4044, 4045, 4046, 4070, 4071, 4072, 4074, 4076, 4079, 4084, 4085, 4090, 4097, 4102, 4104, 4164, 4176, 4197, 4210, 4211, 4212, 4213, 4215, 4224, 4251, 4286, 4314, 4320, 4329
4330: #endif
4331: }
4332:
4333: /********************************
4334: * Optimize and canonicalize an expression tree.
4335: * Fiddle with double operators so that the rvalue is a pointer
4336: * (this is needed by the 8086 code generator).
4337: *
4338: * op op
4339: * / \ / \
4340: * e1 e2 e1 ,
4341: * / \
4342: * = &
4343: * / \ \
4344: * fr e2 fr
4345: *
4346: * e1 op (*p) e1 op p
4347: * e1 op c e1 op &dc
4348: * e1 op v e1 op &v
4349: */
4350:
4351: elem *doptelem(elem *e,HINT goal)
4352: {
4353: //printf("doptelem(e = %p, goal = %d)\n", e, goal);
4354: cgelem_goal = goal;
4355:
4356: assert(!PARSER);
4357: do
4358: { again = 0;
4359: e = optelem(e,goal & (GOALflags | GOALvalue | GOALnone));
4360: } while (again && goal & GOALagain && e);
4361:
4362: /* If entire expression is a struct, and we can replace it with */
4363: /* something simpler, do so. */
4364: if (goal & GOALstruct && e && tybasic(e->Ety) == TYstruct)
4365: e = elstruct(e);
4366:
4367: return e;
4368: }
4369:
4370: /****************************************
4371: * Do optimizations after bltailrecursion() and before common subexpressions.
4372: */
4373:
4374: void postoptelem(elem *e)
4375: {
4376: int linnum = 0;
4377: const char *filename = NULL;
4378:
4379: elem_debug(e);
4380: while (1)
4381: {
4382: if (OTunary(e->Eoper))
4383: {
4384: /* This is necessary as the optimizer tends to lose this information
4385: */
4386: #if MARS
4387: if (e->Esrcpos.Slinnum > linnum)
warning C4018: '>' : signed/unsigned mismatch
4388: { linnum = e->Esrcpos.Slinnum;
4389: filename = e->Esrcpos.Sfilename;
4390: }
4391: #endif
4392: if (e->Eoper == OPind)
4393: {
4394: #if MARS
4395: if (e->E1->Eoper == OPconst &&
4396: el_tolong(e->E1) >= 0 && el_tolong(e->E1) < 4096)
4397: {
4398: error(filename, linnum, "null dereference in function %s", funcsym_p->Sident);
4399: e->E1->EV.Vlong = 4096; // suppress redundant messages
4400: }
4401: #endif
4402: }
4403: e = e->E1;
4404: }
4405: else if (OTbinary(e->Eoper))
4406: {
4407: #if MARS
4408: /* This is necessary as the optimizer tends to lose this information
4409: */
4410: if (e->Esrcpos.Slinnum > linnum)
warning C4018: '>' : signed/unsigned mismatch
4411: { linnum = e->Esrcpos.Slinnum;
4412: filename = e->Esrcpos.Sfilename;
4413: }
4414: #endif
4415: if (e->Eoper == OPparam)
4416: {
4417: if (!I64)
4418: elparamx(e);
4419: }
4420: postoptelem(e->E2);
4421: e = e->E1;
4422: }
4423: else
4424: break;
4425: }
4426: }
4427:
4428: #endif // !SPP
4429: