1 /**
2  * Local optimizations of elem trees
3  *
4  * Compiler implementation of the
5  * $(LINK2 https://www.dlang.org, D programming language).
6  *
7  * Does strength reduction optimizations on the elem trees,
8  * i.e. rewriting trees to less expensive trees.
9  *
10  * Copyright:   Copyright (C) 1985-1998 by Symantec
11  *              Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved
12  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
13  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
14  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/cgelem.d, backend/cgelem.d)
15  * Documentation:  https://dlang.org/phobos/dmd_backend_cgelem.html
16  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/backend/cgelem.d
17  *              Add coverage tests to https://github.com/dlang/dmd/blob/master/test/runnable/testcgelem.d
18  */
19 
20 module dmd.backend.cgelem;
21 
22 import core.stdc.stdio;
23 import core.stdc.stdlib;
24 import core.stdc.string;
25 
26 import dmd.backend.cc;
27 import dmd.backend.code;
28 import dmd.backend.cdef;
29 import dmd.backend.code_x86;
30 import dmd.backend.oper;
31 import dmd.backend.global;
32 import dmd.backend.goh;
33 import dmd.backend.el;
34 import dmd.backend.rtlsym;
35 import dmd.backend.symtab;
36 import dmd.backend.ty;
37 import dmd.backend.type;
38 
39 import dmd.backend.dlist;
40 import dmd.backend.dvec;
41 
42 
43 nothrow:
44 @safe:
45 
46 import dmd.backend.evalu8 : evalu8;
47 
48 /* Masks so we can easily check size */
49 enum CHARMASK  = 0xFF;
50 enum SHORTMASK = 0xFFFF;
51 enum INTMASK   = SHORTMASK;
52 enum LONGMASK  = 0xFFFFFFFF;
53 
54 /* Common constants often checked for */
55 enum LLONGMASK = 0xFFFFFFFFFFFFFFFFL;
56 enum ZEROLL    = 0L;
57 
58 private __gshared
59 {
60     bool again;
61     bool topair;
62     tym_t global_tyf;
63 }
64 
65 private bool cnst(const elem* e) { return e.Eoper == OPconst; }
66 
67 /*****************************
68  */
69 
70 @trusted
71 private elem * cgel_lvalue(elem *e)
72 {
73     //printf("cgel_lvalue()\n"); elem_print(e);
74     elem *e1 = e.EV.E1;
75     if (e1.Eoper == OPbit)
76     {
77         elem *e11 = e1.EV.E1;
78 
79         if (e11.Eoper == OPcomma)
80         {
81             // Replace (((e,v) bit x) op e2) with (e,((v bit x) op e2))
82             e1.EV.E1 = e11.EV.E2;
83             e11.EV.E2 = e;
84             e11.Ety = e.Ety;
85             e11.ET = e.ET;
86             e = e11;
87             goto L1;
88         }
89         else if (OTassign(e11.Eoper))
90         {
91             // Replace (((e op= v) bit x) op e2) with ((e op= v) , ((e bit x) op e2))
92             e1.EV.E1 = el_copytree(e11.EV.E1);
93             e = el_bin(OPcomma,e.Ety,e11,e);
94             goto L1;
95         }
96     }
97     else if (e1.Eoper == OPcomma)
98     {
99         // Replace ((e,v) op e2) with (e,(v op e2))
100         const op = e.Eoper;
101         e.Eoper = OPcomma;
102         e1.Eoper = op;
103         e1.Ety = e.Ety;
104         e1.ET = e.ET;
105         e.EV.E1 = e1.EV.E1;
106         e1.EV.E1 = e1.EV.E2;
107         e1.EV.E2 = e.EV.E2;
108         e.EV.E2 = e1;
109         goto L1;
110     }
111     else if (OTassign(e1.Eoper))
112     {
113         // Replace ((e op= v) op e2) with ((e op= v) , (e op e2))
114         e.EV.E1 = el_copytree(e1.EV.E1);
115         e = el_bin(OPcomma,e.Ety,e1,e);
116     L1:
117         e = optelem(e,GOALvalue);
118     }
119     return e;
120 }
121 
122 
123 /******************************
124  * Scan down commas.
125  */
126 
127 @trusted
128 private elem * elscancommas(elem *e)
129 {
130     while (e.Eoper == OPcomma
131            || e.Eoper == OPinfo
132           )
133         e = e.EV.E2;
134     return e;
135 }
136 
137 /*************************
138  * Returns:
139  *    true if elem is the constant 1.
140  */
141 
142 int elemisone(elem *e)
143 {
144     if (e.Eoper == OPconst)
145     {
146         switch (tybasic(e.Ety))
147         {
148             case TYchar:
149             case TYuchar:
150             case TYschar:
151             case TYchar16:
152             case TYshort:
153             case TYushort:
154             case TYint:
155             case TYuint:
156             case TYlong:
157             case TYulong:
158             case TYllong:
159             case TYullong:
160             case TYnullptr:
161             case TYsptr:
162             case TYcptr:
163             case TYhptr:
164             case TYfptr:
165             case TYvptr:
166             case TYnptr:
167             case TYimmutPtr:
168             case TYsharePtr:
169             case TYrestrictPtr:
170             case TYfgPtr:
171             case TYbool:
172             case TYwchar_t:
173             case TYdchar:
174                 if (el_tolong(e) != 1)
175                     goto nomatch;
176                 break;
177             case TYldouble:
178             case TYildouble:
179                 if (e.EV.Vldouble != 1)
180                     goto nomatch;
181                 break;
182             case TYdouble:
183             case TYidouble:
184             case TYdouble_alias:
185                 if (e.EV.Vdouble != 1)
186                         goto nomatch;
187                 break;
188             case TYfloat:
189             case TYifloat:
190                 if (e.EV.Vfloat != 1)
191                         goto nomatch;
192                 break;
193             default:
194                 goto nomatch;
195         }
196         return true;
197     }
198 
199 nomatch:
200     return false;
201 }
202 
203 /*************************
204  * Returns: true if elem is the constant -1.
205  */
206 
207 int elemisnegone(elem *e)
208 {
209     if (e.Eoper == OPconst)
210     {
211         switch (tybasic(e.Ety))
212         {
213             case TYchar:
214             case TYuchar:
215             case TYschar:
216             case TYchar16:
217             case TYshort:
218             case TYushort:
219             case TYint:
220             case TYuint:
221             case TYlong:
222             case TYulong:
223             case TYllong:
224             case TYullong:
225             case TYnullptr:
226             case TYnptr:
227             case TYsptr:
228             case TYcptr:
229             case TYhptr:
230             case TYfptr:
231             case TYvptr:
232             case TYimmutPtr:
233             case TYsharePtr:
234             case TYrestrictPtr:
235             case TYfgPtr:
236             case TYbool:
237             case TYwchar_t:
238             case TYdchar:
239                 if (el_tolong(e) != -1)
240                     goto nomatch;
241                 break;
242             case TYldouble:
243             //case TYildouble:
244                 if (e.EV.Vldouble != -1)
245                     goto nomatch;
246                 break;
247             case TYdouble:
248             //case TYidouble:
249             case TYdouble_alias:
250                 if (e.EV.Vdouble != -1)
251                         goto nomatch;
252                 break;
253             case TYfloat:
254             //case TYifloat:
255                 if (e.EV.Vfloat != -1)
256                         goto nomatch;
257                 break;
258             default:
259                 goto nomatch;
260         }
261         return true;
262     }
263 
264 nomatch:
265     return false;
266 }
267 
268 /**********************************
269  * Swap relational operators (like if we swapped the leaves).
270  */
271 
272 OPER swaprel(OPER op)
273 {
274     assert(op < OPMAX);
275     if (OTrel(op))
276         op = rel_swap(op);
277     return op;
278 }
279 
280 /**************************
281  * Replace e1 by t=e1, replace e2 by t.
282  */
283 
284 private void fixside(elem **pe1,elem **pe2)
285 {
286     const tym = (*pe1).Ety;
287     elem *tmp = el_alloctmp(tym);
288     *pe1 = el_bin(OPeq,tym,tmp,*pe1);
289     elem *e2 = el_copytree(tmp);
290     el_free(*pe2);
291     *pe2 = e2;
292 }
293 
294 
295 
296 /****************************
297  * Compute the 'cost' of evaluating a elem. Could be done
298  * as Sethi-Ullman numbers, but that ain't worth the bother.
299  * We'll fake it.
300  */
301 
302 private int cost(const elem* n) { return opcost[n.Eoper]; }
303 
304 /*******************************
305  * For floating point expressions, the cost would be the number
306  * of registers in the FPU stack needed.
307  */
308 
309 @trusted
310 private int fcost(const elem *e)
311 {
312     int cost;
313 
314     //printf("fcost()\n");
315     switch (e.Eoper)
316     {
317         case OPadd:
318         case OPmin:
319         case OPmul:
320         case OPdiv:
321         {
322             const int cost1 = fcost(e.EV.E1);
323             const int cost2 = fcost(e.EV.E2);
324             cost = cost2 + 1;
325             if (cost1 > cost)
326                 cost = cost1;
327             break;
328         }
329 
330         case OPcall:
331         case OPucall:
332             cost = 8;
333             break;
334 
335         case OPneg:
336         case OPabs:
337         case OPtoprec:
338             return fcost(e.EV.E1);
339 
340         case OPvar:
341         case OPconst:
342         case OPind:
343         default:
344             return 1;
345     }
346     if (cost > 8)
347         cost = 8;
348     return cost;
349 }
350 
351 /*******************************
352  * The lvalue of an op= is a conversion operator. Since the code
353  * generator cannot handle this, we will have to fix it here. The
354  * general strategy is:
355  *      (conv) e1 op= e2        =>      e1 = (conv) e1 op e2
356  * Since e1 can only be evaluated once, if it is an expression we
357  * must use a temporary.
358  */
359 
360 @trusted
361 private elem *fixconvop(elem *e)
362 {
363     static immutable ubyte[CNVOPMAX - CNVOPMIN + 1] invconvtab =
364     [
365         OPbool,         // OPb_8
366         OPs32_d,        // OPd_s32
367         OPd_s32,        // OPs32_d
368         OPs16_d,        /* OPd_s16      */
369         OPd_s16,        /* OPs16_d      */
370         OPu16_d,        // OPd_u16
371         OPd_u16,        // OPu16_d
372         OPu32_d,        /* OPd_u32      */
373         OPd_u32,        /* OPu32_d      */
374         OPs64_d,        // OPd_s64
375         OPd_s64,        // OPs64_d
376         OPu64_d,        // OPd_u64
377         OPd_u64,        // OPu64_d
378         OPf_d,          // OPd_f
379         OPd_f,          // OPf_d
380         OP32_16,        // OPs16_32
381         OP32_16,        // OPu16_32
382         OPs16_32,       // OP32_16
383         OP16_8,         // OPu8_16
384         OP16_8,         // OPs8_16
385         OPs8_16,        // OP16_8
386         OP64_32,        // OPu32_64
387         OP64_32,        // OPs32_64
388         OPs32_64,       // OP64_32
389         OP128_64,       // OPu64_128
390         OP128_64,       // OPs64_128
391         OPs64_128,      // OP128_64
392 
393         0,              /* OPvp_fp      */
394         0,              /* OPcvp_fp     */
395         OPnp_fp,        /* OPoffset     */
396         OPoffset,       /* OPnp_fp      */
397         OPf16p_np,      /* OPnp_f16p    */
398         OPnp_f16p,      /* OPf16p_np    */
399 
400         OPd_ld,         // OPld_d
401         OPld_d,         // OPd_ld
402         OPu64_d,        // OPld_u64
403     ];
404 
405     //printf("fixconvop before\n");
406     //elem_print(e);
407     assert(invconvtab.length == CNVOPMAX - CNVOPMIN + 1);
408     assert(e);
409     tym_t tyme = e.Ety;
410     const cop = e.EV.E1.Eoper;             /* the conversion operator      */
411     assert(cop <= CNVOPMAX);
412 
413     elem *econv = e.EV.E1;
414     while (OTconv(econv.Eoper))
415     {
416         if (econv.EV.E1.Eoper != OPcomma)
417         {
418             econv = econv.EV.E1;
419             continue;
420         }
421         /* conv(a,b) op= e2     or     conv(conv(a,b)) op= e2
422          *   =>                 many:    =>
423          * a, (conv(b) op= e2)         a, (conv(conv(b)) op= e2)
424          */
425         elem *ecomma = econv.EV.E1;
426         econv.EV.E1 = ecomma.EV.E2;
427         econv.EV.E1.Ety = ecomma.Ety;
428         ecomma.EV.E2 = e;
429         ecomma.Ety = e.Ety;
430         //printf("fixconvop comma\n");
431         //elem_print(ecomma);
432         return optelem(ecomma, GOALvalue);
433     }
434 
435     if (e.EV.E1.Eoper == OPd_f && OTconv(e.EV.E1.EV.E1.Eoper) && tyintegral(tyme))
436     {
437         elem *e1 = e.EV.E1;
438         e.EV.E1 = e1.EV.E1;
439         e.EV.E2 = el_una(OPf_d, e.EV.E1.Ety, e.EV.E2);
440         e1.EV.E1 = null;
441         el_free(e1);
442         return fixconvop(e);
443     }
444 
445     tym_t tycop = e.EV.E1.Ety;
446     tym_t tym = e.EV.E1.EV.E1.Ety;
447     e.EV.E1 = el_selecte1(e.EV.E1);     /* dump it for now              */
448     elem *e1 = e.EV.E1;
449     e1.Ety = tym;
450     elem *e2 = e.EV.E2;
451     assert(e1 && e2);
452     /* select inverse conversion operator   */
453     const icop = invconvtab[convidx(cop)];
454 
455     /* First, let's see if we can just throw it away.       */
456     /* (unslng or shtlng) e op= e2  => e op= (lngsht) e2    */
457     if (OTwid(e.Eoper) &&
458             (cop == OPs16_32 || cop == OPu16_32 ||
459              cop == OPu8_16 || cop == OPs8_16))
460     {   if (e.Eoper != OPshlass && e.Eoper != OPshrass && e.Eoper != OPashrass)
461             e.EV.E2 = el_una(icop,tym,e2);
462 
463         // https://issues.dlang.org/show_bug.cgi?id=23618
464         if ((cop == OPu16_32 || cop == OPu8_16) && e.Eoper == OPashrass)
465             e.Eoper = OPshrass;     // always unsigned right shift for MARS
466 
467         return e;
468     }
469 
470     /* Oh well, just split up the op and the =.                     */
471     const op = opeqtoop(e.Eoper); // convert op= to op
472     e.Eoper = OPeq;                  // just plain =
473     elem *ed = el_copytree(e1);       // duplicate e1
474                                       // make: e1 = (icop) ((cop) ed op e2)
475     e.EV.E2 = el_una(icop,e1.Ety,
476                              el_bin(op,tycop,el_una(cop,tycop,ed),
477                                                   e2));
478 
479     //printf("after1\n");
480     //elem_print(e);
481 
482     if (op == OPdiv &&
483         tybasic(e2.Ety) == TYcdouble)
484     {
485         if (tycop == TYdouble)
486         {
487             e.EV.E2.EV.E1.Ety = tybasic(e2.Ety);
488             e.EV.E2.EV.E1 = el_una(OPc_r, tycop, e.EV.E2.EV.E1);
489         }
490         else if (tycop == TYidouble)
491         {
492             e.EV.E2.EV.E1.Ety = tybasic(e2.Ety);
493             e.EV.E2.EV.E1 = el_una(OPc_i, tycop, e.EV.E2.EV.E1);
494         }
495     }
496 
497     if (op == OPdiv &&
498         tybasic(e2.Ety) == TYcfloat)
499     {
500         if (tycop == TYfloat)
501         {
502             e.EV.E2.EV.E1.Ety = tybasic(e2.Ety);
503             e.EV.E2.EV.E1 = el_una(OPc_r, tycop, e.EV.E2.EV.E1);
504         }
505         else if (tycop == TYifloat)
506         {
507             e.EV.E2.EV.E1.Ety = tybasic(e2.Ety);
508             e.EV.E2.EV.E1 = el_una(OPc_i, tycop, e.EV.E2.EV.E1);
509         }
510     }
511 
512     // Handle case of multiple conversion operators on lvalue
513     // (such as (intdbl 8int char += double))
514     elem *ex = e;
515     elem **pe = &e;
516     while (OTconv(ed.Eoper))
517     {
518         const uint copx = ed.Eoper;
519         const uint icopx = invconvtab[convidx(copx)];
520         tym_t tymx = ex.EV.E1.EV.E1.Ety;
521         ex.EV.E1 = el_selecte1(ex.EV.E1);       // dump it for now
522         e1 = ex.EV.E1;
523         e1.Ety = tymx;
524         ex.EV.E2 = el_una(icopx,e1.Ety,ex.EV.E2);
525         ex.Ety = tymx;
526         tym = tymx;
527 
528         if (ex.Ety != tyme)
529         {   *pe = el_una(copx, ed.Ety, ex);
530             pe = &(*pe).EV.E1;
531         }
532 
533         ed = ed.EV.E1;
534     }
535     //printf("after2\n");
536     //elem_print(e);
537 
538     e.Ety = tym;
539     if (tym != tyme &&
540         !(tyintegral(tym) && tyintegral(tyme) && tysize(tym) == tysize(tyme)))
541         e = el_una(cop, tyme, e);
542 
543     if (ed.Eoper == OPbit)         // special handling
544     {
545         ed = ed.EV.E1;
546         e1 = e1.EV.E1;            // go down one
547     }
548 
549     /* If we have a *, must assign a temporary to the expression
550      * underneath it (even if it's a var, as e2 may modify the var)
551      */
552     if (ed.Eoper == OPind)
553     {
554         elem *T = el_alloctmp(ed.EV.E1.Ety);    // make temporary
555         ed.EV.E1 = el_bin(OPeq,T.Ety,T,ed.EV.E1); // ed: *(T=e)
556         el_free(e1.EV.E1);
557         e1.EV.E1 = el_copytree(T);
558     }
559     //printf("after3\n");
560     //elem_print(e);
561     return e;
562 }
563 
564 private elem * elerr(elem *e, goal_t goal)
565 {
566     debug elem_print(e);
567     assert(0);
568 }
569 
570 /* For ops with no optimizations */
571 
572 private elem * elzot(elem *e, goal_t goal)
573 {
574     return e;
575 }
576 
577 /****************************
578  */
579 
580 private elem * elstring(elem *e, goal_t goal)
581 {
582     return e;
583 }
584 
585 /************************
586  */
587 
588 /************************
589  * Convert far pointer to pointer.
590  */
591 
592 @trusted
593 private void eltonear(elem **pe)
594 {
595     elem *e = *pe;
596     const tym_t ty = e.EV.E1.Ety;
597     e = el_selecte1(e);
598     e.Ety = ty;
599     *pe = optelem(e,GOALvalue);
600 }
601 
602 /************************
603  */
604 
605 @trusted
606 private elem * elstrcpy(elem *e, goal_t goal)
607 {
608     elem_debug(e);
609     switch (e.EV.E2.Eoper)
610     {
611         case OPnp_fp:
612             if (OPTIMIZER)
613             {
614                 eltonear(&e.EV.E2);
615                 e = optelem(e,GOALvalue);
616             }
617             break;
618 
619         case OPstring:
620             /* Replace strcpy(e1,"string") with memcpy(e1,"string",sizeof("string")) */
621             // As streq
622             e.Eoper = OPstreq;
623             type *t = type_allocn(TYarray, tstypes[TYchar]);
624             t.Tdim = strlen(e.EV.E2.EV.Vstring) + 1;
625             e.ET = t;
626             t.Tcount++;
627             e.EV.E1 = el_una(OPind,TYstruct,e.EV.E1);
628             e.EV.E2 = el_una(OPind,TYstruct,e.EV.E2);
629 
630             e = el_bin(OPcomma,e.Ety,e,el_copytree(e.EV.E1.EV.E1));
631             if (el_sideeffect(e.EV.E2))
632                 fixside(&e.EV.E1.EV.E1.EV.E1,&e.EV.E2);
633             e = optelem(e,GOALvalue);
634             break;
635 
636         default:
637             break;
638     }
639     return e;
640 }
641 
642 /************************
643  */
644 
645 @trusted
646 private elem * elstrcmp(elem *e, goal_t goal)
647 {
648     elem_debug(e);
649     if (OPTIMIZER)
650     {
651         if (e.EV.E1.Eoper == OPnp_fp)
652             eltonear(&e.EV.E1);
653         switch (e.EV.E2.Eoper)
654         {
655             case OPnp_fp:
656                 eltonear(&e.EV.E2);
657                 break;
658 
659             case OPstring:
660                 // Replace strcmp(e1,"string") with memcmp(e1,"string",sizeof("string"))
661                 e.Eoper = OPparam;
662                 e = el_bin(OPmemcmp,e.Ety,e,el_long(TYint,strlen(e.EV.E2.EV.Vstring) + 1));
663                 e = optelem(e,GOALvalue);
664                 break;
665 
666             default:
667                 break;
668         }
669     }
670     return e;
671 }
672 
673 /****************************
674  * For OPmemcmp
675  * memcmp(a, b, nbytes) => ((a param b) OPmemcmp nbytes)
676  */
677 @trusted
678 
679 private elem * elmemcmp(elem *e, goal_t goal)
680 {
681     elem_debug(e);
682     if (!OPTIMIZER)
683         return e;
684 
685     /* Hoist comma operators in `a` out of OPmemcmp
686      */
687     {
688         elem* ec = e.EV.E1.EV.E1;
689         if (ec.Eoper == OPcomma)
690         {
691             /* Rewrite: (((a,b) param c) OPmemcmp nbytes)
692              * As: a,((b param c) OPmemcmp nbytes)
693              */
694             e.EV.E1.EV.E1 = ec.EV.E2;
695             e.EV.E1.EV.E1.Ety = ec.Ety;
696             e.EV.E1.EV.E1.ET = ec.ET;
697             ec.EV.E2 = e;
698             ec.Ety = e.Ety;
699             return optelem(ec, goal);
700         }
701     }
702 
703     /* Hoist comma operators in `b` out of OPmemcmp
704      */
705     {
706         elem* ec = e.EV.E1.EV.E2;
707         if (ec.Eoper == OPcomma)
708         {
709             /* Have: ((a param (b,c)) OPmemcmp nbytes)
710              */
711             elem* a = e.EV.E1.EV.E1;
712             elem* b = ec.EV.E1;
713             if (a.canHappenAfter(b))
714             {
715                 /* Rewrite: ((a param (b,c)) OPmemcmp nbytes)
716                  * As: b,((a param c) OPmemcmp nbytes)
717                  */
718                 e.EV.E1.EV.E2 = ec.EV.E2;
719                 e.EV.E1.EV.E2.Ety = ec.Ety;
720                 e.EV.E1.EV.E2.ET = ec.ET;
721                 ec.EV.E2 = e;
722                 ec.Ety = e.Ety;
723                 return optelem(ec, goal);
724             }
725         }
726     }
727 
728     elem *ex = e.EV.E1;
729     if (ex.EV.E1.Eoper == OPnp_fp)
730         eltonear(&ex.EV.E1);
731     if (ex.EV.E2.Eoper == OPnp_fp)
732         eltonear(&ex.EV.E2);
733 
734     return e;
735 }
736 
737 /****************************
738  * For OPmemset
739  */
740 
741 @trusted
742 private elem * elmemset(elem *e, goal_t goal)
743 {
744     //printf("elmemset()\n");
745     elem_debug(e);
746 
747     elem *ex = e.EV.E1;
748     if (ex.Eoper == OPnp_fp)
749     {
750         eltonear(&ex);
751         return e;
752     }
753 
754     // lvalue OPmemset (nelems param value)
755     elem *enelems = e.EV.E2.EV.E1;
756     elem *evalue = e.EV.E2.EV.E2;
757 
758     if (!(enelems.Eoper == OPconst && evalue.Eoper == OPconst && REGSIZE >= 4))
759         return e;
760 
761     elem *e1 = e.EV.E1;
762 
763     if (e1.Eoper == OPcomma || OTassign(e1.Eoper))
764         return cgel_lvalue(e);    // replace ((e,v) memset e2) with (e,(v memset e2))
765 
766     /* Attempt to replace OPmemset with a sequence of ordinary assignments,
767      * so cdmemset() will have fewer cases to deal with
768      */
769 
770     const sz = tysize(evalue.Ety);
771     int nelems = cast(int)el_tolong(enelems);
772     ulong value = el_tolong(evalue);
773 
774     if (sz * nelems > REGSIZE * 4)
775         return e;
776 
777     switch (sz)
778     {
779         case 1:  value = 0x0101_0101_0101_0101 * (value & 0xFF);       break;
780         case 2:  value = 0x0001_0001_0001_0001 * (value & 0xFFFF);     break;
781         case 4:  value = 0x0000_0001_0000_0001 * (value & 0xFFFFFFFF); break;
782         case 8:  break;
783         default:
784             return e;
785     }
786 
787     ulong valuexor = 0;
788     if (sz == 8 && REGSIZE == 4)
789         valuexor = (value ^ (value >> 32)) & 0xFFFF_FFFF;
790 
791     elem* ey = null;
792     if (e1.Eoper != OPrelconst)
793     {
794         ey = e1;
795         e1 = el_same(&ey);
796     }
797     e.EV.E1 = null;             // so we can free e later
798 
799     for (int offset = 0; offset < sz * nelems; )
800     {
801         int left = sz * nelems - offset;
802         if (left > REGSIZE)
803             left = REGSIZE;
804         tym_t tyv;
805         switch (left)
806         {
807             case 0: assert(0);
808             case 1: tyv = TYchar;  left = 1; break;
809             case 2:
810             case 3: tyv = TYshort; left = 2; break;
811             case 4:
812             case 5:
813             case 6:
814             case 7: tyv = TYlong;  left = 4; break;
815             default:
816             case 8: tyv = TYllong; left = 8; break;
817         }
818         auto e1a = el_copytree(e1);
819         assert(tybasic(e1a.Ety) != TYstruct);
820         e1a = el_bin(OPadd, TYnptr, e1a, el_long(TYsize_t, offset));
821         e1a = el_una(OPind, tyv, e1a);
822         auto ea = el_bin(OPeq, tyv, e1a, el_long(tyv, value));
823         if (sz * nelems - offset >= REGSIZE)
824             value ^= valuexor;          // flip between low and high 32 bits of 8 byte value
825         offset += left;
826         ey = el_combine(ey, ea);
827     }
828     ey = el_combine(ey, e1);
829     el_free(e);
830     e = optelem(ey,GOALvalue);
831     return e;
832 }
833 
834 
835 /****************************
836  * For OPmemcpy
837  *  OPmemcpy
838  *   /   \
839  * s1   OPparam
840  *       /   \
841  *      s2    n
842  */
843 
844 @trusted
845 private elem * elmemcpy(elem *e, goal_t goal)
846 {
847     elem_debug(e);
848     if (OPTIMIZER)
849     {
850         elem *ex = e.EV.E1;
851         if (ex.Eoper == OPnp_fp)
852             eltonear(&e.EV.E1);
853         ex = e.EV.E2;
854         if (ex.EV.E1.Eoper == OPnp_fp)
855             eltonear(&ex.EV.E1);
856         if (ex.EV.E2.Eoper == OPconst)
857         {
858             if (!boolres(ex.EV.E2))
859             {   // Copying 0 bytes, so remove memcpy
860                 e.EV.E2 = e.EV.E1;
861                 e.EV.E1 = ex.EV.E1;
862                 ex.EV.E1 = null;
863                 e.Eoper = OPcomma;
864                 el_free(ex);
865                 return optelem(e, GOALvalue);
866             }
867             // Convert OPmemcpy to OPstreq
868             e.Eoper = OPstreq;
869             type *t = type_allocn(TYarray, tstypes[TYchar]);
870             t.Tdim = cast(uint)el_tolong(ex.EV.E2);
871             e.ET = t;
872             t.Tcount++;
873             e.EV.E1 = el_una(OPind,TYstruct,e.EV.E1);
874             e.EV.E2 = el_una(OPind,TYstruct,ex.EV.E1);
875             ex.EV.E1 = null;
876             el_free(ex);
877             ex = el_copytree(e.EV.E1.EV.E1);
878             if (tysize(e.Ety) > tysize(ex.Ety))
879                 ex = el_una(OPnp_fp,e.Ety,ex);
880             e = el_bin(OPcomma,e.Ety,e,ex);
881             if (el_sideeffect(e.EV.E2))
882                 fixside(&e.EV.E1.EV.E1.EV.E1,&e.EV.E2);
883             return optelem(e,GOALvalue);
884         }
885 
886         /+ The following fails the autotester for Linux32 and FreeBSD32
887          + for unknown reasons I cannot reproduce
888         // Convert to memcpy(s1, s2, n)
889         elem* ep = el_params(e.EV.E2.EV.E2, e.EV.E2.EV.E1, e.EV.E1, null);
890         const ty = e.Ety;
891         e.EV.E1 = null;
892         e.EV.E2.EV.E1 = null;
893         e.EV.E2.EV.E2 = null;
894         el_free(e);
895         e = el_bin(OPcall, ty, el_var(getRtlsym(RTLSYM.MEMCPY)), ep);
896          +/
897     }
898     return e;
899 }
900 
901 
902 /***********************
903  *        +             #       (combine offsets with addresses)
904  *       / \    =>      |
905  *      #   c          v,c
906  *      |
907  *      v
908  */
909 
910 @trusted
911 private elem * eladd(elem *e, goal_t goal)
912 {
913     //printf("eladd(%p)\n",e);
914     targ_size_t ptrmask = ~cast(targ_size_t)0;
915     if (_tysize[TYnptr] <= 4)
916         ptrmask = 0xFFFFFFFF;
917 L1:
918     elem *e1 = e.EV.E1;
919     elem *e2 = e.EV.E2;
920     if (e2.Eoper == OPconst)
921     {
922         if (e1.Eoper == OPrelconst && e1.EV.Vsym.Sfl == FLgot)
923             return e;
924         if (e1.Eoper == OPrelconst ||          // if (&v) + c
925             e1.Eoper == OPstring)
926         {
927             e1.EV.Voffset += e2.EV.Vpointer;
928             e1.EV.Voffset &= ptrmask;
929             e = el_selecte1(e);
930             return e;
931         }
932     }
933     else if (e1.Eoper == OPconst)
934     {
935         if (e2.Eoper == OPrelconst && e2.EV.Vsym.Sfl == FLgot)
936             return e;
937         if (e2.Eoper == OPrelconst ||          // if c + (&v)
938             e2.Eoper == OPstring)
939         {
940             e2.EV.Voffset += e1.EV.Vpointer;
941             e2.EV.Voffset &= ptrmask;
942             e = el_selecte2(e);
943             return e;
944         }
945     }
946 
947     if (!OPTIMIZER)
948         return e;
949 
950     // Replace ((e + &v) + c) with (e + (&v+c))
951     if (e2.Eoper == OPconst && e1.Eoper == OPadd &&
952        (e1.EV.E2.Eoper == OPrelconst || e1.EV.E2.Eoper == OPstring))
953     {
954         e1.EV.E2.EV.Voffset += e2.EV.Vpointer;
955         e1.EV.E2.EV.Voffset &= ptrmask;
956         e = el_selecte1(e);
957         goto L1;
958     }
959     // Replace ((e + c) + &v) with (e + (&v+c))
960     else if ((e2.Eoper == OPrelconst || e2.Eoper == OPstring) &&
961              e1.Eoper == OPadd && cnst(e1.EV.E2))
962     {
963         e2.EV.Voffset += e1.EV.E2.EV.Vpointer;
964         e2.EV.Voffset &= ptrmask;
965         e.EV.E1 = el_selecte1(e1);
966         goto L1;                        /* try and find some more       */
967     }
968     // Replace (e1 + -e) with (e1 - e)
969     else if (e2.Eoper == OPneg)
970     {
971         e.EV.E2 = el_selecte1(e2);
972         e.Eoper = OPmin;
973         again = 1;
974         return e;
975     }
976     // Replace (-v + e) with (e + -v)
977     else if (e1.Eoper == OPneg && OTleaf(e1.EV.E1.Eoper))
978     {
979         e.EV.E1 = e2;
980         e.EV.E2 = e1;                     /* swap leaves                  */
981         goto L1;
982     }
983     /* Replace ((e - e2) + e2) with (e)
984      * The optimizer sometimes generates this case
985      */
986     else if (!tyfloating(e.Ety) &&       /* no floating bugs             */
987         e1.Eoper == OPmin &&
988         el_match(e1.EV.E2,e2) &&
989         !el_sideeffect(e2))
990     {
991         tym_t tym = e.Ety;
992         e = el_selecte1(el_selecte1(e));
993         e.Ety = tym;                   /* retain original type         */
994         return e;
995     }
996     // Replace ((e - #v+c1) + #v+c2) with ((e - c1) + c2)
997     else if (e2.Eoper == OPrelconst &&
998            e1.Eoper == OPmin &&
999            e1.EV.E2.Eoper == OPrelconst &&
1000            e1.EV.E2.EV.Vsym == e2.EV.Vsym)
1001     {
1002         e2.Eoper = OPconst;
1003         e2.Ety = TYint;
1004         e1.Ety = e1.EV.E1.Ety;
1005         e1.EV.E2.Eoper = OPconst;
1006         e1.EV.E2.Ety = TYint;
1007         {
1008             /* Watch out for pointer types changing, requiring a conversion */
1009             tym_t ety = tybasic(e.Ety);
1010             tym_t e11ty = tybasic(e1.EV.E1.Ety);
1011             if (typtr(ety) && typtr(e11ty) &&
1012                 _tysize[ety] != _tysize[e11ty])
1013             {
1014                 e = el_una((_tysize[ety] > _tysize[e11ty]) ? OPnp_fp : OPoffset,
1015                             e.Ety,e);
1016                 e.EV.E1.Ety = e1.Ety;
1017             }
1018         }
1019         again = 1;
1020         return e;
1021     }
1022     // Replace (e + e) with (e * 2)
1023     else if (el_match(e1,e2) && !el_sideeffect(e1) && !tyfloating(e1.Ety) &&
1024         !tyvector(e1.Ety))      // not all CPUs support XMM multiply
1025     {
1026         e.Eoper = OPmul;
1027         el_free(e2);
1028         e.EV.E2 = el_long(e1.Ety,2);
1029         again = 1;
1030         return e;
1031     }
1032 
1033     // Replace ((e11 + c) + e2) with ((e11 + e2) + c)
1034     if (e1.Eoper == OPadd && e1.EV.E2.Eoper == OPconst &&
1035         (e2.Eoper == OPvar || !OTleaf(e2.Eoper)) &&
1036         tysize(e1.Ety) == tysize(e2.Ety) &&
1037         tysize(e1.EV.E2.Ety) == tysize(e2.Ety))
1038     {
1039         e.EV.E2 = e1.EV.E2;
1040         e1.EV.E2 = e2;
1041         e1.Ety = e.Ety;
1042         return e;
1043     }
1044 
1045     // Replace (~e1 + 1) with (-e1)
1046     if (e1.Eoper == OPcom && e2.Eoper == OPconst && el_tolong(e2) == 1)
1047     {
1048         e = el_selecte1(e);
1049         e.Eoper = OPneg;
1050         e = optelem(e, goal);
1051         return e;
1052     }
1053 
1054     // Replace ((e11 - e12) + e2) with ((e11 + e2) - e12)
1055     // (this should increase the number of LEA possibilities)
1056     int sz = tysize(e.Ety);
1057     if (e1.Eoper == OPmin &&
1058         tysize(e1.Ety) == sz &&
1059         tysize(e2.Ety) == sz &&
1060         tysize(e1.EV.E1.Ety) == sz &&
1061         tysize(e1.EV.E2.Ety) == sz &&
1062         !tyfloating(e.Ety)
1063        )
1064     {
1065         e.Eoper = OPmin;
1066         e.EV.E2 = e1.EV.E2;
1067         e1.EV.E2 = e2;
1068         e1.Eoper = OPadd;
1069     }
1070 
1071     return e;
1072 }
1073 
1074 
1075 /************************
1076  * Multiply (for OPmul && OPmulass)
1077  *      e * (c**2) => e << c    ;replace multiply by power of 2 with shift
1078  */
1079 
1080 @trusted
1081 private elem * elmul(elem *e, goal_t goal)
1082 {
1083     tym_t tym = e.Ety;
1084 
1085     if (OPTIMIZER)
1086     {
1087         // Replace -a*-b with a*b.
1088         // This is valid for all floating point types as well as integers.
1089         if (tyarithmetic(tym) && e.EV.E2.Eoper == OPneg && e.EV.E1.Eoper == OPneg)
1090         {
1091             e.EV.E1 = el_selecte1(e.EV.E1);
1092             e.EV.E2 = el_selecte1(e.EV.E2);
1093         }
1094     }
1095 
1096     elem *e2 = e.EV.E2;
1097     if (e2.Eoper == OPconst)           // try to replace multiplies with shifts
1098     {
1099         if (OPTIMIZER)
1100         {
1101             elem *e1 = e.EV.E1;
1102             uint op1 = e1.Eoper;
1103 
1104             if (tyintegral(tym) &&              // skip floating types
1105                 OTbinary(op1) &&
1106                 e1.EV.E2.Eoper == OPconst
1107                )
1108             {
1109                 /* Attempt to replace ((e + c1) * c2) with (e * c2 + (c1 * c2))
1110                  * because the + can be frequently folded out (merged into an
1111                  * array offset, for example.
1112                  */
1113                 if (op1 == OPadd)
1114                 {
1115                     e.Eoper = OPadd;
1116                     e1.Eoper = OPmul;
1117                     e.EV.E2 = el_bin(OPmul,tym,e1.EV.E2,e2);
1118                     e1.EV.E2 = el_copytree(e2);
1119                     again = 1;
1120                     return e;
1121                 }
1122 
1123                 // ((e << c1) * c2) => e * ((1 << c1) * c2)
1124                 if (op1 == OPshl)
1125                 {
1126                     e2.EV.Vullong *= cast(targ_ullong)1 << el_tolong(e1.EV.E2);
1127                     e1.EV.E2.EV.Vullong = 0;
1128                     again = 1;
1129                     return e;
1130                 }
1131             }
1132 
1133             if (elemisnegone(e2))
1134             {
1135                 e.Eoper = (e.Eoper == OPmul) ? OPneg : OPnegass;
1136                 e.EV.E2 = null;
1137                 el_free(e2);
1138                 return e;
1139             }
1140         }
1141 
1142         if (tyintegral(tym) && !tyvector(tym))
1143         {
1144             int i = ispow2(el_tolong(e2));      // check for power of 2
1145             if (i != -1)                        // if it is a power of 2
1146             {   e2.EV.Vint = i;
1147                 e2.Ety = TYint;
1148                 e.Eoper = (e.Eoper == OPmul)  /* convert to shift left */
1149                         ? OPshl : OPshlass;
1150                 again = 1;
1151                 return e;
1152             }
1153             else if (el_allbits(e2,-1))
1154                 goto Lneg;
1155         }
1156         else if (elemisnegone(e2) && !tycomplex(e.EV.E1.Ety))
1157         {
1158             goto Lneg;
1159         }
1160     }
1161     return e;
1162 
1163 Lneg:
1164     e.Eoper = (e.Eoper == OPmul)      /* convert to negate */
1165             ? OPneg : OPnegass;
1166     el_free(e.EV.E2);
1167     e.EV.E2 = null;
1168     again = 1;
1169     return e;
1170 }
1171 
1172 /************************
1173  * Subtract
1174  *        -               +
1175  *       / \    =>       / \            (propagate minuses)
1176  *      e   c           e   -c
1177  */
1178 
1179 @trusted
1180 private elem * elmin(elem *e, goal_t goal)
1181 {
1182     elem *e2 = e.EV.E2;
1183 
1184     if (OPTIMIZER)
1185     {
1186         tym_t tym = e.Ety;
1187         elem *e1 = e.EV.E1;
1188         if (e2.Eoper == OPrelconst)
1189         {
1190             if (e1.Eoper == OPrelconst && e1.EV.Vsym == e2.EV.Vsym)
1191             {
1192                 e.Eoper = OPconst;
1193                 e.EV.Vllong = e1.EV.Voffset - e2.EV.Voffset;
1194                 el_free(e1);
1195                 el_free(e2);
1196                 return e;
1197             }
1198         }
1199 
1200         // Convert subtraction of long pointers to subtraction of integers
1201         if (tyfv(e2.Ety) && tyfv(e1.Ety))
1202         {
1203             e.EV.E1 = el_una(OP32_16,tym,e1);
1204             e.EV.E2 = el_una(OP32_16,tym,e2);
1205             return optelem(e,GOALvalue);
1206         }
1207 
1208         // Replace (0 - e2) with (-e2)
1209         if (cnst(e1) && !boolres(e1) &&
1210             !(tycomplex(tym) && !tycomplex(e1.Ety) && !tycomplex(e2.Ety)) &&
1211             !tyvector(e1.Ety)
1212            )
1213         {
1214             e.EV.E1 = e2;
1215             e.EV.E2 = null;
1216             e.Eoper = OPneg;
1217             el_free(e1);
1218             return optelem(e,GOALvalue);
1219         }
1220 
1221         // Replace (e - e) with (0)
1222         if (el_match(e1,e2) && !el_sideeffect(e1))
1223         {
1224             el_free(e);
1225             e = el_calloc();
1226             e.Eoper = OPconst;
1227             e.Ety = tym;
1228             return e;
1229         }
1230 
1231         // Replace ((e1 + c) - e2) with ((e1 - e2) + c), but not
1232         // for floating or far or huge pointers!
1233         if (e1.Eoper == OPadd &&
1234             cnst(e1.EV.E2) &&
1235             (tyintegral(tym) ||
1236              tybasic(tym) == TYnptr ||
1237              tybasic(tym) == TYsptr ||
1238              tybasic(tym) == TYfgPtr ||
1239              tybasic(tym) == TYimmutPtr ||
1240              tybasic(tym) == TYrestrictPtr ||
1241              tybasic(tym) == TYsharePtr)
1242            )
1243         {
1244             e.Eoper = OPadd;
1245             e1.Eoper = OPmin;
1246             elem* c = e1.EV.E2;
1247             e1.EV.E2 = e2;
1248             e.EV.E2 = c;
1249             return optelem(e,GOALvalue);
1250         }
1251 
1252         // Replace (e1 + c1) - (e2 + c2) with (e1 - e2) + (c1 - c2), but not
1253         // for floating or far or huge pointers!
1254         if (e1.Eoper == OPadd && e2.Eoper == OPadd &&
1255             cnst(e1.EV.E2) && cnst(e2.EV.E2) &&
1256             (tyintegral(tym) ||
1257              tybasic(tym) == TYnptr ||
1258              tybasic(tym) == TYsptr ||
1259              tybasic(tym) == TYfgPtr ||
1260              tybasic(tym) == TYimmutPtr ||
1261              tybasic(tym) == TYrestrictPtr ||
1262              tybasic(tym) == TYsharePtr)
1263            )
1264         {
1265             e.Eoper = OPadd;
1266             e1.Eoper = OPmin;
1267             e2.Eoper = OPmin;
1268             elem *tmp = e1.EV.E2;
1269             e1.EV.E2 = e2.EV.E1;
1270             e2.EV.E1 = tmp;
1271             return optelem(e,GOALvalue);
1272         }
1273 
1274         // Replace (-e1 - 1) with (~e1)
1275         if (e1.Eoper == OPneg && e2.Eoper == OPconst && tyintegral(tym) && el_tolong(e2) == 1)
1276         {
1277             e = el_selecte1(e);
1278             e.Eoper = OPcom;
1279             e = optelem(e, goal);
1280             return e;
1281         }
1282 
1283         // Replace (-1 - e2) with (~e2)
1284         if (e1.Eoper == OPconst && tyintegral(tym) && !tyvector(tym) && el_tolong(e1) == -1)
1285         {
1286             el_free(e1);
1287             e.EV.E1 = e.EV.E2;
1288             e.EV.E2 = null;
1289             e.Eoper = OPcom;
1290             e = optelem(e, goal);
1291             return e;
1292         }
1293 
1294         /* Replace e1 - (v * c) with e1 + (v * -c)
1295          */
1296         if (e2.Eoper == OPmul &&
1297             e2.EV.E2.Eoper == OPconst)
1298         {
1299             e.Eoper = OPadd;
1300             e2.EV.E2 = el_una(OPneg, e2.EV.E2.Ety, e2.EV.E2);
1301             return optelem(e, goal);
1302         }
1303     }
1304 
1305     if (I16 && tybasic(e2.Ety) == TYhptr && tybasic(e.EV.E1.Ety) == TYhptr)
1306     {   // Convert to _aNahdiff(e1,e2)
1307         __gshared Symbol *hdiff;
1308         if (!hdiff)
1309         {
1310             Symbol *s = symbol_calloc(LARGECODE ? "_aFahdiff" : "_aNahdiff");
1311             s.Stype = tsclib;
1312             s.Sclass = SC.extern_;
1313             s.Sfl = FLfunc;
1314             s.Ssymnum = 0;
1315             s.Sregsaved = mBX|mCX|mSI|mDI|mBP|mES;
1316             hdiff = s;
1317         }
1318         e.Eoper = OPcall;
1319         e.EV.E2 = el_bin(OPparam,TYint,e2,e.EV.E1);
1320         e.EV.E1 = el_var(hdiff);
1321         return e;
1322     }
1323 
1324     /* Disallow the optimization on doubles. The - operator is not
1325      * rearrangable by K+R, and can cause floating point problems if
1326      * converted to an add ((a + 1.0) - 1.0 shouldn't be folded).
1327      */
1328     if (cnst(e2) && !tyfloating(e2.Ety) &&
1329         !tyvector(e2.Ety)) // don't do vectors until we get constant folding for them
1330     {
1331         e.EV.E2 = el_una(OPneg,e2.Ety,e2);
1332         e.Eoper = OPadd;
1333         return optelem(e,GOALvalue);
1334     }
1335     return e;
1336 }
1337 
1338 /*****************************
1339  * OPand,OPor,OPxor
1340  * This should be expanded to include long type stuff.
1341  */
1342 
1343 @trusted
1344 private elem * elbitwise(elem *e, goal_t goal)
1345 {
1346     //printf("elbitwise(e = %p, goal = x%x)\n", e, goal);
1347 
1348     elem *e2 = e.EV.E2;
1349     elem *e1 = e.EV.E1;
1350     const op = e1.Eoper;
1351     uint sz = tysize(e2.Ety);
1352 
1353     if (e2.Eoper == OPconst)
1354     {
1355         switch (sz)
1356         {
1357             case CHARSIZE:
1358                 /* Replace (c & 0xFF) with (c)  */
1359                 if (OPTIMIZER && e2.EV.Vuchar == CHARMASK)
1360                 {
1361                 L1:
1362                     switch (e.Eoper)
1363                     {   case OPand:     /* (c & 0xFF) => (c)    */
1364                             return el_selecte1(e);
1365                         case OPor:      /* (c | 0xFF) => (0xFF) */
1366                             return el_selecte2(e);
1367                         case OPxor:     /* (c ^ 0xFF) => (~c)   */
1368                             return el_una(OPcom,e.Ety,el_selecte1(e));
1369                         default:
1370                             assert(0);
1371                     }
1372                 }
1373                 break;
1374 
1375             case LONGSIZE:
1376             {
1377                 if (!OPTIMIZER)
1378                     break;
1379                 targ_ulong ul = e2.EV.Vulong;
1380 
1381                 if (ul == 0xFFFFFFFF)           /* if e1 & 0xFFFFFFFF   */
1382                     goto L1;
1383                 /* (x >> 16) & 0xFFFF => (cast(uint)x >> 16)       */
1384                 if (ul == 0xFFFF && e.Eoper == OPand && (op == OPshr || op == OPashr) &&
1385                     e1.EV.E2.Eoper == OPconst && el_tolong(e1.EV.E2) == 16)
1386                 {
1387                     elem *e11 = e1.EV.E1;
1388                     e11.Ety = touns(e11.Ety) | (e11.Ety & ~mTYbasic);
1389                     goto L1;
1390                 }
1391 
1392                 /* Replace (L & 0x0000XXXX) with (unslng)((lngsht) & 0xXXXX) */
1393                 if (_tysize[TYint] < LONGSIZE &&
1394                     e.Eoper == OPand &&
1395                     ul <= SHORTMASK)
1396                 {
1397                     tym_t tym = e.Ety;
1398                     e.EV.E1 = el_una(OP32_16,TYushort,e.EV.E1);
1399                     e.EV.E2 = el_una(OP32_16,TYushort,e.EV.E2);
1400                     e.Ety = TYushort;
1401                     e = el_una(OPu16_32,tym,e);
1402                     goto Lopt;
1403                 }
1404 
1405                 // Replace ((s8sht)L & 0xFF) with (u8sht)L
1406                 if (ul == 0xFF && _tysize[TYint] == LONGSIZE && e.Eoper == OPand &&
1407                     (op == OPs8_16 || op == OPu8_16)
1408                    )
1409                 {
1410                     e1.Eoper = OPu8_16;
1411                     e = el_selecte1(e);
1412                     goto Lopt;
1413                 }
1414                 break;
1415             }
1416 
1417             case SHORTSIZE:
1418             {
1419                 targ_short i = e2.EV.Vshort;
1420                 if (i == cast(targ_short)SHORTMASK) // e2 & 0xFFFF
1421                     goto L1;
1422 
1423                 /* (x >> 8) & 0xFF => ((uint short)x >> 8)          */
1424                 if (OPTIMIZER && i == 0xFF && e.Eoper == OPand &&
1425                     (op == OPshr || op == OPashr) && e1.EV.E2.Eoper == OPconst && e1.EV.E2.EV.Vint == 8)
1426                 {
1427                     elem *e11 = e1.EV.E1;
1428                     e11.Ety = touns(e11.Ety) | (e11.Ety & ~mTYbasic);
1429                     goto L1;
1430                 }
1431 
1432                 // (s8_16(e) & 0xFF) => u8_16(e)
1433                 if (OPTIMIZER && op == OPs8_16 && e.Eoper == OPand &&
1434                     i == 0xFF)
1435                 {
1436                     e1.Eoper = OPu8_16;
1437                     e = el_selecte1(e);
1438                     goto Lopt;
1439                 }
1440 
1441                 if (
1442                     /* OK for uint if AND or high bits of i are 0   */
1443                     op == OPu8_16 && (e.Eoper == OPand || !(i & ~0xFF)) ||
1444                     /* OK for signed if i is 'sign-extended'    */
1445                     op == OPs8_16 && cast(targ_short)cast(targ_schar)i == i
1446                    )
1447                 {
1448                     /* Convert ((u8int) e) & i) to (u8int)(e & (int8) i) */
1449                     /* or similar for s8int                              */
1450                     e = el_una(e1.Eoper,e.Ety,e);
1451                     e.EV.E1.Ety = e1.Ety = e1.EV.E1.Ety;
1452                     e.EV.E1.EV.E1 = el_selecte1(e1);
1453                     e.EV.E1.EV.E2 = el_una(OP16_8,e.EV.E1.Ety,e.EV.E1.EV.E2);
1454                     goto Lopt;
1455                 }
1456                 break;
1457             }
1458 
1459             case LLONGSIZE:
1460                 if (OPTIMIZER)
1461                 {
1462                     if (e2.EV.Vullong == LLONGMASK)
1463                         goto L1;
1464                 }
1465                 break;
1466 
1467             default:
1468                 break;
1469         }
1470         if (OPTIMIZER && sz < 16)
1471         {
1472             targ_ullong ul = el_tolong(e2);
1473 
1474             if (e.Eoper == OPor && op == OPand && e1.EV.E2.Eoper == OPconst)
1475             {
1476                 // ((x & c1) | c2) => (x | c2)
1477                 targ_ullong c3;
1478 
1479                 c3 = ul | e1.EV.E2.EV.Vullong;
1480                 switch (sz)
1481                 {
1482                     case CHARSIZE:
1483                         if ((c3 & CHARMASK) == CHARMASK)
1484                             goto L2;
1485                         break;
1486 
1487                     case SHORTSIZE:
1488                         if ((c3 & SHORTMASK) == SHORTMASK)
1489                             goto L2;
1490                         break;
1491 
1492                     case LONGSIZE:
1493                         if ((c3 & LONGMASK) == LONGMASK)
1494                         {
1495                         L2:
1496                             e1.EV.E2.EV.Vullong = c3;
1497                             e.EV.E1 = elbitwise(e1, GOALvalue);
1498                             goto Lopt;
1499                         }
1500                         break;
1501 
1502                     case LLONGSIZE:
1503                         if ((c3 & LLONGMASK) == LLONGMASK)
1504                             goto L2;
1505                         break;
1506 
1507                     default:
1508                         assert(0);
1509                 }
1510             }
1511 
1512             if (op == OPs16_32 && (ul & 0xFFFFFFFFFFFF8000L) == 0 ||
1513                 op == OPu16_32 && (ul & 0xFFFFFFFFFFFF0000L) == 0 ||
1514                 op == OPs8_16  && (ul & 0xFFFFFFFFFFFFFF80L) == 0 ||
1515                 op == OPu8_16  && (ul & 0xFFFFFFFFFFFFFF00L) == 0 ||
1516                 op == OPs32_64 && (ul & 0xFFFFFFFF80000000L) == 0 ||
1517                 op == OPu32_64 && (ul & 0xFFFFFFFF00000000L) == 0
1518                )
1519             {
1520                 if (e.Eoper == OPand)
1521                 {
1522                     if (op == OPs16_32 && (ul & 0x8000) == 0)
1523                         e1.Eoper = OPu16_32;
1524                     else if (op == OPs8_16  && (ul & 0x80) == 0)
1525                         e1.Eoper = OPu8_16;
1526                     else if (op == OPs32_64 && (ul & 0x80000000) == 0)
1527                         e1.Eoper = OPu32_64;
1528                 }
1529 
1530                 // ((shtlng)s & c) => ((shtlng)(s & c)
1531                 e1.Ety = e.Ety;
1532                 e.Ety = e2.Ety = e1.EV.E1.Ety;
1533                 e.EV.E1 = e1.EV.E1;
1534                 e1.EV.E1 = e;
1535                 e = e1;
1536                 goto Lopt;
1537             }
1538 
1539             // Replace (((a & b) ^ c) & d) with ((a ^ c) & e), where
1540             // e is (b&d).
1541             if (e.Eoper == OPand && op == OPxor && e1.EV.E1.Eoper == OPand &&
1542                 e1.EV.E1.EV.E2.Eoper == OPconst)
1543             {
1544                 e2.EV.Vullong &= e1.EV.E1.EV.E2.EV.Vullong;
1545                 e1.EV.E1 = el_selecte1(e1.EV.E1);
1546                 goto Lopt;
1547             }
1548 
1549             // Replace ((a >> b) & 1) with (a btst b)
1550             if ((I32 || I64) &&
1551                 e.Eoper == OPand &&
1552                 ul == 1 &&
1553                 (e.EV.E1.Eoper == OPshr || e.EV.E1.Eoper == OPashr) &&
1554                 sz <= REGSIZE &&
1555                 tysize(e1.Ety) >= 2     // BT doesn't work on byte operands
1556                )
1557             {
1558                 e.EV.E1.Eoper = OPbtst;
1559                 e = el_selecte1(e);
1560                 goto Lopt;
1561             }
1562         }
1563     }
1564 
1565     if (OPTIMIZER && goal & GOALflags && (I32 || I64) && e.Eoper == OPand &&
1566         (sz == 4 || sz == 8))
1567     {
1568         /* These should all compile to a BT instruction when -O, for -m32 and -m64
1569          * int bt32(uint *p, uint b) { return ((p[b >> 5] & (1 << (b & 0x1F)))) != 0; }
1570          * int bt64a(ulong *p, uint b) { return ((p[b >> 6] & (1L << (b & 63)))) != 0; }
1571          * int bt64b(ulong *p, size_t b) { return ((p[b >> 6] & (1L << (b & 63)))) != 0; }
1572          */
1573 
1574         static bool ELCONST(elem* e, long c) { return e.Eoper == OPconst && el_tolong(e) == c; }
1575         int pow2sz = ispow2(sz);
1576 
1577         if (e1.Eoper == OPind)
1578         {   // Swap e1 and e2 so that e1 is the mask and e2 is the memory location
1579             e2 = e1;
1580             e1 = e.EV.E2;
1581         }
1582 
1583         /* Replace:
1584          *  ((1 << (b & 31))   &   *(((b >>> 5) << 2) + p)
1585          * with:
1586          *  p bt b
1587          */
1588         elem *e12;              // the (b & 31), which may be preceded by (64_32)
1589         elem *e2111;            // the (b >>> 5), which may be preceded by (u32_64)
1590         if (e1.Eoper == OPshl &&
1591             ELCONST(e1.EV.E1,1) &&
1592             (((e12 = e1.EV.E2).Eoper == OP64_32 ? (e12 = e12.EV.E1) : e12).Eoper == OPand) &&
1593             ELCONST(e12.EV.E2,sz * 8 - 1) &&
1594             tysize(e12.Ety) <= sz &&
1595 
1596             e2.Eoper == OPind &&
1597             e2.EV.E1.Eoper == OPadd &&
1598             e2.EV.E1.EV.E1.Eoper == OPshl &&
1599             ELCONST(e2.EV.E1.EV.E1.EV.E2,pow2sz) &&
1600             (((e2111 = e2.EV.E1.EV.E1.EV.E1).Eoper == OPu32_64 ? (e2111 = e2111.EV.E1) : e2111).Eoper == OPshr) &&
1601             ELCONST(e2111.EV.E2,pow2sz + 3)
1602            )
1603         {
1604             elem **pb1 = &e12.EV.E1;
1605             elem **pb2 = &e2111.EV.E1;
1606             elem **pp  = &e2.EV.E1.EV.E2;
1607 
1608             if (el_match(*pb1, *pb2) &&
1609                 !el_sideeffect(*pb1))
1610             {
1611                 e.Eoper = OPbt;
1612                 e.EV.E1 = *pp;            // p
1613                 *pp = null;
1614                 e.EV.E2 = *pb1;           // b
1615                 *pb1 = null;
1616                 *pb2 = null;
1617                 el_free(e1);
1618                 el_free(e2);
1619                 return optelem(e,goal);
1620             }
1621         }
1622 
1623         /* Replace:
1624          *  (1 << a) & b
1625          * with:
1626          *  b btst a
1627          */
1628         if (e1.Eoper == OPshl &&
1629             ELCONST(e1.EV.E1,1) &&
1630             tysize(e.EV.E1.Ety) <= REGSIZE)
1631         {
1632             const int sz1 = tysize(e.EV.E1.Ety);
1633             e.Eoper = OPbtst;
1634             e.Ety = TYbool;
1635             e.EV.E1 = e2;
1636             e.EV.E2 = e1.EV.E2;
1637             //e.EV.E2.Ety = e.EV.E1.Ety; // leave type as int
1638             e1.EV.E2 = null;
1639             el_free(e1);
1640 
1641             if (sz1 >= 2)
1642                 e = el_una(OPu8_16, TYushort, e);
1643             if (sz1 >= 4)
1644                 e = el_una(OPu16_32, TYulong, e);
1645             if (sz1 >= 8)
1646                 e = el_una(OPu32_64, TYullong, e);
1647 
1648             return optelem(e, goal);
1649         }
1650     }
1651 
1652     return e;
1653 
1654 Lopt:
1655     debug
1656     {
1657         __gshared int nest;
1658         nest++;
1659         if (nest > 100)
1660         {   elem_print(e);
1661             assert(0);
1662         }
1663         e = optelem(e,GOALvalue);
1664         nest--;
1665         return e;
1666     }
1667     else
1668         return optelem(e,GOALvalue);
1669 }
1670 
1671 /***************************************
1672  * Fill in ops[] with operands of repeated operator oper.
1673  * Returns:
1674  *      true    didn't fail
1675  *      false   more than ops.length operands
1676  */
1677 
1678 @trusted
1679 private
1680 bool fillinops(elem*[] ops, ref size_t opsi, OPER oper, elem* e)
1681 {
1682     if (e.Eoper == oper)
1683     {
1684         if (!fillinops(ops, opsi, oper, e.EV.E1) ||
1685             !fillinops(ops, opsi, oper, e.EV.E2))
1686             return false;
1687     }
1688     else
1689     {
1690         if (opsi >= ops.length)
1691             return false;       // error, too many
1692         ops[opsi] = e;
1693         opsi += 1;
1694     }
1695     return true;
1696 }
1697 
1698 
1699 /*************************************
1700  * Replace shift|shift with rotate.
1701  */
1702 
1703 @trusted
1704 private elem *elor(elem *e, goal_t goal)
1705 {
1706     //printf("elor()\n");
1707     /* ROL:     (a << shift) | (a >> (sizeof(a) * 8 - shift))
1708      * ROR:     (a >> shift) | (a << (sizeof(a) * 8 - shift))
1709      */
1710     elem *e1 = e.EV.E1;
1711     elem *e2 = e.EV.E2;
1712     uint sz = tysize(e.Ety);
1713     if (sz <= REGSIZE)
1714     {
1715         if (e1.Eoper == OPshl && e2.Eoper == OPshr &&
1716             tyuns(e2.EV.E1.Ety) && e2.EV.E2.Eoper == OPmin &&
1717             e2.EV.E2.EV.E1.Eoper == OPconst &&
1718             el_tolong(e2.EV.E2.EV.E1) == sz * 8 &&
1719             el_match5(e1.EV.E1, e2.EV.E1) &&
1720             el_match5(e1.EV.E2, e2.EV.E2.EV.E2) &&
1721             !el_sideeffect(e)
1722            )
1723         {
1724             e1.Eoper = OProl;
1725             return el_selecte1(e);
1726         }
1727         if (e1.Eoper == OPshr && e2.Eoper == OPshl &&
1728             tyuns(e1.EV.E1.Ety) && e2.EV.E2.Eoper == OPmin &&
1729             e2.EV.E2.EV.E1.Eoper == OPconst &&
1730             el_tolong(e2.EV.E2.EV.E1) == sz * 8 &&
1731             el_match5(e1.EV.E1, e2.EV.E1) &&
1732             el_match5(e1.EV.E2, e2.EV.E2.EV.E2) &&
1733             !el_sideeffect(e)
1734            )
1735         {
1736             e1.Eoper = OPror;
1737             return el_selecte1(e);
1738         }
1739         // rotate left by a constant
1740         if (e1.Eoper == OPshl && e2.Eoper == OPshr &&
1741             tyuns(e2.EV.E1.Ety) &&
1742             e1.EV.E2.Eoper == OPconst &&
1743             e2.EV.E2.Eoper == OPconst &&
1744             el_tolong(e2.EV.E2) == sz * 8 - el_tolong(e1.EV.E2) &&
1745             el_match5(e1.EV.E1, e2.EV.E1) &&
1746             !el_sideeffect(e)
1747            )
1748         {
1749             e1.Eoper = OProl;
1750             return el_selecte1(e);
1751         }
1752         // rotate right by a constant
1753         if (e1.Eoper == OPshr && e2.Eoper == OPshl &&
1754             tyuns(e2.EV.E1.Ety) &&
1755             e1.EV.E2.Eoper == OPconst &&
1756             e2.EV.E2.Eoper == OPconst &&
1757             el_tolong(e2.EV.E2) == sz * 8 - el_tolong(e1.EV.E2) &&
1758             el_match5(e1.EV.E1, e2.EV.E1) &&
1759             !el_sideeffect(e)
1760            )
1761         {
1762             e1.Eoper = OPror;
1763             return el_selecte1(e);
1764         }
1765     }
1766 
1767     /* Recognize the following function and replace it with OPbswap:
1768         ushort byteswap(ushort x) { return cast(ushort)(((x >> 8) & 0xFF) | ((x << 8) & 0xFF00)); }
1769 
1770          |  TYunsigned short
1771           &  TYshort
1772            32_16  TYshort
1773             >>  TYint
1774              u16_32  TYint
1775               var  TYunsigned short  x
1776              const  TYint 8L
1777            const  TYshort 255
1778           &  TYshort
1779            <<  TYshort
1780             var  TYshort  x
1781             const  TYshort 8
1782            const  TYshort 0xFF00
1783      */
1784     if (sz == 2 && OPTIMIZER)
1785     {
1786         if (e.Eoper == OPor &&
1787             e1.Eoper == OPand &&
1788             e2.Eoper == OPand)
1789         {
1790             elem* evar;
1791             elem* evar2;
1792             auto e11 = e1.EV.E1;
1793             auto e12 = e1.EV.E2;
1794             if (e11.Eoper == OP32_16 &&
1795                 e12.Eoper == OPconst && el_tolong(e12) == 0xFF)
1796             {
1797                 auto e111 = e11.EV.E1;
1798                 if (e111.Eoper == OPshr || e111.Eoper == OPashr)
1799                 {
1800                     auto e1111 = e111.EV.E1;
1801                     auto e1112 = e111.EV.E2;
1802                     if (e1112.Eoper == OPconst && el_tolong(e1112) == 8 &&
1803                         e1111.Eoper == OPu16_32)
1804                         evar = e1111.EV.E1;
1805                 }
1806             }
1807 
1808             if (evar)
1809             {
1810                 auto e22 = e2.EV.E2;
1811                 if (e22.Eoper == OPconst && el_tolong(e22) == 0xFF00)
1812                 {
1813                     auto e21 = e2.EV.E1;
1814                     if (e21.Eoper == OPshl)
1815                     {
1816                         auto e211 = e21.EV.E1;
1817                         auto e212 = e21.EV.E2;
1818                         if (e212.Eoper == OPconst && el_tolong(e212) == 8)
1819                         {
1820                             if (el_match5(evar, e211) && !el_sideeffect(e211))
1821                             {
1822                                 evar2 = e211;
1823                                 e21.EV.E1 = null;
1824                             }
1825                         }
1826                     }
1827                 }
1828             }
1829 
1830             if (evar2)
1831             {
1832                 el_free(e1);
1833                 el_free(e2);
1834                 e.Eoper = OPbswap;
1835                 e.EV.E1 = evar2;
1836                 e.EV.E2 = null;
1837                 //printf("Matched byteswap(ushort)\n");
1838                 return e;
1839             }
1840         }
1841     }
1842 
1843     /* BSWAP: (data[0]<< 24) | (data[1]<< 16) | (data[2]<< 8) | (data[3]<< 0)
1844      */
1845     if (sz == 4 && OPTIMIZER)
1846     {
1847         elem*[4] ops = void;
1848         size_t opsi = 0;
1849         if (fillinops(ops, opsi, OPor, e) && opsi == ops.length)
1850         {
1851             elem *ex = null;
1852             uint bmask = 0;
1853             foreach (eo; ops)
1854             {
1855                 elem *eo2;
1856                 int shift;
1857                 elem *eo111;
1858                 if (eo.Eoper == OPu8_16 &&
1859                     eo.EV.E1.Eoper == OPind)
1860                 {
1861                     eo111 = eo.EV.E1.EV.E1;
1862                     shift = 0;
1863                 }
1864                 else if (eo.Eoper == OPshl &&
1865                     eo.EV.E1.Eoper == OPu8_16 &&
1866                     (eo2 = eo.EV.E2).Eoper == OPconst &&
1867                     eo.EV.E1.EV.E1.Eoper == OPind)
1868                 {
1869                     shift = cast(int)el_tolong(eo2);
1870                     switch (shift)
1871                     {
1872                         case 8:
1873                         case 16:
1874                         case 24:
1875                             break;
1876 
1877                         default:
1878                             goto L1;
1879                     }
1880                     eo111 = eo.EV.E1.EV.E1.EV.E1;
1881                 }
1882                 else
1883                     goto L1;
1884 
1885                 uint off;
1886                 elem *ed;
1887                 if (eo111.Eoper == OPadd)
1888                 {
1889                     ed = eo111.EV.E1;
1890                     if (eo111.EV.E2.Eoper != OPconst)
1891                         goto L1;
1892                     off = cast(uint)el_tolong(eo111.EV.E2);
1893                     if (off < 1 || off > 3)
1894                         goto L1;
1895                 }
1896                 else
1897                 {
1898                     ed = eo111;
1899                     off = 0;
1900                 }
1901                 switch ((off << 5) | shift)
1902                 {
1903                     // BSWAP
1904                     case (0 << 5) | 24: bmask |= 1; break;
1905                     case (1 << 5) | 16: bmask |= 2; break;
1906                     case (2 << 5) |  8: bmask |= 4; break;
1907                     case (3 << 5) |  0: bmask |= 8; break;
1908 
1909                     // No swap
1910                     case (0 << 5) |  0: bmask |= 0x10; break;
1911                     case (1 << 5) |  8: bmask |= 0x20; break;
1912                     case (2 << 5) | 16: bmask |= 0x40; break;
1913                     case (3 << 5) | 24: bmask |= 0x80; break;
1914 
1915                     default:
1916                         goto L1;
1917                 }
1918                 if (ex)
1919                 {
1920                     if (!el_match(ex, ed))
1921                         goto L1;
1922                 }
1923                 else
1924                 {   if (el_sideeffect(ed))
1925                         goto L1;
1926                     ex = ed;
1927                 }
1928             }
1929             /* Got a match, build:
1930              *   BSWAP(*ex)
1931              */
1932             if (bmask == 0x0F)
1933                 e = el_una(OPbswap, e.Ety, el_una(OPind, e.Ety, ex));
1934             else if (bmask == 0xF0)
1935                 e = el_una(OPind, e.Ety, ex);
1936             else
1937                 goto L1;
1938             return e;
1939         }
1940     }
1941   L1:
1942 
1943     return elbitwise(e, goal);
1944 }
1945 
1946 /*************************************
1947  */
1948 
1949 @trusted
1950 private elem *elxor(elem *e, goal_t goal)
1951 {
1952     if (OPTIMIZER)
1953     {
1954         elem *e1 = e.EV.E1;
1955         elem *e2 = e.EV.E2;
1956 
1957         /* Recognize:
1958          *    (a & c) ^ (b & c)  =>  (a ^ b) & c
1959          */
1960         if (e1.Eoper == OPand && e2.Eoper == OPand &&
1961             el_match5(e1.EV.E2, e2.EV.E2) &&
1962             (e2.EV.E2.Eoper == OPconst || (!el_sideeffect(e2.EV.E1) && !el_sideeffect(e2.EV.E2))))
1963         {
1964             el_free(e1.EV.E2);
1965             e1.EV.E2 = e2.EV.E1;
1966             e1.Eoper = OPxor;
1967             e.Eoper = OPand;
1968             e.EV.E2 = e2.EV.E2;
1969             e2.EV.E1 = null;
1970             e2.EV.E2 = null;
1971             el_free(e2);
1972             return optelem(e, GOALvalue);
1973         }
1974     }
1975     return elbitwise(e, goal);
1976 }
1977 
1978 /**************************
1979  * Optimize nots.
1980  *      ! ! e => bool e
1981  *      ! bool e => ! e
1982  *      ! OTrel => !OTrel       (invert the condition)
1983  *      ! OTconv => !
1984  */
1985 
1986 @trusted
1987 private elem * elnot(elem *e, goal_t goal)
1988 {
1989     elem *e1 = e.EV.E1;
1990     const op = e1.Eoper;
1991     switch (op)
1992     {
1993         case OPnot:                     // ! ! e => bool e
1994         case OPbool:                    // ! bool e => ! e
1995             e1.Eoper = cast(ubyte)(op ^ (OPbool ^ OPnot));
1996             /* That was a clever substitute for the following:  */
1997             /* e.Eoper = (op == OPnot) ? OPbool : OPnot;               */
1998             e = optelem(el_selecte1(e), goal);
1999             break;
2000 
2001         default:
2002             if (OTrel(op))                      /* ! OTrel => !OTrel            */
2003             {
2004                   /* Find the logical negation of the operator  */
2005                   auto op2 = rel_not(op);
2006                   if (!tyfloating(e1.EV.E1.Ety))
2007                   {   op2 = rel_integral(op2);
2008                       assert(OTrel(op2));
2009                   }
2010                   e1.Eoper = cast(ubyte)op2;
2011                   e = optelem(el_selecte1(e), goal);
2012             }
2013             else if (tybasic(e1.Ety) == TYbool && tysize(e.Ety) == 1)
2014             {
2015                 // !e1 => (e1 ^ 1)
2016                 e.Eoper = OPxor;
2017                 e.EV.E2 = el_long(e1.Ety,1);
2018                 e = optelem(e, goal);
2019             }
2020             else
2021             {
2022                 static if (0)
2023                 {
2024                     // Can't use this because what if OPd_s32?
2025                     // Note: !(long)(.1) != !(.1)
2026                     if (OTconv(op))             // don't use case because of differ target
2027                     {   // conversion operators
2028                         e1.Eoper = e.Eoper;
2029                         e = optelem(el_selecte1(e), goal);
2030                         break;
2031                     }
2032                 }
2033             }
2034             break;
2035 
2036         case OPs32_d:
2037         case OPs16_d:
2038         case OPu16_d:
2039         case OPu32_d:
2040         case OPf_d:
2041         case OPd_ld:
2042         case OPs16_32:
2043         case OPu16_32:
2044         case OPu8_16:
2045         case OPs8_16:
2046         case OPu32_64:
2047         case OPs32_64:
2048         case OPvp_fp:
2049         case OPcvp_fp:
2050         case OPnp_fp:
2051             e1.Eoper = e.Eoper;
2052             e = optelem(el_selecte1(e), goal);
2053             break;
2054     }
2055     return e;
2056 }
2057 
2058 /*************************
2059  * Complement
2060  *      ~ ~ e => e
2061  */
2062 
2063 @trusted
2064 private elem * elcom(elem *e, goal_t goal)
2065 {
2066     elem *e1 = e.EV.E1;
2067     if (e1.Eoper == OPcom)                       // ~ ~ e => e
2068         // Typing problem here
2069         e = el_selecte1(el_selecte1(e));
2070     return e;
2071 }
2072 
2073 /*************************
2074  * If it is a conditional of a constant
2075  * then we know which exp to evaluate.
2076  * BUG:
2077  *      doesn't detect ("string" ? et : ef)
2078  */
2079 
2080 @trusted
2081 private elem * elcond(elem *e, goal_t goal)
2082 {
2083     //printf("elcond() goal = %d\n", goal);
2084     //elem_print(e);
2085     elem *e1 = e.EV.E1;
2086     switch (e1.Eoper)
2087     {
2088         case OPconst:
2089             if (boolres(e1))
2090             L1:
2091                 e = el_selecte1(el_selecte2(e));
2092             else
2093                 e = el_selecte2(el_selecte2(e));
2094             break;
2095 
2096         case OPrelconst:
2097         case OPstring:
2098             goto L1;
2099 
2100         case OPcomma:
2101             // ((a,b) ? c) => (a,(b ? c))
2102             e.Eoper = OPcomma;
2103             e.EV.E1 = e1.EV.E1;
2104             e1.EV.E1 = e1.EV.E2;
2105             e1.EV.E2 = e.EV.E2;
2106             e.EV.E2 = e1;
2107             e1.Eoper = OPcond;
2108             e1.Ety = e.Ety;
2109             return optelem(e,GOALvalue);
2110 
2111         case OPnot:
2112         {
2113             // (!a ? b : c) => (a ? c : b)
2114             elem *ex = e.EV.E2.EV.E1;
2115             e.EV.E2.EV.E1 = e.EV.E2.EV.E2;
2116             e.EV.E2.EV.E2 = ex;
2117             goto L2;
2118         }
2119 
2120         default:
2121             if (OTboolnop(e1.Eoper))
2122             {
2123         L2:
2124                 e.EV.E1 = e1.EV.E1;
2125                 e1.EV.E1 = null;
2126                 el_free(e1);
2127                 return elcond(e,goal);
2128             }
2129             if (!OPTIMIZER)
2130                 break;
2131 
2132         {
2133             tym_t ty = e.Ety;
2134             elem *ec1 = e.EV.E2.EV.E1;
2135             elem *ec2 = e.EV.E2.EV.E2;
2136 
2137             if (tyintegral(ty) && ec1.Eoper == OPconst && ec2.Eoper == OPconst)
2138             {
2139                 targ_llong i1 = el_tolong(ec1);
2140                 targ_llong i2 = el_tolong(ec2);
2141                 tym_t ty1 = tybasic(e1.Ety);
2142 
2143                 if ((ty1 == TYbool && !OTlogical(e1.Eoper) || e1.Eoper == OPand && e1.EV.E2.Eoper == OPconst) &&
2144                     tysize(ty) == tysize(ec1.Ety))
2145                 {
2146                     targ_llong b = ty1 == TYbool ? 1 : el_tolong(e1.EV.E2);
2147 
2148                     if (b == 1 && ispow2(i1 - i2) != -1)
2149                     {
2150                         // replace (e1 ? i1 : i2) with (i1 + (e1 ^ 1) * (i2 - i1))
2151                         // replace (e1 ? i2 : i1) with (i1 + e1 * (i2 - i1))
2152                         int sz = tysize(e1.Ety);
2153                         while (sz < tysize(ec1.Ety))
2154                         {
2155                             // Increase the size of e1 until it matches the size of ec1
2156                             switch (sz)
2157                             {
2158                                 case 1:
2159                                     e1 = el_una(OPu8_16, TYushort, e1);
2160                                     sz = 2;
2161                                     break;
2162                                 case 2:
2163                                     e1 = el_una(OPu16_32, TYulong, e1);
2164                                     sz = 4;
2165                                     break;
2166                                 case 4:
2167                                     e1 = el_una(OPu32_64, TYullong, e1);
2168                                     sz = 8;
2169                                     break;
2170                                 default:
2171                                     assert(0);
2172                             }
2173                         }
2174                         if (i1 < i2)
2175                         {
2176                             ec2.EV.Vllong = i2 - i1;
2177                             e1 = el_bin(OPxor,e1.Ety,e1,el_long(e1.Ety,1));
2178                         }
2179                         else
2180                         {
2181                             ec1.EV.Vllong = i2;
2182                             ec2.EV.Vllong = i1 - i2;
2183                         }
2184                         e.EV.E1 = ec1;
2185                         e.EV.E2.Eoper = OPmul;
2186                         e.EV.E2.Ety = ty;
2187                         e.EV.E2.EV.E1 = e1;
2188                         e.Eoper = OPadd;
2189                         return optelem(e,GOALvalue);
2190                     }
2191 
2192                     /* If b is an integer with only 1 bit set then
2193                      *   replace ((a & b) ? b : 0) with (a & b)
2194                      *   replace ((a & b) ? 0 : b) with ((a & b) ^ b)
2195                      */
2196                     if (e1.Eoper == OPand && e1.EV.E2.Eoper == OPconst && ispow2(b) != -1) // if only 1 bit is set
2197                     {
2198                         if (b == i1 && i2 == 0)
2199                         {   e = el_selecte1(e);
2200                             e.EV.E1.Ety = ty;
2201                             e.EV.E2.Ety = ty;
2202                             e.EV.E2.EV.Vllong = b;
2203                             return optelem(e,GOALvalue);
2204                         }
2205                         else if (i1 == 0 && b == i2)
2206                         {
2207                             e1.Ety = ty;
2208                             e1.EV.E1.Ety = ty;
2209                             e1.EV.E2.Ety = ty;
2210                             e1.EV.E2.EV.Vllong = b;
2211                             e.EV.E1 = el_bin(OPxor,ty,e1,el_long(ty,b));
2212                             e = el_selecte1(e);
2213                             return optelem(e,GOALvalue);
2214                         }
2215                     }
2216                 }
2217 
2218                 /* Replace ((a relop b) ? 1 : 0) with (a relop b)       */
2219                 else if (OTrel(e1.Eoper) &&
2220                     tysize(ty) <= tysize(TYint))
2221                 {
2222                     if (i1 == 1 && i2 == 0)
2223                         e = el_selecte1(e);
2224                     else if (i1 == 0 && i2 == 1)
2225                     {
2226                         e.EV.E1 = el_una(OPnot,ty,e1);
2227                         e = optelem(el_selecte1(e),GOALvalue);
2228                     }
2229                 }
2230 
2231                 // The next two optimizations attempt to replace with an
2232                 // uint compare, which the code generator can generate
2233                 // code for without using jumps.
2234 
2235                 // Try to replace (!e1) with (e1 < 1)
2236                 else if (e1.Eoper == OPnot && !OTrel(e1.EV.E1.Eoper) && e1.EV.E1.Eoper != OPand)
2237                 {
2238                     e.EV.E1 = el_bin(OPlt,TYint,e1.EV.E1,el_long(touns(e1.EV.E1.Ety),1));
2239                     e1.EV.E1 = null;
2240                     el_free(e1);
2241                 }
2242                 // Try to replace (e1) with (e1 >= 1)
2243                 else if (!OTrel(e1.Eoper) && e1.Eoper != OPand)
2244                 {
2245                     if (tyfv(e1.Ety))
2246                     {
2247                         if (tysize(e.Ety) == tysize(TYint))
2248                         {
2249                             if (i1 == 1 && i2 == 0)
2250                             {   e.Eoper = OPbool;
2251                                 el_free(e.EV.E2);
2252                                 e.EV.E2 = null;
2253                             }
2254                             else if (i1 == 0 && i2 == 1)
2255                             {   e.Eoper = OPnot;
2256                                 el_free(e.EV.E2);
2257                                 e.EV.E2 = null;
2258                             }
2259                         }
2260                     }
2261                     else if(tyintegral(e1.Ety))
2262                         e.EV.E1 = el_bin(OPge,TYint,e1,el_long(touns(e1.Ety),1));
2263                 }
2264             }
2265 
2266             // Try to detect absolute value expression
2267             // (a < 0) -a : a
2268             else if ((e1.Eoper == OPlt || e1.Eoper == OPle) &&
2269                 e1.EV.E2.Eoper == OPconst &&
2270                 !boolres(e1.EV.E2) &&
2271                 !tyuns(e1.EV.E1.Ety) &&
2272                 !tyuns(e1.EV.E2.Ety) &&
2273                 ec1.Eoper == OPneg &&
2274                 !el_sideeffect(ec2) &&
2275                 el_match(e.EV.E1.EV.E1,ec2) &&
2276                 el_match(ec1.EV.E1,ec2) &&
2277                 tysize(ty) >= _tysize[TYint]
2278                )
2279             {   e.EV.E2.EV.E2 = null;
2280                 el_free(e);
2281                 e = el_una(OPabs,ty,ec2);
2282             }
2283             // (a >= 0) a : -a
2284             else if ((e1.Eoper == OPge || e1.Eoper == OPgt) &&
2285                 e1.EV.E2.Eoper == OPconst &&
2286                 !boolres(e1.EV.E2) &&
2287                 !tyuns(e1.EV.E1.Ety) &&
2288                 !tyuns(e1.EV.E2.Ety) &&
2289                 ec2.Eoper == OPneg &&
2290                 !el_sideeffect(ec1) &&
2291                 el_match(e.EV.E1.EV.E1,ec1) &&
2292                 el_match(ec2.EV.E1,ec1) &&
2293                 tysize(ty) >= _tysize[TYint]
2294                )
2295             {   e.EV.E2.EV.E1 = null;
2296                 el_free(e);
2297                 e = el_una(OPabs,ty,ec1);
2298             }
2299 
2300             /* Replace:
2301              *    a ? noreturn : c
2302              * with:
2303              *    (a && noreturn), c
2304              * because that means fewer noreturn cases for the data flow analysis to deal with
2305              */
2306             else if (!el_returns(ec1))
2307             {
2308                 e.Eoper = OPcomma;
2309                 e.EV.E1 = e.EV.E2;
2310                 e.EV.E2 = ec2;
2311                 e.EV.E1.Eoper = OPandand;
2312                 e.EV.E1.Ety = TYvoid;
2313                 e.EV.E1.EV.E2 = ec1;
2314                 e.EV.E1.EV.E1 = e1;
2315             }
2316 
2317             /* Replace:
2318              *    a ? b : noreturn
2319              * with:
2320              *    (a || noreturn), b
2321              */
2322             else if (!el_returns(ec2))
2323             {
2324                 e.Eoper = OPcomma;
2325                 e.EV.E1 = e.EV.E2;
2326                 e.EV.E2 = ec1;
2327                 e.EV.E1.Eoper = OPoror;
2328                 e.EV.E1.Ety = TYvoid;
2329                 e.EV.E1.EV.E2 = ec2;
2330                 e.EV.E1.EV.E1 = e1;
2331             }
2332 
2333             /* Replace:
2334              *   *p op e ? p : false
2335              * with:
2336              *   bool
2337              */
2338             else if (goal == GOALflags &&
2339                 ec2.Eoper == OPconst && !boolres(ec2) &&
2340                 typtr(ec1.Ety) &&
2341                 ec1.Eoper == OPvar &&
2342                 OTbinary(e1.Eoper) &&
2343                 !OTsideff(e1.Eoper) &&
2344                 e1.EV.E1.Eoper == OPind &&
2345                 el_match(findPointer(e1.EV.E1.EV.E1), ec1) &&
2346                 !el_sideeffect(e))
2347             {
2348                 /* NOTE: should optimize other cases of this
2349                  */
2350                 el_free(e.EV.E2);
2351                 e.EV.E2 = null;
2352                 e.Eoper = OPbool;
2353                 e.Ety = TYint;
2354             }
2355             break;
2356         }
2357     }
2358     return e;
2359 }
2360 
2361 /******************************
2362  * Given an elem that is the operand to OPind,
2363  * find the expression representing the pointer.
2364  * Params:
2365  *      e = operand to OPind
2366  * Returns:
2367  *      expression that represents the pointer
2368  */
2369 @trusted
2370 private elem* findPointer(elem* e)
2371 {
2372     if (e.Eoper == OPvar)
2373         return e;
2374     if (OTleaf(e.Eoper) || !(e.Eoper == OPadd || e.Eoper == OPmin))
2375         return null;
2376 
2377     if (typtr(e.EV.E1.Ety))
2378         return findPointer(e.EV.E1);
2379     if (OTbinary(e.Eoper))
2380     {
2381         if (typtr(e.EV.E2.Ety))
2382             return findPointer(e.EV.E2);
2383     }
2384     return null;
2385 }
2386 
2387 
2388 /****************************
2389  * Comma operator.
2390  *        ,      e
2391  *       / \  =>                expression with no effect
2392  *      c   e
2393  *        ,               ,
2394  *       / \    =>       / \    operators with no effect
2395  *      +   e           ,   e
2396  *     / \             / \
2397  *    e   e           e   e
2398  */
2399 
2400 @trusted
2401 private elem * elcomma(elem *e, goal_t goal)
2402 {
2403     int changes = -1;
2404 L1:
2405     changes++;
2406 L2:
2407     //printf("elcomma()\n");
2408     elem *e2 = e.EV.E2;
2409     elem **pe1 = &(e.EV.E1);
2410     elem *e1 = *pe1;
2411     int e1op = e1.Eoper;
2412 
2413   // c,e => e
2414     if (OTleaf(e1op) && !OTsideff(e1op) && !(e1.Ety & (mTYvolatile | mTYshared)))
2415     {
2416         e2.Ety = e.Ety;
2417         e = el_selecte2(e);
2418         goto Lret;
2419     }
2420 
2421     // ((a op b),e2) => ((a,b),e2)        if op has no side effects
2422     if (!el_sideeffect(e1) && e1op != OPcomma && e1op != OPandand &&
2423         e1op != OPoror && e1op != OPcond)
2424     {
2425         if (OTunary(e1op))
2426             *pe1 = el_selecte1(e1); /* get rid of e1                */
2427         else
2428         {
2429             e1.Eoper = OPcomma;
2430             e1.Ety = e1.EV.E2.Ety;
2431         }
2432         goto L1;
2433     }
2434 
2435     if (!OPTIMIZER)
2436         goto Lret;
2437 
2438     /* Replace (a,b),e2 with a,(b,e2)   */
2439     if (e1op == OPcomma)
2440     {
2441         e1.Ety = e.Ety;
2442         e.EV.E1 = e1.EV.E1;
2443         e1.EV.E1 = e1.EV.E2;
2444         e1.EV.E2 = e2;
2445         e.EV.E2 = elcomma(e1, GOALvalue);
2446         goto L2;
2447     }
2448 
2449     if ((OTopeq(e1op) || e1op == OPeq) &&
2450         (e1.EV.E1.Eoper == OPvar || e1.EV.E1.Eoper == OPind) &&
2451         !el_sideeffect(e1.EV.E1)
2452        )
2453     {
2454         if (el_match(e1.EV.E1,e2))
2455             // ((a = b),a) => (a = b)
2456             e = el_selecte1(e);
2457         else if (OTrel(e2.Eoper) &&
2458                  OTleaf(e2.EV.E2.Eoper) &&
2459                  el_match(e1.EV.E1,e2.EV.E1)
2460                 )
2461         {   // ((a = b),(a < 0)) => ((a = b) < 0)
2462             e1.Ety = e2.EV.E1.Ety;
2463             e.EV.E1 = e2.EV.E1;
2464             e2.EV.E1 = e1;
2465             goto L1;
2466         }
2467         else if ((e2.Eoper == OPandand ||
2468                   e2.Eoper == OPoror   ||
2469                   e2.Eoper == OPcond) &&
2470                  el_match(e1.EV.E1,e2.EV.E1)
2471                 )
2472         {
2473             /* ((a = b),(a || c)) => ((a = b) || c)     */
2474             e1.Ety = e2.EV.E1.Ety;
2475             e.EV.E1 = e2.EV.E1;
2476             e2.EV.E1 = e1;
2477             e = el_selecte2(e);
2478             changes++;
2479             goto Lret;
2480         }
2481         else if (e1op == OPeq)
2482         {
2483             /* Replace ((a = b),(c = a)) with a,(c = (a = b))   */
2484             for (; e2.Eoper == OPcomma; e2 = e2.EV.E1)
2485             { }
2486             if ((OTopeq(e2.Eoper) || e2.Eoper == OPeq) &&
2487                 el_match(e1.EV.E1,e2.EV.E2) &&
2488                 //!(e1.EV.E1.Eoper == OPvar && el_appears(e2.EV.E1,e1.EV.E1.EV.Vsym)) &&
2489                 ERTOL(e2))
2490             {
2491                 e.EV.E1 = e2.EV.E2;
2492                 e1.Ety = e2.EV.E2.Ety;
2493                 e2.EV.E2 = e1;
2494                 goto L1;
2495             }
2496         }
2497         else
2498         {
2499           static if (1) // This optimization is undone in eleq().
2500           {
2501             // Replace ((a op= b),(a op= c)) with (0,a = (a op b) op c)
2502             for (; e2.Eoper == OPcomma; e2 = e2.EV.E1)
2503             { }
2504             if ((OTopeq(e2.Eoper)) &&
2505                 el_match(e1.EV.E1,e2.EV.E1))
2506             {
2507                 elem *ex;
2508                 e.EV.E1 = el_long(TYint,0);
2509                 e1.Eoper = cast(ubyte)opeqtoop(e1op);
2510                 e2.EV.E2 = el_bin(opeqtoop(e2.Eoper),e2.Ety,e1,e2.EV.E2);
2511                 e2.Eoper = OPeq;
2512                 goto L1;
2513             }
2514           }
2515         }
2516     }
2517 Lret:
2518     again = changes != 0;
2519     return e;
2520 }
2521 
2522 /********************************
2523  */
2524 
2525 private elem * elremquo(elem *e, goal_t goal)
2526 {
2527     static if (0)
2528     if (cnst(e.EV.E2) && !boolres(e.EV.E2))
2529         error(e.Esrcpos.Sfilename, e.Esrcpos.Slinnum, e.Esrcpos.Scharnum, "divide by zero\n");
2530 
2531     return e;
2532 }
2533 
2534 /********************************
2535  */
2536 
2537 @trusted
2538 private elem * elmod(elem *e, goal_t goal)
2539 {
2540     tym_t tym = e.EV.E1.Ety;
2541     if (!tyfloating(tym))
2542         return eldiv(e, goal);
2543     return e;
2544 }
2545 
2546 /*****************************
2547  * Convert divides to >> if power of 2.
2548  * Can handle OPdiv, OPdivass, OPmod.
2549  */
2550 
2551 @trusted
2552 private elem * eldiv(elem *e, goal_t goal)
2553 {
2554     //printf("eldiv()\n");
2555     elem *e2 = e.EV.E2;
2556     tym_t tym = e.EV.E1.Ety;
2557     int uns = tyuns(tym) | tyuns(e2.Ety);
2558     if (cnst(e2))
2559     {
2560         static if (0)
2561         if (!boolres(e2))
2562             error(e.Esrcpos.Sfilename, e.Esrcpos.Slinnum, e.Esrcpos.Scharnum, "divide by zero\n");
2563 
2564         if (uns)
2565         {
2566             e2.Ety = touns(e2.Ety);
2567             int i = ispow2(el_tolong(e2));
2568             if (i != -1)
2569             {
2570                 OPER op;
2571                 switch (e.Eoper)
2572                 {   case OPdiv:
2573                         op = OPshr;
2574                         goto L1;
2575 
2576                     case OPdivass:
2577                         op = OPshrass;
2578                     L1:
2579                         e2.EV.Vint = i;
2580                         e2.Ety = TYint;
2581                         e.EV.E1.Ety = touns(tym);
2582                         break;
2583 
2584                     case OPmod:
2585                         op = OPand;
2586                         goto L3;
2587                     case OPmodass:
2588                         op = OPandass;
2589                     L3:
2590                         e2.EV.Vullong = el_tolong(e2) - 1;
2591                         break;
2592 
2593                     default:
2594                         assert(0);
2595                 }
2596                 e.Eoper = cast(ubyte)op;
2597                 return optelem(e,GOALvalue);
2598             }
2599         }
2600     }
2601 
2602     if (OPTIMIZER)
2603     {
2604         const int SQRT_INT_MAX = 0xB504;
2605         const uint SQRT_UINT_MAX = 0x10000;
2606         elem *e1 = e.EV.E1;
2607         if (tyintegral(tym) && e.Eoper == OPdiv && e2.Eoper == OPconst &&
2608             e1.Eoper == OPdiv && e1.EV.E2.Eoper == OPconst)
2609         {
2610             /* Replace:
2611              *   (e / c1) / c2
2612              * With:
2613              *   e / (c1 * c2)
2614              */
2615             targ_llong c1 = el_tolong(e1.EV.E2);
2616             targ_llong c2 = el_tolong(e2);
2617             bool uns1 = tyuns(e1.EV.E1.Ety) || tyuns(e1.EV.E2.Ety);
2618             bool uns2 = tyuns(e1.Ety) || tyuns(e2.Ety);
2619             if (uns1 == uns2)   // identity doesn't hold for mixed sign case
2620             {
2621                 // The transformation will fail if c1*c2 overflows. This substitutes
2622                 // for a proper overflow check.
2623                 if (uns1 ? (c1 < SQRT_UINT_MAX && c2 < SQRT_UINT_MAX)
2624                          : (-SQRT_INT_MAX < c1 && c1 < SQRT_INT_MAX && -SQRT_INT_MAX < c2 && c2 < SQRT_INT_MAX))
2625                 {
2626                     e.EV.E1 = e1.EV.E1;
2627                     e1.EV.E1 = e1.EV.E2;
2628                     e1.EV.E2 = e2;
2629                     e.EV.E2 = e1;
2630                     e1.Eoper = OPmul;
2631                     return optelem(e, GOALvalue);
2632                 }
2633             }
2634         }
2635 
2636         if (tyintegral(tym) && e.Eoper == OPdiv && e2.Eoper == OPconst &&
2637             e1.Eoper == OP64_32 &&
2638             e1.EV.E1.Eoper == OPremquo && e1.EV.E1.EV.E2.Eoper == OPconst)
2639         {
2640             /* Replace:
2641              *   (64_32 (e /% c1)) / c2
2642              * With:
2643              *   e / (c1 * c2)
2644              */
2645             elem *erq = e1.EV.E1;
2646             targ_llong c1 = el_tolong(erq.EV.E2);
2647             targ_llong c2 = el_tolong(e2);
2648             bool uns1 = tyuns(erq.EV.E1.Ety) || tyuns(erq.EV.E2.Ety);
2649             bool uns2 = tyuns(e1.Ety) || tyuns(e2.Ety);
2650             if (uns1 == uns2)   // identity doesn't hold for mixed sign case
2651             {
2652                 // The transformation will fail if c1*c2 overflows. This substitutes
2653                 // for a proper overflow check.
2654                 if (uns1 ? (c1 < SQRT_UINT_MAX && c2 < SQRT_UINT_MAX)
2655                          : (-SQRT_INT_MAX < c1 && c1 < SQRT_INT_MAX && -SQRT_INT_MAX < c2 && c2 < SQRT_INT_MAX))
2656                 {
2657                     e.EV.E1 = erq.EV.E1;
2658                     erq.EV.E1 = erq.EV.E2;
2659                     erq.EV.E2 = e2;
2660                     e.EV.E2 = erq;
2661                     erq.Eoper = OPmul;
2662                     erq.Ety = e1.Ety;
2663                     e1.EV.E1 = null;
2664                     el_free(e1);
2665                     return optelem(e, GOALvalue);
2666                 }
2667             }
2668         }
2669 
2670         /* Convert if(e1/e2) to if(e1>=e2) iff uint division.
2671          */
2672         if (goal == GOALflags && uns && e.Eoper == OPdiv)
2673         {
2674             e.Eoper = OPge;
2675             e.Ety = TYbool;
2676             return e;
2677         }
2678 
2679         /* TODO: (i*c1)/c2 => i*(c1/c2) if (c1%c2)==0
2680          * TODO: i/(x?c1:c2) => i>>(x?log2(c1):log2(c2)) if c1 and c2 are powers of 2
2681          */
2682 
2683         if (tyintegral(tym) && (e.Eoper == OPdiv || e.Eoper == OPmod))
2684         {
2685             int sz = tysize(tym);
2686 
2687             // See if we can replace with OPremquo
2688             if (sz == REGSIZE
2689                 // Currently don't allow this because OPmsw doesn't work for the case
2690                 //|| (I64 && sz == 4)
2691                 )
2692             {
2693                 // Don't do it if there are special code sequences in the
2694                 // code generator (see cdmul())
2695                 int pow2;
2696                 if (e2.Eoper == OPconst &&
2697                     !uns &&
2698                     (pow2 = ispow2(el_tolong(e2))) != -1 &&
2699                     !(config.target_cpu < TARGET_80286 && pow2 != 1 && e.Eoper == OPdiv)
2700                    )
2701                 { }
2702                 else
2703                 {
2704                     assert(sz == 2 || sz == 4 || sz == 8);
2705                     OPER op = OPmsw;
2706                     if (e.Eoper == OPdiv)
2707                     {
2708                         op = (sz == 2) ? OP32_16 : (sz == 4) ? OP64_32 : OP128_64;
2709                     }
2710                     e.Eoper = OPremquo;
2711                     e = el_una(op, tym, e);
2712                     e.EV.E1.Ety = (sz == 2) ? TYlong : (sz == 4) ? TYllong : TYcent;
2713                     return e;
2714                 }
2715             }
2716         }
2717     }
2718 
2719     return e;
2720 }
2721 
2722 /**************************
2723  * Convert (a op b) op c to a op (b op c).
2724  */
2725 
2726 @trusted
2727 private elem * swaplog(elem *e, goal_t goal)
2728 {
2729     elem *e1 = e.EV.E1;
2730     e.EV.E1 = e1.EV.E2;
2731     e1.EV.E2 = e;
2732     return optelem(e1,goal);
2733 }
2734 
2735 @trusted
2736 private elem * eloror(elem *e, goal_t goal)
2737 {
2738     tym_t ty1,ty2;
2739 
2740     elem *e1 = e.EV.E1;
2741     if (OTboolnop(e1.Eoper))
2742     {
2743         e.EV.E1 = e1.EV.E1;
2744         e1.EV.E1 = null;
2745         el_free(e1);
2746         return eloror(e, goal);
2747     }
2748 
2749     elem *e2 = e.EV.E2;
2750     if (OTboolnop(e2.Eoper))
2751     {
2752         e.EV.E2 = e2.EV.E1;
2753         e2.EV.E1 = null;
2754         el_free(e2);
2755         return eloror(e, goal);
2756     }
2757 
2758     if (OPTIMIZER)
2759     {
2760         if (e1.Eoper == OPbool)
2761         {   ty1 = e1.EV.E1.Ety;
2762             e1 = e.EV.E1 = el_selecte1(e1);
2763             e1.Ety = ty1;
2764         }
2765         if (e1.Eoper == OPoror)
2766         {   /* convert (a||b)||c to a||(b||c). This will find more CSEs.    */
2767             return swaplog(e, goal);
2768         }
2769         e2 = elscancommas(e2);
2770         e1 = elscancommas(e1);
2771     }
2772 
2773     tym_t t = e.Ety;
2774     if (e2.Eoper == OPconst || e2.Eoper == OPrelconst || e2.Eoper == OPstring)
2775     {
2776         if (boolres(e2))                /* e1 || 1  => e1 , 1           */
2777         {
2778             if (e.EV.E2 == e2)
2779                 goto L2;
2780         }
2781         else                            /* e1 || 0  =>  bool e1         */
2782         {
2783             if (e.EV.E2 == e2)
2784             {
2785                 el_free(e.EV.E2);
2786                 e.EV.E2 = null;
2787                 e.Eoper = OPbool;
2788                 goto L3;
2789             }
2790         }
2791     }
2792 
2793     if (e1.Eoper == OPconst || e1.Eoper == OPrelconst || e1.Eoper == OPstring)
2794     {
2795         if (boolres(e1))                /* (x,1) || e2  =>  (x,1),1     */
2796         {
2797             if (tybasic(e.EV.E2.Ety) == TYvoid)
2798             {
2799                 assert(!goal);
2800                 el_free(e);
2801                 return null;
2802             }
2803             else
2804             {
2805             L2:
2806                 e.Eoper = OPcomma;
2807                 el_free(e.EV.E2);
2808                 e.EV.E2 = el_long(t,1);
2809             }
2810         }
2811         else                            /* (x,0) || e2  =>  (x,0),(bool e2) */
2812         {
2813             e.Eoper = OPcomma;
2814             if (tybasic(e.EV.E2.Ety) != TYvoid)
2815                 e.EV.E2 = el_una(OPbool,t,e.EV.E2);
2816         }
2817   }
2818   else if (OPTIMIZER &&
2819         e.EV.E2.Eoper == OPvar &&
2820         !OTlogical(e1.Eoper) &&
2821         tysize(ty2 = e2.Ety) == tysize(ty1 = e1.Ety) &&
2822         tysize(ty1) <= _tysize[TYint] &&
2823         !tyfloating(ty2) &&
2824         !tyfloating(ty1) &&
2825         !(ty2 & (mTYvolatile | mTYshared)))
2826     {   /* Convert (e1 || e2) => (e1 | e2)      */
2827         e.Eoper = OPor;
2828         e.Ety = ty1;
2829         e = el_una(OPbool,t,e);
2830     }
2831     else if (OPTIMIZER &&
2832              e1.Eoper == OPand && e2.Eoper == OPand &&
2833              tysize(e1.Ety) == tysize(e2.Ety) &&
2834              el_match(e1.EV.E1,e2.EV.E1) && !el_sideeffect(e1.EV.E1) &&
2835              !el_sideeffect(e2.EV.E2)
2836             )
2837     {   // Convert ((a & b) || (a & c)) => bool(a & (b | c))
2838         e.Eoper = OPbool;
2839         e.EV.E2 = null;
2840         e2.Eoper = OPor;
2841         el_free(e2.EV.E1);
2842         e2.EV.E1 = e1.EV.E2;
2843         e1.EV.E2 = e2;
2844     }
2845     else
2846         goto L1;
2847 L3:
2848     e = optelem(e,GOALvalue);
2849 L1:
2850     return e;
2851 }
2852 
2853 /**********************************************
2854  * Try to rewrite sequence of || and && with faster operations, such as BT.
2855  * Returns:
2856  *      false   nothing changed
2857  *      true    *pe is rewritten
2858  */
2859 
2860 @trusted
2861 private bool optim_loglog(ref elem* pe)
2862 {
2863     if (I16)
2864         return false;
2865     elem *e = pe;
2866     const op = e.Eoper;
2867     assert(op == OPandand || op == OPoror);
2868     size_t n = el_opN(e, op);
2869     if (n <= 3)
2870         return false;
2871     uint ty = e.Ety;
2872 
2873     import dmd.common.string : SmallBuffer;
2874     elem*[100] tmp = void;
2875     auto sb = SmallBuffer!(elem*)(n, tmp[]);
2876     elem*[] array = sb[];
2877 
2878     elem **p = array.ptr;
2879     el_opArray(&p, e, op);
2880 
2881     bool any = false;
2882     size_t first, last;
2883     targ_ullong emin, emax;
2884     int cmpop = op == OPandand ? OPne : OPeqeq;
2885     for (size_t i = 0; i < n; ++i)
2886     {
2887         elem *eq = array[i];
2888         if (eq.Eoper == cmpop &&
2889             eq.EV.E2.Eoper == OPconst &&
2890             tyintegral(eq.EV.E2.Ety) &&
2891             !el_sideeffect(eq.EV.E1))
2892         {
2893             targ_ullong m = el_tolong(eq.EV.E2);
2894             if (any)
2895             {
2896                 if (el_match(array[first].EV.E1, eq.EV.E1))
2897                 {
2898                     last = i;
2899                     if (m < emin)
2900                         emin = m;
2901                     if (m > emax)
2902                         emax = m;
2903                 }
2904                 else if (last - first > 2)
2905                     break;
2906                 else
2907                 {
2908                     first = last = i;
2909                     emin = emax = m;
2910                 }
2911             }
2912             else
2913             {
2914                 any = true;
2915                 first = last = i;
2916                 emin = emax = m;
2917             }
2918         }
2919         else if (any && last - first > 2)
2920             break;
2921         else
2922             any = false;
2923     }
2924 
2925     //printf("n = %d, count = %d, min = %d, max = %d\n", cast(int)n, last - first + 1, cast(int)emin, cast(int)emax);
2926     if (any && last - first > 2 && emax - emin < REGSIZE * 8)
2927     {
2928         /**
2929          * Transforms expressions of the form x==c1 || x==c2 || x==c3 || ... into a single
2930          * comparison by using a bitmapped representation of data, as follows. First, the
2931          * smallest constant of c1, c2, ... (call it min) is subtracted from all constants
2932          * and also from x (this step may be elided if all constants are small enough). Then,
2933          * the test is expressed as
2934          *   (1 << (x-min)) | ((1 << (c1-min)) | (1 << (c2-min)) | ...)
2935          * The test is guarded for overflow (x must be no larger than the largest of c1, c2, ...).
2936          * Since each constant is encoded as a displacement in a bitmap, hitting any bit yields
2937          * true for the expression.
2938          *
2939          * I.e. replace:
2940          *   e==c1 || e==c2 || e==c3 ...
2941          * with:
2942          *   (e - emin) <= (emax - emin) && (1 << (int)(e - emin)) & bits
2943          * where bits is:
2944          *   (1<<(c1-emin)) | (1<<(c2-emin)) | (1<<(c3-emin)) ...
2945          *
2946          * For the case of:
2947          *  x!=c1 && x!=c2 && x!=c3 && ...
2948          * using De Morgan's theorem, rewrite as:
2949          *   (e - emin) > (emax - emin) || ((1 << (int)(e - emin)) & ~bits)
2950          */
2951 
2952         // Delete all the || nodes that are no longer referenced
2953         el_opFree(e, op);
2954 
2955         if (emax < 32)                  // if everything fits in a 32 bit register
2956             emin = 0;                   // no need for bias
2957 
2958         // Compute bit mask
2959         targ_ullong bits = 0;
2960         for (size_t i = first; i <= last; ++i)
2961         {
2962             elem *eq = array[i];
2963             if (0 && eq.EV.E2.Eoper != OPconst)
2964             {
2965                 printf("eq = %p, eq.EV.E2 = %p\n", eq, eq.EV.E2);
2966                 printf("first = %d, i = %d, last = %d, Eoper = %d\n", cast(int)first, cast(int)i, cast(int)last, eq.EV.E2.Eoper);
2967                 printf("any = %d, n = %d, count = %d, min = %d, max = %d\n", any, cast(int)n, cast(int)(last - first + 1), cast(int)emin, cast(int)emax);
2968             }
2969             assert(eq.EV.E2.Eoper == OPconst);
2970             bits |= cast(targ_ullong)1 << (el_tolong(eq.EV.E2) - emin);
2971         }
2972         //printf("n = %d, count = %d, min = %d, max = %d\n", cast(int)n, last - first + 1, cast(int)emin, cast(int)emax);
2973         //printf("bits = x%llx\n", bits);
2974 
2975         if (op == OPandand)
2976             bits = ~bits;
2977 
2978         uint tyc = array[first].EV.E1.Ety;
2979 
2980         elem *ex = el_bin(OPmin, tyc, array[first].EV.E1, el_long(tyc,emin));
2981         ex = el_bin(op == OPandand ? OPgt : OPle, TYbool, ex, el_long(touns(tyc), emax - emin));
2982         elem *ey = el_bin(OPmin, tyc, array[first + 1].EV.E1, el_long(tyc,emin));
2983 
2984         tym_t tybits = TYuint;
2985         if ((emax - emin) >= 32)
2986         {
2987             assert(I64);                // need 64 bit BT
2988             tybits = TYullong;
2989         }
2990 
2991         // Shift count must be an int
2992         switch (tysize(tyc))
2993         {
2994             case 1:
2995                 ey = el_una(OPu8_16,TYint,ey);
2996                 goto case 2;
2997 
2998             case 2:
2999                 ey = el_una(OPu16_32,TYint,ey);
3000                 break;
3001 
3002             case 4:
3003                 break;
3004 
3005             case 8:
3006                 ey = el_una(OP64_32,TYint,ey);
3007                 break;
3008 
3009             default:
3010                 assert(0);
3011         }
3012         ey = el_bin(OPbtst,TYbool,el_long(tybits,bits),ey);
3013         ex = el_bin(op == OPandand ? OPoror : OPandand, ty, ex, ey);
3014 
3015         /* Free unneeded nodes
3016          */
3017         array[first].EV.E1 = null;
3018         el_free(array[first]);
3019         array[first + 1].EV.E1 = null;
3020         el_free(array[first + 1]);
3021         for (size_t i = first + 2; i <= last; ++i)
3022             el_free(array[i]);
3023 
3024         array[first] = ex;
3025 
3026         for (size_t i = first + 1; i + (last - first) < n; ++i)
3027             array[i] = array[i + (last - first)];
3028         n -= last - first;
3029         pe = el_opCombine(array.ptr, n, op, ty);
3030 
3031         return true;
3032     }
3033 
3034     return false;
3035 }
3036 
3037 @trusted
3038 private elem * elandand(elem *e, goal_t goal)
3039 {
3040     elem *e1 = e.EV.E1;
3041     if (OTboolnop(e1.Eoper))
3042     {
3043         e.EV.E1 = e1.EV.E1;
3044         e1.EV.E1 = null;
3045         el_free(e1);
3046         return elandand(e, goal);
3047     }
3048     elem *e2 = e.EV.E2;
3049     if (OTboolnop(e2.Eoper))
3050     {
3051         e.EV.E2 = e2.EV.E1;
3052         e2.EV.E1 = null;
3053         el_free(e2);
3054         return elandand(e, goal);
3055     }
3056     if (OPTIMIZER)
3057     {
3058         /* Recognize: (a >= c1 && a < c2)
3059          */
3060         if ((e1.Eoper == OPge || e1.Eoper == OPgt) &&
3061             (e2.Eoper == OPlt || e2.Eoper == OPle) &&
3062             e1.EV.E2.Eoper == OPconst && e2.EV.E2.Eoper == OPconst &&
3063             !el_sideeffect(e1.EV.E1) && el_match(e1.EV.E1, e2.EV.E1) &&
3064             tyintegral(e1.EV.E1.Ety) &&
3065             tybasic(e1.EV.E2.Ety) == tybasic(e2.EV.E2.Ety) &&
3066             tysize(e1.EV.E1.Ety) == _tysize[TYnptr])
3067         {
3068             /* Replace with: ((a - c1) < (c2 - c1))
3069              */
3070             targ_llong c1 = el_tolong(e1.EV.E2);
3071             if (e1.Eoper == OPgt)
3072                 ++c1;
3073             targ_llong c2 = el_tolong(e2.EV.E2);
3074             if (0 <= c1 && c1 <= c2)
3075             {
3076                 e1.Eoper = OPmin;
3077                 e1.Ety = e1.EV.E1.Ety;
3078                 e1.EV.E2.EV.Vllong = c1;
3079                 e.EV.E2 = el_long(touns(e2.EV.E2.Ety), c2 - c1);
3080                 e.Eoper = e2.Eoper;
3081                 el_free(e2);
3082                 return optelem(e, GOALvalue);
3083             }
3084         }
3085 
3086         // Look for (!(e >>> c) && ...)
3087         if (e1.Eoper == OPnot && e1.EV.E1.Eoper == OPshr &&
3088             e1.EV.E1.EV.E2.Eoper == OPconst)
3089         {
3090             // Replace (e >>> c) with (e & x)
3091             elem *e11 = e1.EV.E1;
3092 
3093             targ_ullong shift = el_tolong(e11.EV.E2);
3094             if (shift < _tysize[TYint] * 8)
3095             {
3096                 targ_ullong m;
3097                 m = ~0L << cast(int)shift;
3098                 e11.Eoper = OPand;
3099                 e11.EV.E2.EV.Vullong = m;
3100                 e11.EV.E2.Ety = e11.Ety;
3101                 return optelem(e,GOALvalue);
3102             }
3103         }
3104 
3105         if (e1.Eoper == OPbool)
3106         {
3107             tym_t t = e1.EV.E1.Ety;
3108             e1 = e.EV.E1 = el_selecte1(e1);
3109             e1.Ety = t;
3110         }
3111         if (e1.Eoper == OPandand)
3112         {   // convert (a&&b)&&c to a&&(b&&c). This will find more CSEs.
3113             return swaplog(e, goal);
3114         }
3115         e2 = elscancommas(e2);
3116 
3117         while (1)
3118         {
3119             e1 = elscancommas(e1);
3120             if (e1.Eoper == OPeq)
3121                 e1 = e1.EV.E2;
3122             else
3123                 break;
3124         }
3125     }
3126 
3127     if (e2.Eoper == OPconst || e2.Eoper == OPrelconst || e2.Eoper == OPstring)
3128     {
3129         if (boolres(e2))        // e1 && (x,1)  =>  e1 ? ((x,1),1) : 0
3130         {
3131             if (e2 == e.EV.E2)    // if no x, replace e with (bool e1)
3132             {
3133                 el_free(e2);
3134                 e.EV.E2 = null;
3135                 e.Eoper = OPbool;
3136                 goto L3;
3137             }
3138         }
3139         else                            // e1 && (x,0)  =>  e1 , (x,0)
3140         {
3141             if (e2 == e.EV.E2)
3142             {   e.Eoper = OPcomma;
3143                 goto L3;
3144             }
3145         }
3146     }
3147 
3148   if (e1.Eoper == OPconst || e1.Eoper == OPrelconst || e1.Eoper == OPstring)
3149   {
3150         e.Eoper = OPcomma;
3151         if (boolres(e1))                // (x,1) && e2  =>  (x,1),bool e2
3152         {
3153             if (tybasic(e.EV.E2.Ety) != TYvoid)
3154                 e.EV.E2 = el_una(OPbool,e.Ety,e.EV.E2);
3155         }
3156         else                            // (x,0) && e2  =>  (x,0),0
3157         {
3158             if (tybasic(e.EV.E2.Ety) == TYvoid)
3159             {
3160                 assert(!goal);
3161                 el_free(e);
3162                 return null;
3163             }
3164             else
3165             {
3166                 el_free(e.EV.E2);
3167                 e.EV.E2 = el_long(e.Ety,0);
3168             }
3169         }
3170     }
3171     else
3172         goto L1;
3173 L3:
3174     e = optelem(e,GOALvalue);
3175 L1:
3176     return e;
3177 }
3178 
3179 /**************************
3180  * Reference to bit field
3181  *       bit
3182  *       / \    =>      ((e << c) >> b) & m
3183  *      e  w,b
3184  *
3185  * Note that this routine can handle long bit fields, though this may
3186  * not be supported later on.
3187  */
3188 
3189 @trusted
3190 private elem * elbit(elem *e, goal_t goal)
3191 {
3192     tym_t tym1 = e.EV.E1.Ety;
3193     uint sz = tysize(tym1) * 8;
3194     elem *e2 = e.EV.E2;
3195     uint wb = e2.EV.Vuns;
3196 
3197     uint w = (wb >> 8) & 0xFF;               // width in bits of field
3198     targ_ullong m = (cast(targ_ullong)1 << w) - 1;   // mask w bits wide
3199     uint b = wb & 0xFF;                      // bits to right of field
3200     uint c = 0;
3201     //printf("w %u + b %u <= sz %u\n", w, b, sz);
3202     assert(w + b <= sz);
3203 
3204     if (tyuns(tym1))                      // if uint bit field
3205     {
3206         // Should use a more general solution to this
3207         if (w == 8 && sz == 16 && b == 0)
3208         {
3209             e.EV.E1 = el_una(OP16_8,TYuchar,e.EV.E1);
3210             e.Eoper = OPu8_16;
3211             e.EV.E2 = null;
3212             el_free(e2);
3213             return optelem(e,GOALvalue);         // optimize result
3214         }
3215 
3216         if (w + b == sz)                // if field is left-justified
3217             m = ~cast(targ_ullong)0;    // no need to mask
3218     }
3219     else                                // signed bit field
3220     {
3221         if (w == 8 && sz == 16 && b == 0)
3222         {
3223             e.EV.E1 = el_una(OP16_8,TYschar,e.EV.E1);
3224             e.Eoper = OPs8_16;
3225             e.EV.E2 = null;
3226             el_free(e2);
3227             return optelem(e,GOALvalue);         // optimize result
3228         }
3229         m = ~cast(targ_ullong)0;
3230         c = sz - (w + b);
3231         b = sz - w;
3232     }
3233 
3234     e.Eoper = OPand;
3235 
3236     e2.EV.Vullong = m;                   // mask w bits wide
3237     e2.Ety = e.Ety;
3238 
3239     OPER shift = OPshr;
3240     if (!tyuns(tym1))
3241         shift = OPashr;
3242     e.EV.E1 = el_bin(shift,tym1,
3243                 el_bin(OPshl,tym1,e.EV.E1,el_long(TYint,c)),
3244                 el_long(TYint,b));
3245     return optelem(e,GOALvalue);         // optimize result
3246 }
3247 
3248 /*****************
3249  * Indirection
3250  *      * & e => e
3251  */
3252 
3253 @trusted
3254 private elem * elind(elem *e, goal_t goal)
3255 {
3256     tym_t tym = e.Ety;
3257     elem *e1 = e.EV.E1;
3258     switch (e1.Eoper)
3259     {
3260         case OPrelconst:
3261             e.EV.E1.ET = e.ET;
3262             e = el_selecte1(e);
3263             e.Eoper = OPvar;
3264             e.Ety = tym;               /* preserve original type       */
3265             break;
3266 
3267         case OPadd:
3268             if (OPTIMIZER)
3269             {   /* Try to convert far pointer to stack pointer  */
3270                 elem *e12 = e1.EV.E2;
3271 
3272                 if (e12.Eoper == OPrelconst &&
3273                     tybasic(e12.Ety) == TYfptr &&
3274                     /* If symbol is located on the stack        */
3275                     sytab[e12.EV.Vsym.Sclass] & SCSS)
3276                 {   e1.Ety = (e1.Ety & (mTYconst | mTYvolatile | mTYimmutable | mTYshared | mTYLINK)) | TYsptr;
3277                     e12.Ety = (e12.Ety & (mTYconst | mTYvolatile | mTYimmutable | mTYshared | mTYLINK)) | TYsptr;
3278                 }
3279             }
3280             break;
3281 
3282         case OPcomma:
3283             // Replace (*(ea,eb)) with (ea,*eb)
3284             e.EV.E1.ET = e.ET;
3285             type *t = e.ET;
3286             e = el_selecte1(e);
3287             e.Ety = tym;
3288             e.EV.E2 = el_una(OPind,tym,e.EV.E2);
3289             e.EV.E2.ET = t;
3290             again = 1;
3291             return e;
3292 
3293         default:
3294             break;
3295     }
3296     topair |= (config.fpxmmregs && tycomplex(tym));
3297     return e;
3298 }
3299 
3300 /*****************
3301  * Address of.
3302  *      & v => &v
3303  *      & * e => e
3304  *      & (v1 = v2) => ((v1 = v2), &v1)
3305  */
3306 
3307 @trusted
3308 private elem * eladdr(elem *e, goal_t goal)
3309 {
3310     tym_t tym = e.Ety;
3311     elem *e1 = e.EV.E1;
3312     elem_debug(e1);
3313     switch (e1.Eoper)
3314     {
3315         case OPvar:
3316             e1.Eoper = OPrelconst;
3317             e1.EV.Vsym.Sflags &= ~(SFLunambig | GTregcand);
3318             e1.Ety = tym;
3319             e = optelem(el_selecte1(e),GOALvalue);
3320             break;
3321 
3322         case OPind:
3323         {
3324             tym_t tym2 = e1.EV.E1.Ety;
3325 
3326             // Watch out for conversions between near and far pointers
3327             int sz = tysize(tym) - tysize(tym2);
3328             if (sz != 0)
3329             {
3330                 OPER op;
3331                 if (sz > 0)                         // if &far * near
3332                     op = OPnp_fp;
3333                 else                                // else &near * far
3334                     op = OPoffset;
3335                 e.Ety = tym2;
3336                 e = el_una(op,tym,e);
3337                 goto L1;
3338             }
3339 
3340             e = el_selecte1(el_selecte1(e));
3341             e.Ety = tym;
3342             break;
3343         }
3344 
3345         case OPcomma:
3346             // Replace (&(ea,eb)) with (ea,&eb)
3347             e = el_selecte1(e);
3348             e.Ety = tym;
3349             e.EV.E2 = el_una(OPaddr,tym,e.EV.E2);
3350         L1:
3351             e = optelem(e,GOALvalue);
3352             break;
3353 
3354         case OPnegass:
3355             assert(0);
3356 
3357         default:
3358             if (OTassign(e1.Eoper))
3359             {
3360         case OPstreq:
3361                 //  & (v1 = e) => ((v1 = e), &v1)
3362                 if (e1.EV.E1.Eoper == OPvar)
3363                 {
3364                     e.Eoper = OPcomma;
3365                     e.EV.E2 = el_una(OPaddr,tym,el_copytree(e1.EV.E1));
3366                     goto L1;
3367                 }
3368                 //  & (*p1 = e) => ((*(t = p1) = e), t)
3369                 else if (e1.EV.E1.Eoper == OPind)
3370                 {
3371                     const tym_t tym111 = e1.EV.E1.EV.E1.Ety;
3372                     elem *tmp = el_alloctmp(tym111);
3373                     e1.EV.E1.EV.E1 = el_bin(OPeq,tym111,tmp,e1.EV.E1.EV.E1);
3374                     e.Eoper = OPcomma;
3375                     e.EV.E2 = el_copytree(tmp);
3376                     goto L1;
3377                 }
3378             }
3379             break;
3380 
3381         case OPcond:
3382         {   // Replace &(x ? y : z) with (x ? &y : &z)
3383             elem *ecolon = e1.EV.E2;
3384             ecolon.Ety = tym;
3385             ecolon.EV.E1 = el_una(OPaddr,tym,ecolon.EV.E1);
3386             ecolon.EV.E2 = el_una(OPaddr,tym,ecolon.EV.E2);
3387             e = el_selecte1(e);
3388             e = optelem(e,GOALvalue);
3389             break;
3390         }
3391 
3392         case OPinfo:
3393             // Replace &(e1 info e2) with (e1 info &e2)
3394             e = el_selecte1(e);
3395             e.EV.E2 = el_una(OPaddr,tym,e.EV.E2);
3396             e = optelem(e,GOALvalue);
3397             break;
3398     }
3399     return e;
3400 }
3401 
3402 /*******************************************
3403  */
3404 
3405 @trusted
3406 private elem * elneg(elem *e, goal_t goal)
3407 {
3408     if (e.EV.E1.Eoper == OPneg)
3409     {
3410         e = el_selecte1(e);
3411         e = el_selecte1(e);
3412     }
3413     /* Convert -(e1 + c) to (-e1 - c)
3414      */
3415     else if (e.EV.E1.Eoper == OPadd && e.EV.E1.EV.E2.Eoper == OPconst)
3416     {
3417         e.Eoper = OPmin;
3418         e.EV.E2 = e.EV.E1.EV.E2;
3419         e.EV.E1.Eoper = OPneg;
3420         e.EV.E1.EV.E2 = null;
3421         e = optelem(e,goal);
3422     }
3423     else
3424         e = evalu8(e, goal);
3425     return e;
3426 }
3427 
3428 @trusted
3429 private elem * elcall(elem *e, goal_t goal)
3430 {
3431     if (e.EV.E1.Eoper == OPcomma || OTassign(e.EV.E1.Eoper))
3432         e = cgel_lvalue(e);
3433     return e;
3434 }
3435 
3436 /***************************
3437  * Walk tree, converting types to tym.
3438  */
3439 
3440 @trusted
3441 private void elstructwalk(elem *e,tym_t tym)
3442 {
3443     tym_t ety;
3444 
3445     while ((ety = tybasic(e.Ety)) == TYstruct ||
3446            ety == TYarray)
3447     {   elem_debug(e);
3448         e.Ety = (e.Ety & ~mTYbasic) | tym;
3449         switch (e.Eoper)
3450         {
3451             case OPcomma:
3452             case OPcond:
3453             case OPinfo:
3454                 break;
3455 
3456             case OPeq:
3457             case OPcolon:
3458             case OPcolon2:
3459                 elstructwalk(e.EV.E1,tym);
3460                 break;
3461 
3462             default:
3463                 return;
3464         }
3465         e = e.EV.E2;
3466     }
3467 }
3468 
3469 /*******************************
3470  * See if we can replace struct operations with simpler ones.
3471  * For OPstreq and OPstrpar.
3472  */
3473 
3474 @trusted
3475 elem * elstruct(elem *e, goal_t goal)
3476 {
3477     //printf("elstruct(%p)\n", e);
3478     //elem_print(e);
3479     if (e.Eoper == OPstreq && (e.EV.E1.Eoper == OPcomma || OTassign(e.EV.E1.Eoper)))
3480         return cgel_lvalue(e);
3481 
3482     if (e.Eoper == OPstreq && e.EV.E2.Eoper == OPcomma)
3483     {
3484         /* Replace (e1 streq (e21, e22)) with (e21, (e1 streq e22))
3485          */
3486         e.EV.E2.Eoper = e.Eoper;
3487         e.EV.E2.Ety = e.Ety;
3488         e.EV.E2.ET = e.ET;
3489         e.Eoper = OPcomma;
3490         elem *etmp = e.EV.E1;
3491         e.EV.E1 = e.EV.E2.EV.E1;
3492         e.EV.E2.EV.E1 = etmp;
3493         return optelem(e, goal);
3494     }
3495 
3496     if (!e.ET)
3497         return e;
3498     //printf("\tnumbytes = %d\n", cast(int)type_size(e.ET));
3499 
3500     type *t = e.ET;
3501     tym_t tym = ~0;
3502     tym_t ty = tybasic(t.Tty);
3503 
3504     uint sz = (e.Eoper == OPstrpar && type_zeroSize(t, global_tyf)) ? 0 : cast(uint)type_size(t);
3505     //printf("\tsz = %d\n", cast(int)sz);
3506 
3507     type *targ1 = null;
3508     type *targ2 = null;
3509     if (ty == TYstruct)
3510     {   // If a struct is a wrapper for another type, prefer that other type
3511         targ1 = t.Ttag.Sstruct.Sarg1type;
3512         targ2 = t.Ttag.Sstruct.Sarg2type;
3513     }
3514 
3515     if (ty == TYarray && sz && config.exe != EX_WIN64)
3516     {
3517         argtypes(t, targ1, targ2);
3518         if (!targ1)
3519             goto Ldefault;
3520         goto L1;
3521     }
3522     //if (targ1) { printf("targ1\n"); type_print(targ1); }
3523     //if (targ2) { printf("targ2\n"); type_print(targ2); }
3524     switch (cast(int)sz)
3525     {
3526         case 1:  tym = TYchar;   goto L1;
3527         case 2:  tym = TYshort;  goto L1;
3528         case 4:  tym = TYlong;   goto L1;
3529         case 8:  if (_tysize[TYint] == 2)
3530                      goto Ldefault;
3531                  tym = TYllong;  goto L1;
3532 
3533         case 3:  tym = TYlong;  goto L2;
3534         case 5:
3535         case 6:
3536         case 7:  tym = TYllong;
3537         L2:
3538             if (e.Eoper == OPstrpar && config.exe == EX_WIN64)
3539             {
3540                  goto L1;
3541             }
3542             if (I64 && config.exe != EX_WIN64)
3543             {
3544                 goto L1;
3545             }
3546             tym = ~0;
3547             goto Ldefault;
3548 
3549         case 10:
3550         case 12:
3551             if (tysize(TYldouble) == sz && targ1 && !targ2 && tybasic(targ1.Tty) == TYldouble)
3552             {
3553                 tym = TYldouble;
3554                 goto L1;
3555             }
3556             goto case 9;
3557 
3558         case 9:
3559         case 11:
3560         case 13:
3561         case 14:
3562         case 15:
3563             if (I64 && config.exe != EX_WIN64)
3564             {
3565                 goto L1;
3566             }
3567             goto Ldefault;
3568 
3569         case 16:
3570             if (I64 && (ty == TYstruct || (ty == TYarray && config.exe == EX_WIN64)))
3571             {
3572                 tym = TYucent;
3573                 goto L1;
3574             }
3575             if (config.exe == EX_WIN64)
3576                 goto Ldefault;
3577             if (targ1 && !targ2)
3578                 goto L1;
3579             goto Ldefault;
3580 
3581         L1:
3582             if (ty == TYstruct || ty == TYarray)
3583             {
3584                 // This needs to match what TypeFunction::retStyle() does
3585                 if (config.exe == EX_WIN64)
3586                 {
3587                     //if (t.Ttag.Sstruct.Sflags & STRnotpod)
3588                         //goto Ldefault;
3589                 }
3590                 // If a struct is a wrapper for another type, prefer that other type
3591                 else if (targ1 && !targ2)
3592                     tym = targ1.Tty;
3593                 else if (I64 && !targ1 && !targ2)
3594                 {
3595                     if (t.Ttag.Sstruct.Sflags & STRnotpod)
3596                     {
3597                         // In-memory only
3598                         goto Ldefault;
3599                     }
3600 //                    if (type_size(t) == 16)
3601                         goto Ldefault;
3602                 }
3603                 else if (I64 && targ1 && targ2)
3604                 {
3605                     if (tyfloating(tybasic(targ1.Tty)))
3606                         tym = TYcdouble;
3607                     else
3608                         tym = TYucent;
3609                     if ((0 == tyfloating(targ1.Tty)) ^ (0 == tyfloating(targ2.Tty)))
3610                     {
3611                         tym |= tyfloating(targ1.Tty) ? mTYxmmgpr : mTYgprxmm;
3612                     }
3613                 }
3614                 else if (I32 && targ1 && targ2)
3615                 {
3616                     tym = TYllong;
3617                 }
3618                 assert(tym != TYstruct);
3619             }
3620             assert(tym != ~0);
3621             switch (e.Eoper)
3622             {
3623                 case OPstreq:
3624                     if (sz != tysize(tym))
3625                     {
3626                         // we can't optimize OPstreq in this case,
3627                         // there will be memory corruption in the assignment
3628                         elem *e2 = e.EV.E2;
3629                         if (e2.Eoper != OPvar && e2.Eoper != OPind)
3630                         {
3631                             // the source may come in registers. ex: returned from a function.
3632                             assert(tyaggregate(e2.Ety));
3633                             e2 = optelem(e2, GOALvalue);
3634                             e2 = elstruct(e2, GOALvalue);
3635                             e2 = exp2_copytotemp(e2); // (tmp = e2, tmp)
3636                             e2.EV.E2.EV.Vsym.Sfl = FLauto;
3637                             e2.Ety = e2.EV.E2.Ety = e.Ety;
3638                             e2.ET = e2.EV.E2.ET = e.ET;
3639                             e.EV.E2 = e2;
3640                         }
3641                         break;
3642                     }
3643                     e.Eoper = OPeq;
3644                     e.Ety = (e.Ety & ~mTYbasic) | tym;
3645                     elstructwalk(e.EV.E1,tym);
3646                     elstructwalk(e.EV.E2,tym);
3647                     e = optelem(e,GOALvalue);
3648                     break;
3649 
3650                 case OPstrpar:
3651                     e = el_selecte1(e);
3652                     goto default;
3653 
3654                 default:                /* called by doptelem()         */
3655                     elstructwalk(e,tym);
3656                     break;
3657             }
3658             break;
3659 
3660         case 0:
3661             if (e.Eoper == OPstreq)
3662             {
3663                 e.Eoper = OPcomma;
3664                 e = optelem(e,GOALvalue);
3665                 again = 1;
3666             }
3667             else
3668                 goto Ldefault;
3669             break;
3670 
3671         default:
3672         Ldefault:
3673         {
3674             elem **pe2;
3675             if (e.Eoper == OPstreq)
3676                 pe2 = &e.EV.E2;
3677             else if (e.Eoper == OPstrpar)
3678                 pe2 = &e.EV.E1;
3679             else
3680                 break;
3681             while ((*pe2).Eoper == OPcomma)
3682                 pe2 = &(*pe2).EV.E2;
3683             elem *e2 = *pe2;
3684 
3685             if (e2.Eoper == OPvar)
3686                 e2.EV.Vsym.Sflags &= ~GTregcand;
3687 
3688             // Convert (x streq (a?y:z)) to (x streq *(a ? &y : &z))
3689             if (e2.Eoper == OPcond)
3690             {
3691                 tym_t ty2 = e2.Ety;
3692 
3693                 /* We should do the analysis to see if we can use
3694                    something simpler than TYfptr.
3695                  */
3696                 tym_t typ = (_tysize[TYint] == LONGSIZE) ? TYnptr : TYfptr;
3697                 e2 = el_una(OPaddr,typ,e2);
3698                 e2 = optelem(e2,GOALvalue);          /* distribute & to x and y leaves */
3699                 *pe2 = el_una(OPind,ty2,e2);
3700                 break;
3701             }
3702             break;
3703         }
3704     }
3705     //printf("elstruct return\n");
3706     //elem_print(e);
3707     return e;
3708 }
3709 
3710 /**************************
3711  * Assignment. Replace bit field assignment with
3712  * equivalent tree.
3713  *              =
3714  *            /  \
3715  *           /    r
3716  *        bit
3717  *       /   \
3718  *      l     w,b
3719  *
3720  * becomes:
3721  *          ,
3722  *         / \
3723  *        =   (r&m)
3724  *       / \
3725  *      l   |
3726  *         / \
3727  *  (r&m)<<b  &
3728  *           / \
3729  *          l  ~(m<<b)
3730  * Note:
3731  *      This depends on the expression (r&m)<<b before l. This is because
3732  *      of expressions like (l.a = l.b = n). It is an artifact of the way
3733  *      we do things that this works (cost() will rate the << as more
3734  *      expensive than the &, and so it will wind up on the left).
3735  */
3736 
3737 @trusted
3738 private elem * eleq(elem *e, goal_t goal)
3739 {
3740     goal_t wantres = goal;
3741     elem *e1 = e.EV.E1;
3742 
3743     if (e1.Eoper == OPcomma || OTassign(e1.Eoper))
3744         return cgel_lvalue(e);
3745 
3746 static if (0)  // Doesn't work too well, removed
3747 {
3748     // Replace (*p++ = e2) with ((*p = e2),*p++)
3749     if (OPTIMIZER && e1.Eoper == OPind &&
3750       (e1.EV.E1.Eoper == OPpostinc || e1.EV.E1.Eoper == OPpostdec) &&
3751       !el_sideeffect(e1.EV.E1.EV.E1)
3752        )
3753     {
3754         e = el_bin(OPcomma,e.Ety,e,e1);
3755         e.EV.E1.EV.E1 = el_una(OPind,e1.Ety,el_copytree(e1.EV.E1.EV.E1));
3756         return optelem(e,GOALvalue);
3757     }
3758 }
3759 
3760     if (OPTIMIZER)
3761     {
3762         elem *e2 = e.EV.E2;
3763         int op2 = e2.Eoper;
3764 
3765         // Replace (e1 = *p++) with (e1 = *p, p++, e1)
3766         elem *ei = e2;
3767         if (e1.Eoper == OPvar &&
3768             (op2 == OPind || (OTunary(op2) && (ei = e2.EV.E1).Eoper == OPind)) &&
3769             (ei.EV.E1.Eoper == OPpostinc || ei.EV.E1.Eoper == OPpostdec) &&
3770             !el_sideeffect(e1) &&
3771             !el_sideeffect(ei.EV.E1.EV.E1)
3772            )
3773         {
3774            e = el_bin(OPcomma,e.Ety,
3775                 e,
3776                 el_bin(OPcomma,e.Ety,ei.EV.E1,el_copytree(e1)));
3777            ei.EV.E1 = el_copytree(ei.EV.E1.EV.E1);            // copy p
3778            return optelem(e,GOALvalue);
3779         }
3780 
3781         /* Replace (e = e) with (e,e)   */
3782         if (el_match(e1,e2))
3783         {
3784             e.Eoper = OPcomma;
3785         L1:
3786             return optelem(e,GOALvalue);
3787         }
3788 
3789         // Replace (e1 = (e21 , e22)) with (e21 , (e1 = e22))
3790         if (op2 == OPcomma)
3791         {
3792             e2.Ety = e.Ety;
3793             e.EV.E2 = e2.EV.E2;
3794             e2.EV.E2 = e;
3795             e = e2;
3796             goto L1;
3797         }
3798 
3799         if (OTop(op2) && !el_sideeffect(e1)
3800             && op2 != OPdiv && op2 != OPmod
3801            )
3802         {
3803             tym_t ty;
3804 
3805             enum side = false; // don't allow side effects in e2.EV.E2 because of
3806                                // D order-of-evaluation rules
3807 
3808             // Replace (e1 = e1 op e) with (e1 op= e)
3809             if (el_match(e1,e2.EV.E1) &&
3810                 (side || !el_sideeffect(e2.EV.E2)))
3811             {
3812                 ty = e2.EV.E2.Ety;
3813                 e.EV.E2 = el_selecte2(e2);
3814             L2:
3815                 e.EV.E2.Ety = ty;
3816                 e.Eoper = cast(ubyte)optoopeq(op2);
3817                 goto L1;
3818             }
3819             if (OTcommut(op2))
3820             {
3821                 /* Replace (e1 = e op e1) with (e1 op= e)       */
3822                 if (el_match(e1,e2.EV.E2))
3823                 {   ty = e2.EV.E1.Ety;
3824                     e.EV.E2 = el_selecte1(e2);
3825                     goto L2;
3826                 }
3827             }
3828 
3829 static if (0)
3830 {
3831 // Note that this optimization is undone in elcomma(), this results in an
3832 // infinite loop. This optimization is preferable if e1 winds up a register
3833 // variable, the inverse in elcomma() is preferable if e1 winds up in memory.
3834             // Replace (e1 = (e1 op3 ea) op2 eb) with (e1 op3= ea),(e1 op2= eb)
3835             int op3 = e2.EV.E1.Eoper;
3836             if (OTop(op3) && el_match(e1,e2.EV.E1.EV.E1) && !el_depends(e1,e2.EV.E2))
3837             {
3838                 e.Eoper = OPcomma;
3839                 e.EV.E1 = e2.EV.E1;
3840                 e.EV.E1.Eoper = optoopeq(op3);
3841                 e2.EV.E1 = e1;
3842                 e1.Ety = e.EV.E1.Ety;
3843                 e2.Eoper = optoopeq(op2);
3844                 e2.Ety = e.Ety;
3845                 goto L1;
3846             }
3847 }
3848         }
3849 
3850         if (op2 == OPneg && el_match(e1,e2.EV.E1) && !el_sideeffect(e1))
3851         {
3852             // Replace (i = -i) with (negass i)
3853             e.Eoper = OPnegass;
3854             e.EV.E2 = null;
3855             el_free(e2);
3856             return optelem(e, GOALvalue);
3857         }
3858 
3859         // Replace (x = (y ? z : x)) with ((y && (x = z)),x)
3860         if (op2 == OPcond && el_match(e1,e2.EV.E2.EV.E2))
3861         {
3862             elem *e22 = e2.EV.E2;         // e22 is the OPcond
3863             e.Eoper = OPcomma;
3864             e.EV.E2 = e1;
3865             e.EV.E1 = e2;
3866             e2.Eoper = OPandand;
3867             e2.Ety = TYint;
3868             e22.Eoper = OPeq;
3869             e22.Ety = e.Ety;
3870             e1 = e22.EV.E1;
3871             e22.EV.E1 = e22.EV.E2;
3872             e22.EV.E2 = e1;
3873             return optelem(e,GOALvalue);
3874         }
3875 
3876         // Replace (x = (y ? x : z)) with ((y || (x = z)),x)
3877         if (op2 == OPcond && el_match(e1,e2.EV.E2.EV.E1))
3878         {
3879             elem *e22 = e2.EV.E2;         // e22 is the OPcond
3880             e.Eoper = OPcomma;
3881             e.EV.E2 = e1;
3882             e.EV.E1 = e2;
3883             e2.Eoper = OPoror;
3884             e2.Ety = TYint;
3885             e22.Eoper = OPeq;
3886             e22.Ety = e.Ety;
3887             return optelem(e,GOALvalue);
3888         }
3889 
3890         // If floating point, replace (x = -y) with (x = y ^ signbit)
3891         if (op2 == OPneg && (tyreal(e2.Ety) || tyimaginary(e2.Ety)) &&
3892             (e2.EV.E1.Eoper == OPvar || e2.EV.E1.Eoper == OPind) &&
3893            /* Turned off for XMM registers because they don't play well with
3894             * int registers.
3895             */
3896            !config.fpxmmregs)
3897         {
3898             tym_t ty;
3899 
3900             elem *es = el_calloc();
3901             es.Eoper = OPconst;
3902             switch (tysize(e2.Ety))
3903             {
3904                 case FLOATSIZE:
3905                     ty = TYlong;
3906                     es.EV.Vlong = 0x80000000;
3907                     break;
3908 
3909                 case DOUBLESIZE:
3910                     if (I32)
3911                     {
3912                         ty = TYllong;
3913                         es.EV.Vllong = 0x8000000000000000L;
3914                         break;
3915                     }
3916                     goto default;
3917 
3918                 default:
3919                     el_free(es);
3920                     goto L8;
3921             }
3922             es.Ety = ty;
3923             e1.Ety = ty;
3924             e2.Ety = ty;
3925             e2.EV.E1.Ety = ty;
3926             e2.EV.E2 = es;
3927             e2.Eoper = OPxor;
3928             return optelem(e,GOALvalue);
3929 
3930         L8:
3931         }
3932 
3933         // Replace (a=(r1 pair r2)) with (a1=r1), (a2=r2)
3934         if (tysize(e1.Ety) == 2 * REGSIZE &&
3935             e1.Eoper == OPvar &&
3936             (e2.Eoper == OPpair || e2.Eoper == OPrpair) &&
3937             goal == GOALnone &&
3938             !el_appears(e2, e1.EV.Vsym) &&
3939 // this clause needs investigation because the code doesn't match the comment
3940             // Disable this rewrite if we're using x87 and `e1` is a FP-value
3941             // but `e2` is not, or vice versa
3942             // https://issues.dlang.org/show_bug.cgi?id=18197
3943             (config.fpxmmregs ||
3944              (tyfloating(e2.EV.E1.Ety) != 0) == (tyfloating(e2.Ety) != 0))
3945            )
3946         {
3947             // printf("** before:\n"); elem_print(e); printf("\n");
3948             tym_t ty = (REGSIZE == 8) ? TYllong : TYint;
3949             if (tyfloating(e1.Ety) && REGSIZE >= 4)
3950                 ty = (REGSIZE == 8) ? TYdouble : TYfloat;
3951             ty |= e1.Ety & ~mTYbasic;
3952             e2.Ety = ty;
3953             e.Ety = ty;
3954             e1.Ety = ty;
3955             elem *eb = el_copytree(e1);
3956             eb.EV.Voffset += REGSIZE;
3957 
3958             if (e2.Eoper == OPpair)
3959             {
3960                 e.EV.E2 = e2.EV.E1;
3961                 eb = el_bin(OPeq,ty,eb,e2.EV.E2);
3962                 e2.EV.E1 = e;
3963                 e2.EV.E2 = eb;
3964             }
3965             else
3966             {
3967                 e.EV.E2 = e2.EV.E2;
3968                 eb = el_bin(OPeq,ty,eb,e2.EV.E1);
3969                 e2.EV.E1 = eb;
3970                 e2.EV.E2 = e;
3971             }
3972 
3973             e2.Eoper = OPcomma;
3974             // printf("** after:\n"); elem_print(e2); printf("\n");
3975             return optelem(e2,goal);
3976         }
3977 
3978         // Replace (a=b) with (a1=b1),(a2=b2)
3979         if (tysize(e1.Ety) == 2 * REGSIZE &&
3980             e1.Eoper == OPvar &&
3981             e2.Eoper == OPvar &&
3982             goal == GOALnone &&
3983             !tyfloating(e1.Ety) && !tyvector(e1.Ety)
3984            )
3985         {
3986             tym_t ty = (REGSIZE == 8) ? TYllong : TYint;
3987             ty |= e1.Ety & ~mTYbasic;
3988             e2.Ety = ty;
3989             e.Ety = ty;
3990             e1.Ety = ty;
3991 
3992             elem *eb = el_copytree(e);
3993             eb.EV.E1.EV.Voffset += REGSIZE;
3994             eb.EV.E2.EV.Voffset += REGSIZE;
3995 
3996             e = el_bin(OPcomma,ty,e,eb);
3997             return optelem(e,goal);
3998         }
3999     }
4000 
4001    if (e1.Eoper == OPcomma)
4002         return cgel_lvalue(e);
4003   if (e1.Eoper != OPbit)
4004         return e;
4005   if (e1.EV.E1.Eoper == OPcomma || OTassign(e1.EV.E1.Eoper))
4006         return cgel_lvalue(e);
4007 
4008     uint t = e.Ety;
4009     elem *l = e1.EV.E1;                           // lvalue
4010     elem *r = e.EV.E2;
4011     tym_t tyl = l.Ety;
4012     uint sz = tysize(tyl) * 8;
4013     uint w = (e1.EV.E2.EV.Vuns >> 8);        // width in bits of field
4014     targ_ullong m = (cast(targ_ullong)1 << w) - 1;  // mask w bits wide
4015     uint b = e1.EV.E2.EV.Vuns & 0xFF;        // bits to shift
4016 
4017     elem *l2;
4018     elem *r2;
4019     elem *eres =  el_bin(OPeq,t,
4020                 l,
4021                 el_bin(OPor,t,
4022                         el_bin(OPshl,t,
4023                                 (r2 = el_bin(OPand,t,r,el_long(t,m))),
4024                                 el_long(TYint,b)
4025                         ),
4026                         el_bin(OPand,t,
4027                                 (l2 = el_copytree(l)),
4028                                 el_long(t,~(m << b))
4029                         )
4030                 )
4031           );
4032     eres.Esrcpos = e.Esrcpos;           // save line information
4033     if (OPTIMIZER && w + b == sz)
4034         r2.EV.E2.EV.Vllong = ~ZEROLL;    // no need to mask if left justified
4035     if (wantres)
4036     {
4037         uint c;
4038         elem **pe;
4039         elem *e2;
4040 
4041         r = el_copytree(r);
4042         if (tyuns(tyl))                 /* uint bit field           */
4043         {
4044             e2 = el_bin(OPand,t,r,el_long(t,m));
4045             pe = &e2.EV.E1;
4046         }
4047         else                            /* signed bit field             */
4048         {
4049             OPER shift = OPshr;
4050             shift = OPashr;
4051             c = sz - w;                 /* e2 = (r << c) >> c           */
4052             e2 = el_bin(shift,t,el_bin(OPshl,tyl,r,el_long(TYint,c)),el_long(TYint,c));
4053             pe = &e2.EV.E1.EV.E1;
4054         }
4055         eres = el_bin(OPcomma,t,eres,e2);
4056         if (!OTleaf(r.Eoper))
4057             fixside(&(r2.EV.E1),pe);
4058     }
4059 
4060     if (!OTleaf(l.Eoper) && !OTleaf(l.EV.E1.Eoper))
4061         fixside(&(l2.EV.E1),&(l.EV.E1));
4062     e1.EV.E1 = e.EV.E2 = null;
4063     el_free(e);
4064     return optelem(eres,GOALvalue);
4065 }
4066 
4067 /**********************************
4068  */
4069 
4070 private elem * elnegass(elem *e, goal_t goal)
4071 {
4072     e = cgel_lvalue(e);
4073     return e;
4074 }
4075 
4076 /**************************
4077  * Add assignment. Replace bit field assignment with
4078  * equivalent tree.
4079  *             +=
4080  *            /  \
4081  *           /    r
4082  *        bit
4083  *       /   \
4084  *      l     w,b
4085  *
4086  * becomes:
4087  *                   =
4088  *                  / \
4089  *                 l   |
4090  *                    / \
4091  *                  <<   \
4092  *                 /  \   \
4093  *                &    b   &
4094  *               / \      / \
4095  *             op   m    l   ~(m<<b)
4096  *            /  \
4097  *           &    r
4098  *          / \
4099  *        >>   m
4100  *       /  \
4101  *      l    b
4102  */
4103 
4104 @trusted
4105 private elem * elopass(elem *e, goal_t goal)
4106 {
4107     elem *e1 = e.EV.E1;
4108     if (OTconv(e1.Eoper))
4109     {   e = fixconvop(e);
4110         return optelem(e,GOALvalue);
4111     }
4112 
4113     goal_t wantres = goal;
4114     if (e1.Eoper == OPbit)
4115     {
4116         const op = opeqtoop(e.Eoper);
4117 
4118         // Make sure t is uint
4119         // so >> doesn't have to be masked
4120         tym_t t = touns(e.Ety);
4121 
4122         assert(tyintegral(t));
4123         elem *l = e1.EV.E1;                       // lvalue
4124         tym_t tyl = l.Ety;
4125         elem *r = e.EV.E2;
4126         uint w = (e1.EV.E2.EV.Vuns >> 8) & 0xFF; // width in bits of field
4127         targ_llong m = (cast(targ_llong)1 << w) - 1;    // mask w bits wide
4128         uint b = e1.EV.E2.EV.Vuns & 0xFF;        // bits to shift
4129 
4130         elem* l2,l3,op2,eres;
4131 
4132         if (tyuns(tyl))
4133         {
4134             eres = el_bin(OPeq,t,
4135                     l,
4136                     el_bin(OPor,t,
4137                             (op2=el_bin(OPshl,t,
4138                                     el_bin(OPand,t,
4139                                             el_bin(op,t,
4140                                                     el_bin(OPand,t,
4141                                                         el_bin(OPshr,t,
4142                                                             (l2=el_copytree(l)),
4143                                                             el_long(TYint,b)
4144                                                         ),
4145                                                         el_long(t,m)
4146                                                     ),
4147                                                     r
4148                                             ),
4149                                             el_long(t,m)
4150                                     ),
4151                                     el_long(TYint,b)
4152                             )),
4153                             el_bin(OPand,t,
4154                                     l3=el_copytree(l),
4155                                     el_long(t,~(m << b))
4156                             )
4157                     )
4158                 );
4159 
4160             if (wantres)
4161             {
4162                 eres = el_bin(OPcomma,t,eres,el_copytree(op2.EV.E1));
4163                 fixside(&(op2.EV.E1),&(eres.EV.E2));
4164             }
4165         }
4166         else
4167         {   /* signed bit field
4168                rewrite to:      (l bit w,b) = ((l bit w,b) op r)
4169              */
4170             e.Eoper = OPeq;
4171             e.EV.E2 = el_bin(op,t,el_copytree(e1),r);
4172             if (l.Eoper == OPind)
4173                 fixside(&e.EV.E2.EV.E1.EV.E1.EV.E1,&l.EV.E1);
4174             eres = e;
4175             goto ret;
4176         }
4177 
4178         if (!OTleaf(l.Eoper) && !OTleaf(l.EV.E1.Eoper))
4179         {
4180             fixside(&(l2.EV.E1),&(l.EV.E1));
4181             el_free(l3.EV.E1);
4182             l3.EV.E1 = el_copytree(l.EV.E1);
4183         }
4184 
4185         e1.EV.E1 = e.EV.E2 = null;
4186         el_free(e);
4187     ret:
4188         e = optelem(eres,GOALvalue);
4189         return e;
4190     }
4191 
4192     {
4193         if (e1.Eoper == OPcomma || OTassign(e1.Eoper))
4194             e = cgel_lvalue(e);    // replace (e,v)op=e2 with e,(v op= e2)
4195         else
4196         {
4197             switch (e.Eoper)
4198             {
4199                 case OPmulass:
4200                     e = elmul(e,GOALvalue);
4201                     break;
4202 
4203                 case OPdivass:
4204                     // Replace r/=c with r=r/c
4205                     if (tycomplex(e.EV.E2.Ety) && !tycomplex(e1.Ety))
4206                     {
4207                         elem *ed;
4208                         e.Eoper = OPeq;
4209                         if (e1.Eoper == OPind)
4210                         {   // ed: *(tmp=e1.EV.E1)
4211                             // e1: *tmp
4212                             elem *tmp = el_alloctmp(e1.EV.E1.Ety);
4213                             ed = el_bin(OPeq, tmp.Ety, tmp, e1.EV.E1);
4214                             e1.EV.E1 = el_copytree(tmp);
4215                             ed = el_una(OPind, e1.Ety, ed);
4216                         }
4217                         else
4218                             ed = el_copytree(e1);
4219                         // e: e1=ed/e2
4220                         e.EV.E2 = el_bin(OPdiv, e.EV.E2.Ety, ed, e.EV.E2);
4221                         if (tyreal(e1.Ety))
4222                             e.EV.E2 = el_una(OPc_r, e1.Ety, e.EV.E2);
4223                         else
4224                             e.EV.E2 = el_una(OPc_i, e1.Ety, e.EV.E2);
4225                         return optelem(e, GOALvalue);
4226                     }
4227                     // Replace x/=y with x=x/y
4228                     if (OPTIMIZER &&
4229                         tyintegral(e.EV.E1.Ety) &&
4230                         e.EV.E1.Eoper == OPvar &&
4231                         !el_sideeffect(e.EV.E1))
4232                     {
4233                         e.Eoper = OPeq;
4234                         e.EV.E2 = el_bin(OPdiv, e.EV.E2.Ety, el_copytree(e.EV.E1), e.EV.E2);
4235                         return optelem(e, GOALvalue);
4236                     }
4237                     e = eldiv(e, GOALvalue);
4238                     break;
4239 
4240                 case OPmodass:
4241                     // Replace x%=y with x=x%y
4242                     if (OPTIMIZER &&
4243                         tyintegral(e.EV.E1.Ety) &&
4244                         e.EV.E1.Eoper == OPvar &&
4245                         !el_sideeffect(e.EV.E1))
4246                     {
4247                         e.Eoper = OPeq;
4248                         e.EV.E2 = el_bin(OPmod, e.EV.E2.Ety, el_copytree(e.EV.E1), e.EV.E2);
4249                         return optelem(e, GOALvalue);
4250                     }
4251                     break;
4252 
4253                 default:
4254                     break;
4255             }
4256         }
4257     }
4258     return e;
4259 }
4260 
4261 /**************************
4262  * Add assignment. Replace bit field post assignment with
4263  * equivalent tree.
4264  *      (l bit w,b) ++ r
4265  * becomes:
4266  *      (((l bit w,b) += r) - r) & m
4267  */
4268 
4269 @trusted
4270 private elem * elpost(elem *e, goal_t goal)
4271 {
4272     elem *e1 = e.EV.E1;
4273     if (e1.Eoper != OPbit)
4274     {
4275         if (e1.Eoper == OPcomma || OTassign(e1.Eoper))
4276             return cgel_lvalue(e);    // replace (e,v)op=e2 with e,(v op= e2)
4277         return e;
4278     }
4279 
4280     assert(e.EV.E2.Eoper == OPconst);
4281     targ_llong r = el_tolong(e.EV.E2);
4282 
4283     uint w = (e1.EV.E2.EV.Vuns >> 8) & 0xFF;  // width in bits of field
4284     targ_llong m = (cast(targ_llong)1 << w) - 1;     // mask w bits wide
4285 
4286     tym_t ty = e.Ety;
4287     if (e.Eoper != OPpostinc)
4288         r = -r;
4289     e.Eoper = (e.Eoper == OPpostinc) ? OPaddass : OPminass;
4290     e = el_bin(OPmin,ty,e,el_long(ty,r));
4291     if (tyuns(e1.EV.E1.Ety))             /* if uint bit field        */
4292         e = el_bin(OPand,ty,e,el_long(ty,m));
4293     return optelem(e,GOALvalue);
4294 }
4295 
4296 /***************************
4297  * Take care of compares.
4298  *      (e == 0) => (!e)
4299  *      (e != 0) => (bool e)
4300  */
4301 
4302 @trusted
4303 private elem * elcmp(elem *e, goal_t goal)
4304 {
4305     elem *e2 = e.EV.E2;
4306     elem *e1 = e.EV.E1;
4307 
4308     //printf("elcmp(%p)\n",e); elem_print(e);
4309 
4310     if (tyvector(e1.Ety))       // vectors don't give boolean result
4311         return e;
4312 
4313     if (OPTIMIZER)
4314     {
4315         auto op = e.Eoper;
4316 
4317         // Convert comparison of OPrelconsts of the same symbol to comparisons
4318         // of their offsets.
4319         if (e1.Eoper == OPrelconst && e2.Eoper == OPrelconst &&
4320             e1.EV.Vsym == e2.EV.Vsym)
4321         {
4322             e1.Eoper = OPconst;
4323             e1.Ety = TYptrdiff;
4324             e2.Eoper = OPconst;
4325             e2.Ety = TYptrdiff;
4326             return optelem(e,GOALvalue);
4327         }
4328 
4329         // Convert comparison of long pointers to comparison of integers
4330         if ((op == OPlt || op == OPle || op == OPgt || op == OPge) &&
4331             tyfv(e2.Ety) && tyfv(e1.Ety))
4332         {
4333             e.EV.E1 = el_una(OP32_16,e.Ety,e1);
4334             e.EV.E2 = el_una(OP32_16,e.Ety,e2);
4335             return optelem(e,GOALvalue);
4336         }
4337 
4338         // Convert ((e & 1) == 1) => (e & 1)
4339         if (op == OPeqeq && e2.Eoper == OPconst && e1.Eoper == OPand)
4340         {
4341             elem *e12 = e1.EV.E2;
4342 
4343             if (e12.Eoper == OPconst && el_tolong(e2) == 1 && el_tolong(e12) == 1)
4344             {
4345                 tym_t ty = e.Ety;
4346                 tym_t ty1 = e1.Ety;
4347                 e = el_selecte1(e);
4348                 e.Ety = ty1;
4349                 int sz = tysize(ty);
4350                 for (int sz1 = tysize(ty1); sz1 != sz; sz1 = tysize(e.Ety))
4351                 {
4352                     switch (sz1)
4353                     {
4354                         case 1:
4355                             e = el_una(OPu8_16,TYshort,e);
4356                             break;
4357                         case 2:
4358                             if (sz > 2)
4359                                 e = el_una(OPu16_32,TYlong,e);
4360                             else
4361                                 e = el_una(OP16_8,TYuchar,e);
4362                             break;
4363                         case 4:
4364                             if (sz > 2)
4365                                 e = el_una(OPu32_64,TYshort,e);
4366                             else
4367                                 e = el_una(OP32_16,TYshort,e);
4368                             break;
4369                         case 8:
4370                             e = el_una(OP64_32,TYlong,e);
4371                             break;
4372                         default:
4373                             assert(0);
4374                     }
4375                 }
4376                 e.Ety = ty;
4377                 return optelem(e,GOALvalue);
4378             }
4379         }
4380     }
4381 
4382     int uns = tyuns(e1.Ety) | tyuns(e2.Ety);
4383     if (cnst(e2))
4384     {
4385         tym_t tym;
4386         int sz = tysize(e2.Ety);
4387 
4388         if (e1.Eoper == OPu16_32 && e2.EV.Vulong <= cast(targ_ulong) SHORTMASK ||
4389             e1.Eoper == OPs16_32 &&
4390             e2.EV.Vlong == cast(targ_short) e2.EV.Vlong)
4391         {
4392             tym = (uns || e1.Eoper == OPu16_32) ? TYushort : TYshort;
4393             e.EV.E2 = el_una(OP32_16,tym,e2);
4394             goto L2;
4395         }
4396 
4397         /* Try to convert to byte/word comparison for ((x & c)==d)
4398            when mask c essentially casts x to a smaller type
4399          */
4400         if (OPTIMIZER &&
4401             e1.Eoper == OPand &&
4402             e1.EV.E2.Eoper == OPconst &&
4403             sz > CHARSIZE)
4404         {
4405             OPER op;
4406             assert(tyintegral(e2.Ety) || typtr(e2.Ety));
4407             /* ending up with byte ops in A regs */
4408             if (!(el_tolong(e2) & ~CHARMASK) &&
4409                 !(el_tolong(e1.EV.E2) & ~CHARMASK)
4410                )
4411             {
4412                 if (sz == LLONGSIZE)
4413                 {
4414                     e1.EV.E1 = el_una(OP64_32,TYulong,e1.EV.E1);
4415                     e1.EV.E1 = el_una(OP32_16,TYushort,e1.EV.E1);
4416                 }
4417                 else if (sz == LONGSIZE)
4418                     e1.EV.E1 = el_una(OP32_16,TYushort,e1.EV.E1);
4419                 tym = TYuchar;
4420                 op = OP16_8;
4421                 goto L4;
4422             }
4423             if (_tysize[TYint] == SHORTSIZE && /* not a win when regs are long */
4424                 sz == LONGSIZE &&
4425                 !(e2.EV.Vulong & ~SHORTMASK) &&
4426                 !(e1.EV.E2.EV.Vulong & ~SHORTMASK)
4427                )
4428             {
4429                 tym = TYushort;
4430                 op = OP32_16;
4431             L4:
4432                 e2.Ety = tym;
4433                 e1.Ety = tym;
4434                 e1.EV.E2.Ety = tym;
4435                 e1.EV.E1 = el_una(op,tym,e1.EV.E1);
4436                 e = optelem(e,GOALvalue);
4437                 goto ret;
4438             }
4439         }
4440 
4441         if (e1.Eoper == OPf_d && tysize(e1.Ety) == 8 && cast(targ_float)e2.EV.Vdouble == e2.EV.Vdouble)
4442         {
4443             /* Remove unnecessary OPf_d operator
4444              */
4445             e.EV.E1 = e1.EV.E1;
4446             e1.EV.E1 = null;
4447             el_free(e1);
4448             e2.Ety = e.EV.E1.Ety;
4449             e2.EV.Vfloat = cast(targ_float)e2.EV.Vdouble;
4450             return optelem(e,GOALvalue);
4451         }
4452 
4453         if (e1.Eoper == OPd_ld && tysize(e1.Ety) == tysize(TYldouble) && cast(targ_double)e2.EV.Vldouble == e2.EV.Vldouble)
4454         {
4455             /* Remove unnecessary OPd_ld operator
4456              */
4457             e.EV.E1 = e1.EV.E1;
4458             e1.EV.E1 = null;
4459             el_free(e1);
4460             e2.Ety = e.EV.E1.Ety;
4461             e2.EV.Vdouble = cast(targ_double)e2.EV.Vldouble;
4462             return optelem(e,GOALvalue);
4463         }
4464 
4465         /* Convert (ulong > uint.max) to (msw(ulong) != 0)
4466          */
4467         if (OPTIMIZER && I32 && e.Eoper == OPgt && sz == LLONGSIZE && e2.EV.Vullong == 0xFFFFFFFF)
4468         {
4469             e.Eoper = OPne;
4470             e2.Ety = TYulong;
4471             e2.EV.Vulong = 0;
4472             e.EV.E1 = el_una(OPmsw,TYulong,e1);
4473             e = optelem(e,GOALvalue);
4474             goto ret;
4475         }
4476 
4477         if (e1.Eoper == OPu8_16 && e2.EV.Vuns < 256 ||
4478             e1.Eoper == OPs8_16 &&
4479             e2.EV.Vint == cast(targ_schar) e2.EV.Vint)
4480         {
4481             tym = (uns || e1.Eoper == OPu8_16) ? TYuchar : TYschar;
4482             e.EV.E2 = el_una(OP16_8,tym,e2);
4483         L2:
4484             tym |= e1.Ety & ~mTYbasic;
4485             e.EV.E1 = el_selecte1(e1);
4486             e.EV.E1.Ety = tym;
4487             e = optelem(e,GOALvalue);
4488         }
4489         else if (!boolres(e2))
4490         {
4491             targ_int i;
4492             switch (e.Eoper)
4493             {
4494                 case OPle:              // (u <= 0) becomes (u == 0)
4495                     if (!uns)
4496                         break;
4497                     goto case OPeqeq;
4498 
4499                 case OPeqeq:
4500                     e.Eoper = OPnot;
4501                     goto L5;
4502 
4503                 case OPgt:              // (u > 0) becomes (u != 0)
4504                     if (!uns)
4505                         break;
4506                     goto case OPne;
4507 
4508                 case OPne:
4509                     e.Eoper = OPbool;
4510                 L5: el_free(e2);
4511                     e.EV.E2 = null;
4512                     e = optelem(e,GOALvalue);
4513                     break;
4514 
4515                 case OPge:
4516                     i = 1;              // (u >= 0) becomes (u,1)
4517                     goto L3;
4518 
4519                 case OPlt:              // (u < 0) becomes (u,0)
4520                     i = 0;
4521                 L3:
4522                     if (uns)
4523                     {
4524                         e2.EV.Vint = i;
4525                         e2.Ety = TYint;
4526                         e.Eoper = OPcomma;
4527                         e = optelem(e,GOALvalue);
4528                     }
4529                     else
4530                     {
4531                         if (tyintegral(e1.Ety) && sz == 2 * REGSIZE)
4532                         {
4533                             // Only need to examine MSW
4534                             tym_t ty = sz == 4 ? TYint :
4535                                        sz == 8 ? TYint :
4536                                                  TYlong;        // for TYcent's
4537                             e.EV.E1 = el_una(OPmsw, ty, e1);
4538                             e2.Ety = ty;
4539                             return optelem(e, GOALvalue);
4540                         }
4541                     }
4542                     break;
4543 
4544                 default:
4545                     break;
4546             }
4547         }
4548         else if (OPTIMIZER && uns && tysize(e2.Ety) == 2 &&
4549                  cast(ushort)e2.EV.Vuns == 0x8000 &&
4550                  (e.Eoper == OPlt || e.Eoper == OPge)
4551                 )
4552         {
4553             // Convert to signed comparison against 0
4554             tym_t ty = tybasic(e2.Ety);
4555             switch (_tysize[ty])
4556             {
4557                 case 1:     ty = TYschar;   break;
4558                 case 2:     ty = TYshort;   break;
4559                 default:    assert(0);
4560             }
4561             e.Eoper ^= (OPlt ^ OPge);      // switch between them
4562             e2.EV.Vuns = 0;
4563             e2.Ety = ty | (e2.Ety & ~mTYbasic);
4564             e1.Ety = ty | (e1.Ety & ~mTYbasic);
4565         }
4566         else if (OPTIMIZER && e1.Eoper == OPeq &&
4567                  e1.EV.E2.Eoper == OPconst)
4568         {    // Convert ((x = c1) rel c2) to ((x = c1),(c1 rel c2)
4569              elem *ec = el_copytree(e1.EV.E2);
4570              ec.Ety = e1.Ety;
4571              e.EV.E1 = ec;
4572              e = el_bin(OPcomma,e.Ety,e1,e);
4573              e = optelem(e,GOALvalue);
4574         }
4575     }
4576     else if ((
4577              (e1.Eoper == OPu8_16 ||
4578               e1.Eoper == OPs8_16)||
4579              (e1.Eoper == OPu16_32 ||
4580               e1.Eoper == OPs16_32)
4581              ) &&
4582              e1.Eoper == e2.Eoper)
4583     {
4584         if (uns)
4585         {
4586             e1.EV.E1.Ety = touns(e1.EV.E1.Ety);
4587             e2.EV.E1.Ety = touns(e2.EV.E1.Ety);
4588         }
4589         e1.Ety = e1.EV.E1.Ety;
4590         e2.Ety = e2.EV.E1.Ety;
4591         e.EV.E1 = el_selecte1(e1);
4592         e.EV.E2 = el_selecte1(e2);
4593         e = optelem(e,GOALvalue);
4594     }
4595 ret:
4596     return e;
4597 }
4598 
4599 /*****************************
4600  * Boolean operator.
4601  *      OPbool
4602  */
4603 
4604 @trusted
4605 private elem * elbool(elem *e, goal_t goal)
4606 {
4607     //printf("elbool()\n");
4608     elem* e1 = e.EV.E1;
4609     const op = e1.Eoper;
4610 
4611     if (OTlogical(op) ||
4612         // bool bool => bool
4613         (tybasic(e1.Ety) == TYbool && tysize(e.Ety) == 1)
4614        )
4615         return el_selecte1(e);
4616 
4617     switch (op)
4618     {
4619         case OPs32_d:
4620         case OPs16_d:
4621         case OPu16_d:
4622         case OPu32_d:
4623         case OPf_d:
4624         case OPd_ld:
4625         case OPs16_32:
4626         case OPu16_32:
4627         case OPu8_16:
4628         case OPs8_16:
4629         case OPu32_64:
4630         case OPs32_64:
4631         case OPvp_fp:
4632         case OPcvp_fp:
4633         case OPnp_fp:
4634             e1.Eoper = e.Eoper;
4635             return optelem(el_selecte1(e), goal);
4636 
4637         default:
4638             break;
4639     }
4640 
4641     if (OPTIMIZER)
4642     {
4643         int shift;
4644 
4645         // Replace bool(x,1) with (x,1),1
4646         e1 = elscancommas(e1);
4647         if (cnst(e1) || e1.Eoper == OPrelconst)
4648         {
4649             int i = boolres(e1) != 0;
4650             e.Eoper = OPcomma;
4651             e.EV.E2 = el_long(e.Ety,i);
4652             e = optelem(e,GOALvalue);
4653             return e;
4654         }
4655 
4656         // Replace bool(e & 1) with (uint char)(e & 1)
4657         else if (e.EV.E1.Eoper == OPand && e.EV.E1.EV.E2.Eoper == OPconst && el_tolong(e.EV.E1.EV.E2) == 1)
4658         {
4659         L1:
4660             uint sz = tysize(e.EV.E1.Ety);
4661             tym_t ty = e.Ety;
4662             switch (sz)
4663             {
4664                 case 1:
4665                     e = el_selecte1(e);
4666                     break;
4667 
4668                 case 2:
4669                     e.Eoper = OP16_8;
4670                     break;
4671 
4672                 case 4:
4673                     e.Eoper = OP32_16;
4674                     e.Ety = TYushort;
4675                     e = el_una(OP16_8, ty, e);
4676                     break;
4677 
4678                 case 8:
4679                     e.Eoper = OP64_32;
4680                     e.Ety = TYulong;
4681                     e = el_una(OP32_16, TYushort, e);
4682                     e = el_una(OP16_8, ty, e);
4683                     break;
4684 
4685                 default:
4686                     assert(0);
4687             }
4688             e = optelem(e,GOALvalue);
4689         }
4690 
4691         // Replace bool(e % 2) with (uint char)(e & 1)
4692         else if (e.EV.E1.Eoper == OPmod && e.EV.E1.EV.E2.Eoper == OPconst && el_tolong(e.EV.E1.EV.E2) == 2
4693             && !tyfloating(e.EV.E1.Ety)) // dont optimize fmod()
4694         {
4695             uint sz = tysize(e.EV.E1.Ety);
4696             tym_t ty = e.Ety;
4697             e.EV.E1.Eoper = OPand;
4698             e.EV.E1.EV.E2.EV.Vullong = 1;
4699             switch (sz)
4700             {
4701                 case 1:
4702                     e = el_selecte1(e);
4703                     break;
4704 
4705                 case 2:
4706                     e.Eoper = OP16_8;
4707                     break;
4708 
4709                 case 4:
4710                     e.Eoper = OP32_16;
4711                     e.Ety = TYushort;
4712                     e = el_una(OP16_8, ty, e);
4713                     break;
4714 
4715                 case 8:
4716                     e.Eoper = OP64_32;
4717                     e.Ety = TYulong;
4718                     e = el_una(OP32_16, TYushort, e);
4719                     e = el_una(OP16_8, ty, e);
4720                     break;
4721 
4722                 default:
4723                     assert(0);
4724             }
4725             e = optelem(e,GOALvalue);
4726         }
4727 
4728         // Replace bool((1<<c)&b) with -(b btst c)
4729         else if ((I32 || I64) &&
4730                  e.EV.E1.Eoper == OPand &&
4731                  e.EV.E1.EV.E1.Eoper == OPshl &&
4732                  e.EV.E1.EV.E1.EV.E1.Eoper == OPconst && el_tolong(e.EV.E1.EV.E1.EV.E1) == 1 &&
4733                  tysize(e.EV.E1.Ety) <= REGSIZE
4734                 )
4735         {
4736             tym_t ty = e.Ety;
4737             elem *ex = e.EV.E1.EV.E1;
4738             ex.Eoper = OPbtst;
4739             e.EV.E1.EV.E1 = null;
4740             ex.EV.E1 = e.EV.E1.EV.E2;
4741             e.EV.E1.EV.E2 = null;
4742             ex.Ety = e.Ety;
4743             el_free(e);
4744             e = ex;
4745             return optelem(e,GOALvalue);
4746         }
4747 
4748         // Replace bool(a & c) when c is a power of 2 with ((a >> shift) & 1)
4749         else if (e.EV.E1.Eoper == OPand &&
4750                  e.EV.E1.EV.E2.Eoper == OPconst &&
4751                  (shift = ispow2(el_tolong(e.EV.E1.EV.E2))) != -1
4752                 )
4753         {
4754             e.EV.E1.EV.E1 = el_bin(OPshr, e.EV.E1.EV.E1.Ety, e.EV.E1.EV.E1, el_long(TYint, shift));
4755             e.EV.E1.EV.E2.EV.Vullong = 1;
4756             goto L1;
4757         }
4758     }
4759     return e;
4760 }
4761 
4762 
4763 /*********************************
4764  * Conversions of pointers to far pointers.
4765  */
4766 
4767 @trusted
4768 private elem * elptrlptr(elem *e, goal_t goal)
4769 {
4770     if (e.EV.E1.Eoper == OPrelconst || e.EV.E1.Eoper == OPstring)
4771     {
4772         e.EV.E1.Ety = e.Ety;
4773         e = el_selecte1(e);
4774     }
4775     return e;
4776 }
4777 
4778 
4779 /*********************************
4780  * Conversions of handle pointers to far pointers.
4781  */
4782 @trusted
4783 private elem * elvptrfptr(elem *e, goal_t goal)
4784 {
4785     elem *e1 = e.EV.E1;
4786     if (e1.Eoper == OPadd || e1.Eoper == OPmin)
4787     {
4788         elem *e12 = e1.EV.E2;
4789         if (tybasic(e12.Ety) != TYvptr)
4790         {
4791             /* Rewrite (vtof(e11 + e12)) to (vtof(e11) + e12)   */
4792             const op = e.Eoper;
4793             e.Eoper = e1.Eoper;
4794             e.EV.E2 = e12;
4795             e1.Ety = e.Ety;
4796             e1.Eoper = cast(ubyte)op;
4797             e1.EV.E2 = null;
4798             e = optelem(e,GOALvalue);
4799         }
4800     }
4801     return e;
4802 }
4803 
4804 
4805 /************************
4806  * Optimize conversions of longs to ints.
4807  * Also used for (OPoffset) (TYfptr|TYvptr).
4808  * Also used for conversions of ints to bytes.
4809  */
4810 
4811 @trusted
4812 private elem * ellngsht(elem *e, goal_t goal)
4813 {
4814     //printf("ellngsht()\n");
4815     tym_t ty = e.Ety;
4816     elem *e1 = e.EV.E1;
4817     switch (e1.Eoper)
4818     {
4819     case OPs16_32:
4820     case OPu16_32:
4821     case OPu8_16:
4822     case OPs8_16:
4823         // This fix is not quite right. For example, it fails
4824         // if e.Ety != e.EV.E1.EV.E1.Ety. The difference is when
4825         // one is uint and the other isn't.
4826         if (tysize(ty) != tysize(e.EV.E1.EV.E1.Ety))
4827             break;
4828         e = el_selecte1(el_selecte1(e));
4829         e.Ety = ty;
4830         return e;
4831 
4832     case OPvar:                 // simply paint type of variable
4833         // Do not paint type of ints into bytes, as this causes
4834         // many CSEs to be missed, resulting in bad code.
4835         // Loading a word anyway is just as fast as loading a byte.
4836         // for 68000 byte is swapped, load byte != load word
4837         if (e.Eoper == OP16_8)
4838         {
4839             // Mark symbol as being used sometimes as a byte to
4840             // 80X86 - preclude using SI or DI
4841             // 68000 - preclude using An
4842             e1.EV.Vsym.Sflags |= GTbyte;
4843         }
4844         else
4845             e1.Ety = ty;
4846         e = el_selecte1(e);
4847         break;
4848 
4849     case OPind:
4850         e = el_selecte1(e);
4851         break;
4852 
4853     case OPnp_fp:
4854         if (e.Eoper != OPoffset)
4855             goto case_default;
4856         // Replace (offset)(ptrlptr)e11 with e11
4857         e = el_selecte1(el_selecte1(e));
4858         e.Ety = ty;                    // retain original type
4859         break;
4860 
4861     case OPbtst:
4862         e = el_selecte1(e);
4863         break;
4864 
4865     default: // operator
4866     case_default:
4867         // Attempt to replace (lngsht)(a op b) with
4868         // ((lngsht)a op (lngsht)b).
4869         // op is now an integer op, which is cheaper.
4870         if (OTwid(e1.Eoper) && !OTassign(e1.Eoper))
4871         {
4872             tym_t ty1 = e1.EV.E1.Ety;
4873             switch (e.Eoper)
4874             {
4875                 case OP16_8:
4876                     // Make sure e1.EV.E1 is of the type we're converting from
4877                     if (tysize(ty1) <= _tysize[TYint])
4878                     {
4879                         ty1 = (tyuns(ty1) ? TYuchar : TYschar) |
4880                                     (ty1 & ~mTYbasic);
4881                         e1.EV.E1 = el_una(e.Eoper,ty1,e1.EV.E1);
4882                     }
4883                     // Rvalue may be an int if it is a shift operator
4884                     if (OTbinary(e1.Eoper))
4885                     {   tym_t ty2 = e1.EV.E2.Ety;
4886 
4887                         if (tysize(ty2) <= _tysize[TYint])
4888                         {
4889                             ty2 = (tyuns(ty2) ? TYuchar : TYschar) |
4890                                         (ty2 & ~mTYbasic);
4891                             e1.EV.E2 = el_una(e.Eoper,ty2,e1.EV.E2);
4892                         }
4893                     }
4894                     break;
4895 
4896                 case OPoffset:
4897                     if (_tysize[TYint] == LONGSIZE)
4898                     {
4899                         // Make sure e1.EV.E1 is of the type we're converting from
4900                         if (tysize(ty1) > LONGSIZE)
4901                         {
4902                             ty1 = (tyuns(ty1) ? TYuint : TYint) | (ty1 & ~mTYbasic);
4903                             e1.EV.E1 = el_una(e.Eoper,ty1,e1.EV.E1);
4904                         }
4905                         // Rvalue may be an int if it is a shift operator
4906                         if (OTbinary(e1.Eoper))
4907                         {   tym_t ty2 = e1.EV.E2.Ety;
4908 
4909                             if (tysize(ty2) > LONGSIZE)
4910                             {
4911                                 ty2 = (tyuns(ty2) ? TYuint : TYint) |
4912                                             (ty2 & ~mTYbasic);
4913                                 e1.EV.E2 = el_una(e.Eoper,ty2,e1.EV.E2);
4914                             }
4915                         }
4916                         break;
4917                     }
4918                     goto case OP32_16;
4919 
4920                 case OP32_16:
4921                     // Make sure e1.EV.E1 is of the type we're converting from
4922                     if (tysize(ty1) == LONGSIZE)
4923                     {
4924                         ty1 = (tyuns(ty1) ? TYushort : TYshort) | (ty1 & ~mTYbasic);
4925                         e1.EV.E1 = el_una(e.Eoper,ty1,e1.EV.E1);
4926                     }
4927                     // Rvalue may be an int if it is a shift operator
4928                     if (OTbinary(e1.Eoper))
4929                     {   tym_t ty2 = e1.EV.E2.Ety;
4930 
4931                         if (tysize(ty2) == LONGSIZE)
4932                         {
4933                             ty2 = (tyuns(ty2) ? TYushort : TYshort) |
4934                                         (ty2 & ~mTYbasic);
4935                             e1.EV.E2 = el_una(e.Eoper,ty2,e1.EV.E2);
4936                         }
4937                     }
4938                     break;
4939 
4940                 default:
4941                     assert(0);
4942             }
4943             e1.Ety = ty;
4944             e = el_selecte1(e);
4945             again = 1;
4946             return e;
4947         }
4948         break;
4949     }
4950     return e;
4951 }
4952 
4953 
4954 /************************
4955  * Optimize conversions of long longs to ints.
4956  * OP64_32, OP128_64
4957  */
4958 
4959 @trusted
4960 private elem * el64_32(elem *e, goal_t goal)
4961 {
4962     tym_t ty = e.Ety;
4963     elem *e1 = e.EV.E1;
4964     switch (e1.Eoper)
4965     {
4966     case OPs32_64:
4967     case OPu32_64:
4968     case OPs64_128:
4969     case OPu64_128:
4970         if (tysize(ty) != tysize(e.EV.E1.EV.E1.Ety))
4971             break;
4972         e = el_selecte1(el_selecte1(e));
4973         e.Ety = ty;
4974         break;
4975 
4976     case OPpair:
4977         if (tysize(ty) != tysize(e.EV.E1.EV.E1.Ety))
4978             break;
4979         if (el_sideeffect(e1.EV.E2))
4980         {
4981             // Rewrite (OP64_32(a pair b)) as ((t=a),(b,t))
4982             elem *a = e1.EV.E1;
4983             elem *b = e1.EV.E2;
4984             elem *t = el_alloctmp(a.Ety);
4985 
4986             e.Eoper = OPcomma;
4987             e.EV.E1 = el_bin(OPeq,a.Ety,t,a);
4988             e.EV.E2 = e1;
4989 
4990             e1.Eoper = OPcomma;
4991             e1.EV.E1 = b;
4992             e1.EV.E2 = el_copytree(t);
4993             e1.Ety = e.Ety;
4994             break;
4995         }
4996         e = el_selecte1(el_selecte1(e));
4997         e.Ety = ty;
4998         break;
4999 
5000     case OPrpair:
5001         if (tysize(ty) != tysize(e.EV.E1.EV.E2.Ety))
5002             break;
5003         if (el_sideeffect(e1.EV.E1))
5004         {
5005             // Rewrite (OP64_32(a rpair b)) as (a,b)
5006             e = el_selecte1(e);
5007             e.Eoper = OPcomma;
5008             e.Ety = ty;
5009             break;
5010         }
5011         e = el_selecte2(el_selecte1(e));
5012         e.Ety = ty;
5013         break;
5014 
5015     case OPvar:                 // simply paint type of variable
5016     case OPind:
5017         e = el_selecte1(e);
5018         break;
5019 
5020     case OPshr:                 // OP64_32(x >> 32) => OPmsw(x)
5021         if (e1.EV.E2.Eoper == OPconst &&
5022             (e.Eoper == OP64_32 && el_tolong(e1.EV.E2) == 32 && !I64 ||
5023              e.Eoper == OP128_64 && el_tolong(e1.EV.E2) == 64 && I64)
5024            )
5025         {
5026             e.Eoper = OPmsw;
5027             e.EV.E1 = el_selecte1(e.EV.E1);
5028         }
5029         break;
5030 
5031     case OPmul:
5032         if (config.exe & (EX_OSX | EX_OSX64)) // https://issues.dlang.org/show_bug.cgi?id=21047
5033             break;
5034         else
5035             goto case;
5036 
5037     case OPadd:
5038     case OPmin:
5039     case OPor:
5040     case OPand:
5041     case OPxor:
5042         // OP64_32(a op b) => (OP64_32(a) op OP64_32(b))
5043         e1.EV.E1 = el_una(e.Eoper, ty, e1.EV.E1);
5044         e1.EV.E2 = el_una(e.Eoper, ty, e1.EV.E2);
5045         e = el_selecte1(e);
5046         break;
5047 
5048     default:
5049         break;
5050     }
5051     return e;
5052 }
5053 
5054 
5055 /*******************************
5056  * Convert complex to real.
5057  */
5058 
5059 @trusted
5060 private elem *elc_r(elem *e, goal_t goal)
5061 {
5062     elem *e1 = e.EV.E1;
5063 
5064     if (e1.Eoper == OPvar || e1.Eoper == OPind)
5065     {
5066         e1.Ety = e.Ety;
5067         e = el_selecte1(e);
5068     }
5069     return e;
5070 }
5071 
5072 /*******************************
5073  * Convert complex to imaginary.
5074  */
5075 
5076 @trusted
5077 private elem *elc_i(elem *e, goal_t goal)
5078 {
5079     elem *e1 = e.EV.E1;
5080 
5081     if (e1.Eoper == OPvar)
5082     {
5083         e1.Ety = e.Ety;
5084         e1.EV.Voffset += tysize(e.Ety);
5085         e = el_selecte1(e);
5086     }
5087     else if (e1.Eoper == OPind)
5088     {
5089         e1.Ety = e.Ety;
5090         e = el_selecte1(e);
5091         e.EV.E1 = el_bin(OPadd, e.EV.E1.Ety, e.EV.E1, el_long(TYint, tysize(e.Ety)));
5092         return optelem(e, GOALvalue);
5093     }
5094 
5095     return e;
5096 }
5097 
5098 /******************************
5099  * Handle OPu8_16 and OPs8_16.
5100  */
5101 
5102 @trusted
5103 private elem * elbyteint(elem *e, goal_t goal)
5104 {
5105     if (OTlogical(e.EV.E1.Eoper) || e.EV.E1.Eoper == OPbtst)
5106     {
5107         e.EV.E1.Ety = e.Ety;
5108         e = el_selecte1(e);
5109         return e;
5110     }
5111     return evalu8(e, goal);
5112 }
5113 
5114 /******************************
5115  * OPs32_64
5116  * OPu32_64
5117  */
5118 @trusted
5119 private elem * el32_64(elem *e, goal_t goal)
5120 {
5121     if (REGSIZE == 8 && e.EV.E1.Eoper == OPbtst)
5122     {
5123         e.EV.E1.Ety = e.Ety;
5124         e = el_selecte1(e);
5125         return e;
5126     }
5127     return evalu8(e, goal);
5128 }
5129 
5130 /****************************
5131  * Handle OPu64_d,
5132  *      OPd_ld OPu64_d,
5133  *      OPd_f OPu64_d
5134  */
5135 
5136 @trusted
5137 private elem *elu64_d(elem *e, goal_t goal)
5138 {
5139     tym_t ty;
5140     elem** pu;
5141     if (e.Eoper == OPu64_d)
5142     {
5143         pu = &e.EV.E1;
5144         ty = TYdouble;
5145     }
5146     else if (e.Eoper == OPd_ld && e.EV.E1.Eoper == OPu64_d)
5147     {
5148         pu = &e.EV.E1.EV.E1;
5149         *pu = optelem(*pu, GOALvalue);
5150         ty = TYldouble;
5151     }
5152     else if (e.Eoper == OPd_f && e.EV.E1.Eoper == OPu64_d)
5153     {
5154         pu = &e.EV.E1.EV.E1;
5155         *pu = optelem(*pu, GOALvalue);
5156         ty = TYfloat;
5157     }
5158 
5159     if (!pu || (*pu).Eoper == OPconst)
5160         return evalu8(e, goal);
5161 
5162     elem* u = *pu;
5163     if (config.fpxmmregs && I64 && (ty == TYfloat || ty == TYdouble))
5164     {
5165         /* Rewrite for SIMD as:
5166          *    u >= 0 ? OPs64_d(u) : OPs64_d((u >> 1) | (u & 1)) * 2
5167          */
5168         u.Ety = TYllong;
5169         elem *u1 = el_copytree(u);
5170         if (!OTleaf(u.Eoper))
5171             fixside(&u, &u1);
5172         elem *u2 = el_copytree(u1);
5173 
5174         u = el_bin(OPge, TYint, u, el_long(TYllong, 0));
5175 
5176         u1 = el_una(OPs64_d, TYdouble, u1);
5177         if (ty == TYfloat)
5178             u1 = el_una(OPd_f, TYfloat, u1);
5179 
5180         elem* u3 = el_copytree(u2);
5181         u2 = el_bin(OPshr, TYullong, u2, el_long(TYullong, 1));
5182         u3 = el_bin(OPand, TYullong, u3, el_long(TYullong, 1));
5183         u2 = el_bin(OPor, TYllong, u2, u3);
5184 
5185         u2 = el_una(OPs64_d, TYdouble, u2);
5186         if (ty == TYfloat)
5187             u2 = el_una(OPd_f, TYfloat, u2);
5188 
5189         u2 = el_bin(OPmul, ty, u2, el_long(ty, 2));
5190 
5191         elem* r = el_bin(OPcond, e.Ety, u, el_bin(OPcolon, e.Ety, u1, u2));
5192         *pu = null;
5193         el_free(e);
5194         return optelem(r, GOALvalue);
5195     }
5196     if (config.inline8087)
5197     {
5198         /* Rewrite for x87 as:
5199          *  u < 0 ? OPs64_d(u) : OPs64_d(u) + 0x1p+64
5200          */
5201         u.Ety = TYllong;
5202         elem *u1 = el_copytree(u);
5203         if (!OTleaf(u.Eoper))
5204             fixside(&u, &u1);
5205 
5206         elem* eop1 = el_una(OPs64_d, TYdouble, u1);
5207         eop1 = el_una(OPd_ld, TYldouble, eop1);
5208 
5209         elem* eoff = el_calloc();
5210         eoff.Eoper = OPconst;
5211         eoff.Ety = TYldouble;
5212         eoff.EV.Vldouble = 0x1p+64;
5213 
5214         elem* u2 = el_copytree(u1);
5215         u2 = el_una(OPs64_d, TYdouble, u2);
5216         u2 = el_una(OPd_ld, TYldouble, u2);
5217 
5218         elem* eop2 = el_bin(OPadd, TYldouble, u2, eoff);
5219 
5220         elem* r = el_bin(OPcond, TYldouble,
5221                         el_bin(OPge, OPbool, u, el_long(TYllong, 0)),
5222                         el_bin(OPcolon, TYldouble, eop1, eop2));
5223 
5224         if (ty != TYldouble)
5225             r = el_una(OPtoprec, e.Ety, r);
5226 
5227         *pu = null;
5228         el_free(e);
5229 
5230         return optelem(r, GOALvalue);
5231     }
5232 
5233     return evalu8(e, goal);
5234 }
5235 
5236 
5237 /************************
5238  * Handle <<, OProl and OPror
5239  */
5240 
5241 @trusted
5242 private elem *elshl(elem *e, goal_t goal)
5243 {
5244     tym_t ty = e.Ety;
5245     elem *e1 = e.EV.E1;
5246     elem *e2 = e.EV.E2;
5247 
5248     if (e1.Eoper == OPconst && !boolres(e1))             // if e1 is 0
5249     {
5250         e1.Ety = ty;
5251         e = el_selecte1(e);             // (0 << e2) => 0
5252     }
5253     else if (OPTIMIZER &&
5254         e2.Eoper == OPconst &&
5255         (e1.Eoper == OPshr || e1.Eoper == OPashr) &&
5256         e1.EV.E2.Eoper == OPconst &&
5257         el_tolong(e2) == el_tolong(e1.EV.E2))
5258     {   /* Rewrite:
5259          *  (x >> c) << c)
5260          * with:
5261          *  x & ~((1 << c) - 1);
5262          */
5263         targ_ullong c = el_tolong(e.EV.E2);
5264         e = el_selecte1(e);
5265         e = el_selecte1(e);
5266         e = el_bin(OPand, e.Ety, e, el_long(e.Ety, ~((1UL << c) - 1)));
5267         return optelem(e, goal);
5268     }
5269     return e;
5270 }
5271 
5272 /************************
5273  * Handle >>
5274  * OPshr, OPashr
5275  */
5276 
5277 @trusted
5278 private elem * elshr(elem *e, goal_t goal)
5279 {
5280     tym_t ty = e.Ety;
5281     elem *e1 = e.EV.E1;
5282     elem *e2 = e.EV.E2;
5283 
5284     // (x >> 16) replaced with ((shtlng) x+2)
5285     if (OPTIMIZER &&
5286         e2.Eoper == OPconst && e2.EV.Vshort == SHORTSIZE * 8 &&
5287         tysize(ty) == LONGSIZE)
5288     {
5289         if (e1.Eoper == OPvar)
5290         {
5291             Symbol *s = e1.EV.Vsym;
5292 
5293             if (s.Sclass != SC.fastpar && s.Sclass != SC.shadowreg)
5294             {
5295                 e1.EV.Voffset += SHORTSIZE; // address high word in long
5296                 if (I32)
5297                     // Cannot independently address high word of register
5298                     s.Sflags &= ~GTregcand;
5299                 goto L1;
5300             }
5301         }
5302         else if (e1.Eoper == OPind)
5303         {
5304             /* Replace (*p >> 16) with (shtlng)(*(&*p + 2))     */
5305             e.EV.E1 = el_una(OPind,TYshort,
5306                         el_bin(OPadd,e1.EV.E1.Ety,
5307                                 el_una(OPaddr,e1.EV.E1.Ety,e1),
5308                                 el_long(TYint,SHORTSIZE)));
5309         L1:
5310             e.Eoper = tyuns(e1.Ety) ? OPu16_32 : OPs16_32;
5311             el_free(e2);
5312             e.EV.E2 = null;
5313             e1.Ety = TYshort;
5314             e = optelem(e,GOALvalue);
5315         }
5316     }
5317 
5318     // (x >> 32) replaced with ((lngllng) x+4)
5319     if (e2.Eoper == OPconst && e2.EV.Vlong == LONGSIZE * 8 &&
5320         tysize(ty) == LLONGSIZE)
5321     {
5322         if (e1.Eoper == OPvar)
5323         {
5324             e1.EV.Voffset += LONGSIZE;      // address high dword in longlong
5325             if (I64)
5326                 // Cannot independently address high word of register
5327                 e1.EV.Vsym.Sflags &= ~GTregcand;
5328             goto L2;
5329         }
5330         else if (e1.Eoper == OPind)
5331         {
5332             // Replace (*p >> 32) with (lngllng)(*(&*p + 4))
5333             e.EV.E1 = el_una(OPind,TYlong,
5334                         el_bin(OPadd,e1.EV.E1.Ety,
5335                                 el_una(OPaddr,e1.EV.E1.Ety,e1),
5336                                 el_long(TYint,LONGSIZE)));
5337         L2:
5338             e.Eoper = tyuns(e1.Ety) ? OPu32_64 : OPs32_64;
5339             el_free(e2);
5340             e.EV.E2 = null;
5341             e1.Ety = TYlong;
5342             e = optelem(e,GOALvalue);
5343         }
5344     }
5345     return e;
5346 }
5347 
5348 /***********************************
5349  * Handle OPmsw.
5350  */
5351 
5352 @trusted
5353 elem *elmsw(elem *e, goal_t goal)
5354 {
5355     tym_t ty = e.Ety;
5356     elem *e1 = e.EV.E1;
5357 
5358     if (OPTIMIZER &&
5359         tysize(e1.Ety) == LLONGSIZE &&
5360         tysize(ty) == LONGSIZE)
5361     {
5362         // Replace (int)(msw (long)x) with (int)*(&x+4)
5363         if (e1.Eoper == OPvar)
5364         {
5365             e1.EV.Voffset += LONGSIZE;      // address high dword in longlong
5366             if (I64)
5367                 // Cannot independently address high word of register
5368                 e1.EV.Vsym.Sflags &= ~GTregcand;
5369             e1.Ety = ty;
5370             e = optelem(e1,GOALvalue);
5371         }
5372         // Replace (int)(msw (long)*x) with (int)*(&*x+4)
5373         else if (e1.Eoper == OPind)
5374         {
5375             e1 = el_una(OPind,ty,
5376                 el_bin(OPadd,e1.EV.E1.Ety,
5377                     el_una(OPaddr,e1.EV.E1.Ety,e1),
5378                     el_long(TYint,LONGSIZE)));
5379             e = optelem(e1,GOALvalue);
5380         }
5381         else
5382         {
5383             e = evalu8(e, goal);
5384         }
5385     }
5386     else if (OPTIMIZER && I64 &&
5387         tysize(e1.Ety) == CENTSIZE &&
5388         tysize(ty) == LLONGSIZE)
5389     {
5390         // Replace (long)(msw (cent)x) with (long)*(&x+8)
5391         if (e1.Eoper == OPvar)
5392         {
5393             e1.EV.Voffset += LLONGSIZE;      // address high dword in longlong
5394             e1.Ety = ty;
5395             e = optelem(e1,GOALvalue);
5396         }
5397         // Replace (long)(msw (cent)*x) with (long)*(&*x+8)
5398         else if (e1.Eoper == OPind)
5399         {
5400             e1 = el_una(OPind,ty,
5401                 el_bin(OPadd,e1.EV.E1.Ety,
5402                     el_una(OPaddr,e1.EV.E1.Ety,e1),
5403                     el_long(TYint,LLONGSIZE)));
5404             e = optelem(e1,GOALvalue);
5405         }
5406         else
5407         {
5408             e = evalu8(e, goal);
5409         }
5410     }
5411     else
5412     {
5413         e = evalu8(e, goal);
5414     }
5415 
5416     return e;
5417 }
5418 
5419 /***********************************
5420  * Handle OPpair, OPrpair.
5421  */
5422 
5423 @trusted
5424 elem *elpair(elem *e, goal_t goal)
5425 {
5426     //printf("elpair()\n");
5427     elem *e1 = e.EV.E1;
5428     if (e1.Eoper == OPconst)
5429     {
5430         e.EV.E1 = e.EV.E2;
5431         e.EV.E2 = e1;
5432         e.Eoper ^= OPpair ^ OPrpair;
5433     }
5434     return e;
5435 }
5436 
5437 /********************************
5438  * Handle OPddtor
5439  */
5440 
5441 elem *elddtor(elem *e, goal_t goal)
5442 {
5443     return e;
5444 }
5445 
5446 /********************************
5447  * Handle OPinfo, OPmark, OPctor, OPdtor
5448  */
5449 
5450 private elem * elinfo(elem *e, goal_t goal)
5451 {
5452     //printf("elinfo()\n");
5453     return e;
5454 }
5455 
5456 /********************************************
5457  */
5458 
5459 private elem * elclassinit(elem *e, goal_t goal)
5460 {
5461     return e;
5462 }
5463 
5464 /********************************************
5465  */
5466 
5467 @trusted
5468 private elem * elvalist(elem *e, goal_t goal)
5469 {
5470     assert(e.Eoper == OPva_start);
5471 
5472     if (funcsym_p.ty() & mTYnaked)
5473     {   // do not generate prolog
5474         el_free(e);
5475         e = el_long(TYint, 0);
5476         return e;
5477     }
5478 
5479     elem* ap = e.EV.E1;         // pointer to va_list
5480     elem* parmn = e.EV.E2;      // address of last named parameter
5481 
5482     if (I32)
5483     {
5484         // (OPva_start &va)
5485         // (OPeq (OPind E1) (OPptr lastNamed+T.sizeof))
5486         //elem_print(e);
5487 
5488         // Find last named parameter
5489         Symbol *lastNamed = null;
5490         Symbol *arguments_typeinfo = null;
5491         for (SYMIDX si = 0; si < globsym.length; si++)
5492         {
5493             Symbol *s = globsym[si];
5494 
5495             if (s.Sclass == SC.parameter || s.Sclass == SC.regpar)
5496                 lastNamed = s;
5497             if (s.Sident[0] == '_' && strcmp(s.Sident.ptr, "_arguments_typeinfo") == 0)
5498                 arguments_typeinfo = s;
5499         }
5500 
5501         if (!lastNamed)
5502             lastNamed = arguments_typeinfo;
5503 
5504         e.Eoper = OPeq;
5505         e.EV.E1 = el_una(OPind, TYnptr, ap);
5506         if (lastNamed)
5507         {
5508             e.EV.E2 = el_ptr(lastNamed);
5509             e.EV.E2.EV.Voffset = (type_size(lastNamed.Stype) + 3) & ~3;
5510         }
5511         else
5512             e.EV.E2 = el_long(TYnptr, 0);
5513         // elem_print(e);
5514 
5515         return e;
5516     }
5517 
5518 if (config.exe & EX_windos)
5519 {
5520     assert(config.exe == EX_WIN64); // va_start is not an intrinsic on 32-bit
5521 
5522     // (OPva_start &va)
5523     // (OPeq (OPind E1) (OPptr &lastNamed+8))
5524     //elem_print(e);
5525 
5526     // Find last named parameter
5527     Symbol *lastNamed = null;
5528     for (SYMIDX si = 0; si < globsym.length; si++)
5529     {
5530         Symbol *s = globsym[si];
5531 
5532         if (s.Sclass == SC.fastpar || s.Sclass == SC.shadowreg || s.Sclass == SC.parameter)
5533             lastNamed = s;
5534     }
5535 
5536     e.Eoper = OPeq;
5537     e.EV.E1 = el_una(OPind, TYnptr, ap);
5538     if (lastNamed)
5539     {
5540         e.EV.E2 = el_ptr(lastNamed);
5541         e.EV.E2.EV.Voffset = 8;
5542     }
5543     else
5544         e.EV.E2 = el_long(TYnptr, 0);
5545     //elem_print(e);
5546 
5547 }
5548 
5549 if (config.exe & EX_posix)
5550 {
5551     assert(I64); // va_start is not an intrinsic on 32-bit
5552     // (OPva_start &va)
5553     // (OPeq (OPind E1) __va_argsave+offset)
5554     //elem_print(e);
5555 
5556     // Find __va_argsave
5557     Symbol *va_argsave = null;
5558     for (SYMIDX si = 0; si < globsym.length; si++)
5559     {
5560         Symbol *s = globsym[si];
5561         if (s.Sident[0] == '_' && strcmp(s.Sident.ptr, "__va_argsave") == 0)
5562         {
5563             va_argsave = s;
5564             break;
5565         }
5566     }
5567 
5568     e.Eoper = OPeq;
5569     e.EV.E1 = el_una(OPind, TYnptr, ap);
5570     if (va_argsave)
5571     {
5572         e.EV.E2 = el_ptr(va_argsave);
5573         e.EV.E2.EV.Voffset = 6 * 8 + 8 * 16; // offset to struct __va_list_tag defined in sysv_x64.d
5574         return el_combine(prolog_genva_start(va_argsave, parmn.EV.Vsym), e);
5575     }
5576     else
5577         e.EV.E2 = el_long(TYnptr, 0);
5578     //elem_print(e);
5579 }
5580 
5581     return e;
5582 }
5583 
5584 /******************************************
5585  * OPparam
5586  */
5587 
5588 @trusted
5589 private void elparamx(elem *e)
5590 {
5591     //printf("elparam()\n");
5592     if (e.EV.E1.Eoper == OPrpair)
5593     {
5594         e.EV.E1.Eoper = OPparam;
5595     }
5596     else if (e.EV.E1.Eoper == OPpair && !el_sideeffect(e.EV.E1))
5597     {
5598         e.EV.E1.Eoper = OPparam;
5599         elem *ex = e.EV.E1.EV.E2;
5600         e.EV.E1.EV.E2 = e.EV.E1.EV.E1;
5601         e.EV.E1.EV.E1 = ex;
5602     }
5603     else
5604     {
5605         static if (0)
5606         {
5607             // Unfortunately, these don't work because if the last parameter
5608             // is a pair, and it is a D function, the last parameter will get
5609             // passed in EAX.
5610             if (e.EV.E2.Eoper == OPrpair)
5611             {
5612                 e.EV.E2.Eoper = OPparam;
5613             }
5614             else if (e.EV.E2.Eoper == OPpair)
5615             {
5616                 e.EV.E2.Eoper = OPparam;
5617                 elem *ex = e.EV.E2.EV.E2;
5618                 e.EV.E2.EV.E2 = e.EV.E2.EV.E1;
5619                 e.EV.E2.EV.E1 = ex;
5620             }
5621         }
5622     }
5623 }
5624 
5625 @trusted
5626 private elem * elparam(elem *e, goal_t goal)
5627 {
5628     if (!OPTIMIZER)
5629     {
5630         if (!I64)
5631             elparamx(e);
5632     }
5633     return e;
5634 }
5635 
5636 /********************************
5637  * Optimize an element. This routine is recursive!
5638  * Be careful not to do this if VBEs have been done (else the VBE
5639  * work will be undone), or if DAGs have been built (will crash if
5640  * there is more than one parent for an elem).
5641  * If (goal)
5642  *      we care about the result.
5643  */
5644 
5645 @trusted
5646 private elem * optelem(elem *e, goal_t goal)
5647 {
5648 beg:
5649     //__gshared uint count;
5650     //printf("count: %u\n", ++count);
5651     //{ printf("xoptelem: %p %s goal x%x\n",e, oper_str(e.Eoper), goal); }
5652     assert(e);
5653     elem_debug(e);
5654     assert(e.Ecount == 0);             // no CSEs
5655 
5656     if (OPTIMIZER)
5657     {
5658         if (goal)
5659             e.Nflags &= ~NFLnogoal;
5660         else
5661             e.Nflags |= NFLnogoal;
5662     }
5663 
5664     auto op = e.Eoper;
5665     if (OTleaf(op))                     // if not an operator node
5666     {
5667         if (goal || OTsideff(op) || e.Ety & (mTYvolatile | mTYshared))
5668         {
5669             return e;
5670         }
5671         else
5672         {
5673             retnull:
5674                 el_free(e);
5675                 return null;
5676         }
5677     }
5678     else if (OTbinary(op))              // if binary operator
5679     {
5680         /* Determine goals for left and right subtrees  */
5681         goal_t leftgoal = GOALvalue;
5682         goal_t rightgoal = (goal || OTsideff(op)) ? GOALvalue : GOALnone;
5683         switch (op)
5684         {
5685             case OPcomma:
5686             {
5687                 elem *e1 = e.EV.E1 = optelem(e.EV.E1,GOALnone);
5688 //              if (e1 && !OTsideff(e1.Eoper))
5689 //                  e1 = e.EV.E1 = optelem(e1, GOALnone);
5690                 elem *e2 = e.EV.E2 = optelem(e.EV.E2,goal);
5691                 if (!e1)
5692                 {
5693                     if (!e2)
5694                         goto retnull;
5695                     if (!goal)
5696                         e.Ety = e.EV.E2.Ety;
5697                     e = el_selecte2(e);
5698                     return e;
5699                 }
5700                 if (!e2)
5701                 {
5702                     e.Ety = e.EV.E1.Ety;
5703                     return el_selecte1(e);
5704                 }
5705                 if (!goal)
5706                     e.Ety = e2.Ety;
5707                 return e;
5708             }
5709 
5710             case OPcond:
5711                 if (!goal)
5712                 {   // Transform x?y:z into x&&y or x||z
5713                     elem *e2 = e.EV.E2;
5714                     if (!el_sideeffect(e2.EV.E1))
5715                     {
5716                         e.Eoper = OPoror;
5717                         e.EV.E2 = el_selecte2(e2);
5718                         e.Ety = TYint;
5719                         goto beg;
5720                     }
5721                     else if (!el_sideeffect(e2.EV.E2))
5722                     {
5723                         e.Eoper = OPandand;
5724                         e.EV.E2 = el_selecte1(e2);
5725                         e.Ety = TYint;
5726                         goto beg;
5727                     }
5728                     assert(e2.Eoper == OPcolon || e2.Eoper == OPcolon2);
5729                     elem *e21 = e2.EV.E1 = optelem(e2.EV.E1, goal);
5730                     elem *e22 = e2.EV.E2 = optelem(e2.EV.E2, goal);
5731                     if (!e21)
5732                     {
5733                         if (!e22)
5734                         {
5735                             e = el_selecte1(e);
5736                             goto beg;
5737                         }
5738                         // Rewrite (e1 ? null : e22) as (e1 || e22)
5739                         e.Eoper = OPoror;
5740                         e.EV.E2 = el_selecte2(e2);
5741                         goto beg;
5742                     }
5743                     if (!e22)
5744                     {
5745                         // Rewrite (e1 ? e21 : null) as (e1 && e21)
5746                         e.Eoper = OPandand;
5747                         e.EV.E2 = el_selecte1(e2);
5748                         goto beg;
5749                     }
5750                     if (!rightgoal)
5751                         rightgoal = GOALvalue;
5752                 }
5753                 goto Llog;
5754 
5755             case OPoror:
5756                 if (rightgoal)
5757                     rightgoal = GOALflags;
5758                 if (OPTIMIZER && optim_loglog(e))
5759                     goto beg;
5760                 goto Llog;
5761 
5762             case OPandand:
5763                 if (rightgoal)
5764                     rightgoal = GOALflags;
5765                 if (OPTIMIZER && optim_loglog(e))
5766                     goto beg;
5767                 goto Llog;
5768 
5769             Llog:               // case (c log f()) with no goal
5770                 if (goal || el_sideeffect(e.EV.E2))
5771                     leftgoal = GOALflags;
5772                 break;
5773 
5774             default:
5775                 leftgoal = rightgoal;
5776                 break;
5777 
5778             case OPcolon:
5779             case OPcolon2:
5780                 if (!goal && !el_sideeffect(e))
5781                     goto retnull;
5782                 leftgoal = rightgoal;
5783                 break;
5784 
5785             case OPmemcmp:
5786                 if (!goal)
5787                 {   // So OPmemcmp is removed cleanly
5788                     assert(e.EV.E1.Eoper == OPparam);
5789                     e.EV.E1.Eoper = OPcomma;
5790                 }
5791                 leftgoal = rightgoal;
5792                 break;
5793 
5794             case OPcall:
5795             case OPcallns:
5796             {
5797                 const tyf = tybasic(e.EV.E1.Ety);
5798                 leftgoal = rightgoal;
5799                 elem *e1 = e.EV.E1 = optelem(e.EV.E1, leftgoal);
5800 
5801                 // Need argument to type_zeroSize()
5802                 const tyf_save = global_tyf;
5803                 global_tyf = tyf;
5804                 elem *e2 = e.EV.E2 = optelem(e.EV.E2, rightgoal);
5805                 global_tyf = tyf_save;
5806 
5807                 if (!e1)
5808                 {
5809                     if (!e2)
5810                         goto retnull;
5811                     return el_selecte2(e);
5812                 }
5813                 if (!e2)
5814                 {
5815                     if (!leftgoal)
5816                         e.Ety = e1.Ety;
5817                     return el_selecte1(e);
5818                 }
5819                 return (*elxxx[op])(e, goal);
5820             }
5821         }
5822 
5823         elem *e1 = e.EV.E1;
5824         if (OTassign(op))
5825         {
5826             elem *ex = e1;
5827             while (OTconv(ex.Eoper))
5828                 ex = ex.EV.E1;
5829             if (ex.Eoper == OPbit)
5830                 ex.EV.E1 = optelem(ex.EV.E1, leftgoal);
5831             else if (e1.Eoper == OPu64_d)
5832                 e1.EV.E1 = optelem(e1.EV.E1, leftgoal);
5833             else if ((e1.Eoper == OPd_ld || e1.Eoper == OPd_f) && e1.EV.E1.Eoper == OPu64_d)
5834                 e1.EV.E1.EV.E1 = optelem(e1.EV.E1.EV.E1, leftgoal);
5835             else
5836                 e1 = e.EV.E1 = optelem(e1,leftgoal);
5837         }
5838         else
5839             e1 = e.EV.E1 = optelem(e1,leftgoal);
5840 
5841         if ((op == OPandand || op == OPoror || op == OPcond) && e1) // short circuit evaluations
5842         {
5843             switch (op)
5844             {
5845                 case OPandand:
5846                     if (iffalse(e1))
5847                     {
5848                         // Do not evaluate E2
5849                         el_free(e.EV.E2);
5850                         e.EV.E2 = null;
5851                         e.Eoper = OPbool;
5852                         goto beg;
5853                     }
5854                     break;
5855 
5856                 case OPoror:
5857                     if (iftrue(e1))
5858                     {
5859                         // Do not evaluate E2
5860                         el_free(e.EV.E2);
5861                         e.EV.E2 = null;
5862                         e.Eoper = OPbool;
5863                         goto beg;
5864                     }
5865                     break;
5866 
5867                 case OPcond:
5868                     if (iftrue(e1))
5869                     {
5870                         e.EV.E2 = el_selecte1(e.EV.E2);
5871                         e.EV.E2.Ety = e.Ety;
5872                         e.EV.E2.ET = e.ET;
5873                         e.Eoper = OPcomma;
5874                         goto beg;
5875                     }
5876                     if (iffalse(e1))
5877                     {
5878                         e.EV.E2 = el_selecte2(e.EV.E2);
5879                         e.EV.E2.Ety = e.Ety;
5880                         e.EV.E2.ET = e.ET;
5881                         e.Eoper = OPcomma;
5882                         goto beg;
5883                     }
5884                     break;
5885 
5886                 default:
5887                     assert(0);
5888             }
5889         }
5890 
5891         elem *e2 = e.EV.E2 = optelem(e.EV.E2,rightgoal);
5892         if (!e1)
5893         {
5894             if (!e2)
5895                 goto retnull;
5896             return el_selecte2(e);
5897         }
5898         if (!e2)
5899         {
5900             if (!leftgoal)
5901                 e.Ety = e1.Ety;
5902             return el_selecte1(e);
5903         }
5904 
5905         if (op == OPparam && !goal)
5906             e.Eoper = OPcomma; // DMD bug 6733
5907 
5908         if (cnst(e1) && cnst(e2))
5909         {
5910             e = evalu8(e, GOALvalue);
5911             return e;
5912         }
5913         if (OPTIMIZER)
5914         {
5915             if (OTassoc(op))
5916             {
5917                 /* Replace (a op1 (b op2 c)) with ((a op2 b) op1 c)
5918                    (this must come before the leaf swapping, or we could cause
5919                    infinite loops)
5920                  */
5921                 if (e2.Eoper == op &&
5922                     e2.EV.E2.Eoper == OPconst &&
5923                     tysize(e2.EV.E1.Ety) == tysize(e2.EV.E2.Ety) &&
5924                     (!tyfloating(e1.Ety) || e1.Ety == e2.Ety)
5925                    )
5926                 {
5927                   e.EV.E1 = e2;
5928                   e.EV.E2 = e2.EV.E2;
5929                   e2.EV.E2 = e2.EV.E1;
5930                   e2.EV.E1 = e1;
5931                   if (op == OPadd)  /* fix types                    */
5932                   {
5933                       e1 = e.EV.E1;
5934                       if (typtr(e1.EV.E2.Ety))
5935                           e1.Ety = e1.EV.E2.Ety;
5936                       else
5937                           /* suppose a and b are ints, and c is a pointer   */
5938                           /* then this will fix the type of op2 to be int   */
5939                           e1.Ety = e1.EV.E1.Ety;
5940                   }
5941                   goto beg;
5942                 }
5943 
5944                 // Replace ((a op c1) op c2) with (a op (c2 op c1))
5945                 if (e1.Eoper == op &&
5946                     e2.Eoper == OPconst &&
5947                     e1.EV.E2.Eoper == OPconst &&
5948                     e1.EV.E1.Eoper != OPconst &&
5949                     tysize(e2.Ety) == tysize(e1.EV.E2.Ety))
5950                 {
5951                     e.EV.E1 = e1.EV.E1;
5952                     e1.EV.E1 = e2;
5953                     e1.Ety = e2.Ety;
5954                     e.EV.E2 = e1;
5955 
5956                     if (tyfloating(e1.Ety))
5957                     {
5958                         e1 = evalu8(e1, GOALvalue);
5959                         if (!OTleaf(e1.Eoper))        // if failed to fold the constants
5960                         {   // Undo the changes so we don't infinite loop
5961                             e.EV.E2 = e1.EV.E1;
5962                             e1.EV.E1 = e.EV.E1;
5963                             e.EV.E1 = e1;
5964                         }
5965                         else
5966                         {   e.EV.E2 = e1;
5967                             goto beg;
5968                         }
5969                     }
5970                     else
5971                         goto beg;
5972                 }
5973           }
5974 
5975           if (!OTrtol(op) && op != OPparam && op != OPcolon && op != OPcolon2 &&
5976               e1.Eoper == OPcomma)
5977           {     // Convert ((a,b) op c) to (a,(b op c))
5978                 e1.EV.E2.Ety = e1.Ety;
5979                 e1.EV.E2.ET = e1.ET;
5980 
5981                 e1.Ety = e.Ety;
5982                 e1.ET = e.ET;
5983 
5984                 e.EV.E1 = e1.EV.E2;
5985                 e1.EV.E2 = e;
5986                 e = e1;
5987                 goto beg;
5988           }
5989         }
5990 
5991         if (OTcommut(op))                // if commutative
5992         {
5993               /* see if we should swap the leaves       */
5994               enum MARS = true;
5995               if (
5996                 MARS ? (
5997                 cost(e2) > cost(e1) &&
5998                 !(tyvector(e1.Ety) && op == OPgt)
5999                 /* Swap only if order of evaluation can be proved
6000                  * to not matter, as we must evaluate Left-to-Right
6001                  */
6002                 && e1.canHappenAfter(e2)
6003                  )
6004                  : cost(e2) > cost(e1) && !(tyvector(e1.Ety) && op == OPgt)
6005                  )
6006               {
6007                     e.EV.E1 = e2;
6008                     e2 = e.EV.E2 = e1;
6009                     e1 = e.EV.E1;         // reverse the leaves
6010                     op = e.Eoper = cast(ubyte)swaprel(op);
6011               }
6012               if (OTassoc(op))          // if commutative and associative
6013               {
6014                   if (!OTleaf(e1.Eoper) &&
6015                       op == e1.Eoper &&
6016                       e1.EV.E2.Eoper == OPconst &&
6017                       e.Ety == e1.Ety &&
6018                       tysize(e1.EV.E2.Ety) == tysize(e2.Ety)
6019 
6020                       // Reordering floating point can change the semantics
6021                       && (!MARS || !tyfloating(e1.Ety))
6022                      )
6023                   {
6024                         // look for ((e op c1) op c2),
6025                         // replace with (e op (c1 op c2))
6026                         if (e2.Eoper == OPconst)
6027                         {
6028                             e.EV.E1 = e1.EV.E1;
6029                             e.EV.E2 = e1;
6030                             e1.EV.E1 = e1.EV.E2;
6031                             e1.EV.E2 = e2;
6032                             e1.Ety = e2.Ety;
6033 
6034                             e1 = e.EV.E1;
6035                             e2 = e.EV.E2 = evalu8(e.EV.E2, GOALvalue);
6036                         }
6037                         else
6038                         {   // Replace ((e op c) op e2) with ((e op e2) op c)
6039                             e.EV.E2 = e1.EV.E2;
6040                             e1.EV.E2 = e2;
6041                             e2 = e.EV.E2;
6042                         }
6043                   }
6044               }
6045         }
6046 
6047         if (e2.Eoper == OPconst &&             // if right operand is a constant
6048             !(OTopeq(op) && OTconv(e1.Eoper))
6049            )
6050         {
6051             debug assert(!(OTeop0e(op) && (OTeop00(op))));
6052             if (OTeop0e(op))            /* if e1 op 0 => e1             */
6053             {
6054                 if (!boolres(e2))       /* if e2 is 0                   */
6055                 {
6056                     // Don't do it for ANSI floating point
6057                     if (tyfloating(e1.Ety) && !(config.flags4 & CFG4fastfloat))
6058                     { }
6059                     // Don't do it if we're assembling a complex value
6060                     else if ((tytab[e.EV.E1.Ety & 0xFF] ^
6061                          tytab[e.EV.E2.Ety & 0xFF]) == (TYFLreal | TYFLimaginary))
6062                     { }
6063                     else
6064                         return optelem(el_selecte1(e),goal);
6065                 }
6066             }
6067             else if (OTeop00(op) && !boolres(e2) && !tyfloating(e.Ety))
6068             {
6069                 if (OTassign(op))
6070                     op = e.Eoper = OPeq;
6071                 else
6072                     op = e.Eoper = OPcomma;
6073             }
6074 
6075             if (OTeop1e(op))            /* if e1 op 1 => e1             */
6076             {
6077                 if (elemisone(e2) && !tyimaginary(e2.Ety))
6078                     return optelem(el_selecte1(e),goal);
6079             }
6080         }
6081 
6082         if (OTpost(op) && !goal)
6083         {
6084             op = e.Eoper = (op == OPpostinc) ? OPaddass : OPminass;
6085         }
6086   }
6087   else /* unary operator */
6088   {
6089         elem* e1 = e.EV.E1;
6090 
6091         /* op(a,b) => a,(op b)
6092          */
6093         if (e1.Eoper == OPcomma && op != OPstrpar && op != OPddtor)
6094         {
6095             e.Eoper = e1.Eoper;
6096             e.EV.E1 = e1.EV.E1;
6097             e.EV.E2 = e1;
6098             e1.Eoper = op;
6099             e1.Ety = e.Ety;
6100             e1.ET = e.ET;
6101             e1.EV.E1 = e1.EV.E2;
6102             e1.EV.E2 = null;
6103             return optelem(e, goal);
6104         }
6105 
6106         assert(!e.EV.E2 || op == OPinfo || op == OPddtor);
6107         if (!goal && !OTsideff(op) && !(e.Ety & (mTYvolatile | mTYshared)))
6108         {
6109             tym_t tym = e1.Ety;
6110 
6111             e = el_selecte1(e);
6112             e.Ety = tym;
6113             return optelem(e,GOALnone);
6114         }
6115 
6116         if ((op == OPd_f || op == OPd_ld) && e1.Eoper == OPu64_d)
6117         {
6118             return elu64_d(e, goal);
6119         }
6120 
6121         e1 = e.EV.E1 = optelem(e1, (op == OPddtor)
6122                                      ? GOALnone
6123                                      : (op == OPbool || op == OPnot) ? GOALflags : GOALvalue);
6124         if (!e1)
6125             goto retnull;
6126         if (e1.Eoper == OPconst)
6127         {
6128             if (!(op == OPnp_fp && el_tolong(e1) != 0))
6129                 return evalu8(e, GOALvalue);
6130         }
6131   }
6132 
6133 //  if (debugb)
6134 //  {   print("optelem: %p %s\n",e, oper_str(op)); }
6135 
6136     static if (0)
6137     {
6138         printf("xoptelem: %p %s\n", e, oper_str(e.Eoper));
6139         elem_print(e);
6140         e = (*elxxx[op])(e, goal);
6141         printf("After:\n");
6142         elem_print(e);
6143         return e;
6144     }
6145     else
6146     {
6147         return (*elxxx[op])(e, goal);
6148     }
6149 }
6150 
6151 
6152 /********************************
6153  * Optimize and canonicalize an expression tree.
6154  * Fiddle with double operators so that the rvalue is a pointer
6155  * (this is needed by the 8086 code generator).
6156  *
6157  *         op                      op
6158  *        /  \                    /  \
6159  *      e1    e2                e1    ,
6160  *                                   / \
6161  *                                  =   &
6162  *                                 / \   \
6163  *                               fr   e2  fr
6164  *
6165  *      e1 op (*p)              e1 op p
6166  *      e1 op c                 e1 op &dc
6167  *      e1 op v                 e1 op &v
6168  */
6169 
6170 @trusted
6171 elem *doptelem(elem *e, goal_t goal)
6172 {
6173     //printf("doptelem(e = %p, goal = x%x)\n", e, goal);
6174     assert(!PARSER);
6175     do
6176     {   again = false;
6177         topair = false;
6178         e = optelem(e,goal & (GOALflags | GOALvalue | GOALnone));
6179     } while (again && goal & GOALagain && e);
6180 
6181     /* If entire expression is a struct, and we can replace it with     */
6182     /* something simpler, do so.                                        */
6183     if (goal & GOALstruct && e && (tybasic(e.Ety) == TYstruct || tybasic(e.Ety) == TYarray))
6184         e = elstruct(e, goal);
6185 
6186     if (topair && e)
6187         e = elToPair(e);
6188 
6189     return e;
6190 }
6191 
6192 /****************************************
6193  * Do optimizations after bltailrecursion() and before common subexpressions.
6194  */
6195 
6196 @trusted
6197 void postoptelem(elem *e)
6198 {
6199     Srcpos pos = {0};
6200 
6201     elem_debug(e);
6202     while (1)
6203     {
6204         if (OTunary(e.Eoper))
6205         {
6206             /* This is necessary as the optimizer tends to lose this information
6207              */
6208             if (e.Esrcpos.Slinnum > pos.Slinnum)
6209                 pos = e.Esrcpos;
6210 
6211             if (e.Eoper == OPind)
6212             {
6213                 if (e.EV.E1.Eoper == OPconst &&
6214                     /* Allow TYfgptr to reference GS:[0000] etc.
6215                      */
6216                     tybasic(e.EV.E1.Ety) == TYnptr)
6217                 {
6218                     /* Disallow anything in the range [0..4096]
6219                      * Let volatile pointers dereference null
6220                      */
6221                     const targ_ullong v = el_tolong(e.EV.E1);
6222                     if (v < 4096 && !(e.Ety & mTYvolatile))
6223                     {
6224                         error(pos.Sfilename, pos.Slinnum, pos.Scharnum, "null dereference in function %s", funcsym_p.Sident.ptr);
6225                         e.EV.E1.EV.Vlong = 4096;     // suppress redundant messages
6226                     }
6227                 }
6228             }
6229             e = e.EV.E1;
6230         }
6231         else if (OTbinary(e.Eoper))
6232         {
6233             /* This is necessary as the optimizer tends to lose this information
6234              */
6235             if (e.Esrcpos.Slinnum > pos.Slinnum)
6236                 pos = e.Esrcpos;
6237 
6238             if (e.Eoper == OPparam)
6239             {
6240                 if (!I64)
6241                     elparamx(e);
6242             }
6243             postoptelem(e.EV.E2);
6244             e = e.EV.E1;
6245         }
6246         else
6247             break;
6248     }
6249 }
6250 
6251 /***********************************
6252  * Rewrite rvalues of complex numbers to pairs of floating point numbers.
6253  */
6254 @trusted
6255 private elem *elToPair(elem *e)
6256 {
6257     switch (e.Eoper)
6258     {
6259         case OPvar:
6260         {
6261             /* Rewrite complex number loads as a pair of loads
6262              * e => (e.0 pair e.offset)
6263              */
6264             tym_t ty0;
6265             tym_t ty = e.Ety;
6266             if (ty & (mTYxmmgpr | mTYgprxmm))
6267                 break; // register allocation doesn't support it yet.
6268             switch (tybasic(ty))
6269             {
6270                 case TYcfloat:      ty0 = TYfloat  | (ty & ~mTYbasic); goto L1;
6271                 case TYcdouble:     ty0 = TYdouble | (ty & ~mTYbasic); goto L1;
6272                 L1:
6273                     if (_tysize[tybasic(ty0)] < REGSIZE)
6274                         break;                          // func parameters, for example, can't handle this
6275                     e.Ety = ty0;
6276                     elem *e2 = el_copytree(e);
6277                     e2.EV.Voffset += _tysize[tybasic(ty0)];
6278                     return el_bin(OPpair, ty, e, e2);
6279 
6280                 default:
6281                     break;
6282             }
6283             break;
6284         }
6285 
6286         case OPind:
6287         {
6288             e.EV.E1 = elToPair(e.EV.E1);
6289             /* Rewrite complex number loads as a pair of loads
6290              * *e1 => (*e1 pair *(e1 + offset))
6291              */
6292             tym_t ty0;
6293             tym_t ty = e.Ety;
6294             if (ty & (mTYxmmgpr | mTYgprxmm))
6295                 break; // register allocation doesn't support it yet.
6296             switch (tybasic(ty))
6297             {
6298                 case TYcfloat:      ty0 = TYfloat  | (ty & ~mTYbasic); goto L2;
6299                 case TYcdouble:     ty0 = TYdouble | (ty & ~mTYbasic); goto L2;
6300                 L2:
6301                     if (_tysize[tybasic(ty0)] < REGSIZE)
6302                         break;                          // func parameters, for example, can't handle this
6303                     e.Ety = ty0;
6304                     elem *e2 = el_copytree(e.EV.E1);
6305                     if (el_sideeffect(e2))
6306                         fixside(&e.EV.E1, &e2);
6307                     e2 = el_bin(OPadd,e2.Ety,e2,el_long(TYsize, _tysize[tybasic(ty0)]));
6308                     e2 = el_una(OPind, ty0, e2);
6309                     return el_bin(OPpair, ty, e, e2);
6310 
6311                 default:
6312                     break;
6313             }
6314             break;
6315         }
6316 
6317         default:
6318             if (OTassign(e.Eoper))
6319             {
6320                 // Skip over OPvar and OPind lvalues
6321                 if (OTbinary(e.Eoper))
6322                     e.EV.E2 = elToPair(e.EV.E2);
6323                 if (e.EV.E1.Eoper == OPvar)
6324                 {
6325                 }
6326                 else if (e.EV.E1.Eoper == OPind)
6327                     e.EV.E1.EV.E1 = elToPair(e.EV.E1.EV.E1);
6328                 else
6329                     e.EV.E1 = elToPair(e.EV.E1);
6330             }
6331             else if (OTunary(e.Eoper))
6332             {
6333                 e.EV.E1 = elToPair(e.EV.E1);
6334             }
6335             else if (OTbinary(e.Eoper))
6336             {
6337                 e.EV.E2 = elToPair(e.EV.E2);
6338                 e.EV.E1 = elToPair(e.EV.E1);
6339             }
6340             break;
6341     }
6342     return e;
6343 }
6344 
6345 /******************************************
6346  * Determine if `b` can be moved before `a` without disturbing
6347  * order-of-evaluation semantics.
6348  */
6349 
6350 @trusted
6351 private bool canHappenAfter(elem* a, elem* b)
6352 {
6353     return a.Eoper == OPconst ||
6354            a.Eoper == OPrelconst ||
6355 
6356            /* a is a variable that is not aliased
6357             * and is not assigned to in b
6358             */
6359            (a.Eoper == OPvar && a.EV.Vsym.Sflags & SFLunambig && !el_appears(b, a.EV.Vsym)) ||
6360 
6361            !(el_sideeffect(a) || el_sideeffect(b));
6362 }
6363 
6364 
6365 /***************************************************
6366  * Call table, index is OPER
6367  */
6368 
6369 private alias elfp_t = elem *function(elem *, goal_t) nothrow;
6370 
6371 private immutable elfp_t[OPMAX] elxxx =
6372 [
6373     OPunde:    &elerr,
6374     OPadd:     &eladd,
6375     OPmul:     &elmul,
6376     OPand:     &elbitwise,
6377     OPmin:     &elmin,
6378     OPnot:     &elnot,
6379     OPcom:     &elcom,
6380     OPcond:    &elcond,
6381     OPcomma:   &elcomma,
6382     OPremquo:  &elremquo,
6383     OPdiv:     &eldiv,
6384     OPmod:     &elmod,
6385     OPxor:     &elxor,
6386     OPstring:  &elstring,
6387     OPrelconst: &elzot,
6388     OPinp:     &elzot,
6389     OPoutp:    &elzot,
6390     OPasm:     &elzot,
6391     OPinfo:    &elinfo,
6392     OPdctor:   &elzot,
6393     OPddtor:   &elddtor,
6394     OPctor:    &elinfo,
6395     OPdtor:    &elinfo,
6396     OPmark:    &elinfo,
6397     OPvoid:    &elzot,
6398     OPhalt:    &elzot,
6399     OPnullptr: &elerr,
6400     OPpair:    &elpair,
6401     OPrpair:   &elpair,
6402 
6403     OPor:      &elor,
6404     OPoror:    &eloror,
6405     OPandand:  &elandand,
6406     OProl:     &elshl,
6407     OPror:     &elshl,
6408     OPshl:     &elshl,
6409     OPshr:     &elshr,
6410     OPashr:    &elshr,
6411     OPbit:     &elbit,
6412     OPind:     &elind,
6413     OPaddr:    &eladdr,
6414     OPneg:     &elneg,
6415     OPuadd:    &elzot,
6416     OPabs:     &evalu8,
6417     OPsqrt:    &evalu8,
6418     OPsin:     &evalu8,
6419     OPcos:     &evalu8,
6420     OPscale:   &elzot,
6421     OPyl2x:    &elzot,
6422     OPyl2xp1:  &elzot,
6423     OPcmpxchg:     &elzot,
6424     OPtoprec:  &elzot,
6425     OPrint:    &evalu8,
6426     OPrndtol:  &evalu8,
6427     OPstrlen:  &elzot,
6428     OPstrcpy:  &elstrcpy,
6429     OPmemcpy:  &elmemcpy,
6430     OPmemset:  &elmemset,
6431     OPstrcat:  &elzot,
6432     OPstrcmp:  &elstrcmp,
6433     OPmemcmp:  &elmemcmp,
6434     OPsetjmp:  &elzot,
6435     OPnegass:  &elnegass,
6436     OPpreinc:  &elzot,
6437     OPpredec:  &elzot,
6438     OPstreq:   &elstruct,
6439     OPpostinc: &elpost,
6440     OPpostdec: &elpost,
6441     OPeq:      &eleq,
6442     OPaddass:  &elopass,
6443     OPminass:  &elopass,
6444     OPmulass:  &elopass,
6445     OPdivass:  &elopass,
6446     OPmodass:  &elopass,
6447     OPshrass:  &elopass,
6448     OPashrass: &elopass,
6449     OPshlass:  &elopass,
6450     OPandass:  &elopass,
6451     OPxorass:  &elopass,
6452     OPorass:   &elopass,
6453 
6454     OPle:      &elcmp,
6455     OPgt:      &elcmp,
6456     OPlt:      &elcmp,
6457     OPge:      &elcmp,
6458     OPeqeq:    &elcmp,
6459     OPne:      &elcmp,
6460 
6461     OPunord:   &elcmp,
6462     OPlg:      &elcmp,
6463     OPleg:     &elcmp,
6464     OPule:     &elcmp,
6465     OPul:      &elcmp,
6466     OPuge:     &elcmp,
6467     OPug:      &elcmp,
6468     OPue:      &elcmp,
6469     OPngt:     &elcmp,
6470     OPnge:     &elcmp,
6471     OPnlt:     &elcmp,
6472     OPnle:     &elcmp,
6473     OPord:     &elcmp,
6474     OPnlg:     &elcmp,
6475     OPnleg:    &elcmp,
6476     OPnule:    &elcmp,
6477     OPnul:     &elcmp,
6478     OPnuge:    &elcmp,
6479     OPnug:     &elcmp,
6480     OPnue:     &elcmp,
6481 
6482     OPvp_fp:   &elvptrfptr,
6483     OPcvp_fp:  &elvptrfptr,
6484     OPoffset:  &ellngsht,
6485     OPnp_fp:   &elptrlptr,
6486     OPnp_f16p: &elzot,
6487     OPf16p_np: &elzot,
6488 
6489     OPs16_32:  &evalu8,
6490     OPu16_32:  &evalu8,
6491     OPd_s32:   &evalu8,
6492     OPb_8:     &evalu8,
6493     OPs32_d:   &evalu8,
6494     OPd_s16:   &evalu8,
6495     OPs16_d:   &evalu8,
6496     OPd_u16:   &evalu8,
6497     OPu16_d:   &evalu8,
6498     OPd_u32:   &evalu8,
6499     OPu32_d:   &evalu8,
6500     OP32_16:   &ellngsht,
6501     OPd_f:     &evalu8,
6502     OPf_d:     &evalu8,
6503     OPd_ld:    &evalu8,
6504     OPld_d:    &evalu8,
6505     OPc_r:     &elc_r,
6506     OPc_i:     &elc_i,
6507     OPu8_16:   &elbyteint,
6508     OPs8_16:   &elbyteint,
6509     OP16_8:    &ellngsht,
6510     OPu32_64:  &el32_64,
6511     OPs32_64:  &el32_64,
6512     OP64_32:   &el64_32,
6513     OPu64_128: &evalu8,
6514     OPs64_128: &evalu8,
6515     OP128_64:  &el64_32,
6516     OPmsw:     &elmsw,
6517 
6518     OPd_s64:   &evalu8,
6519     OPs64_d:   &evalu8,
6520     OPd_u64:   &evalu8,
6521     OPu64_d:   &elu64_d,
6522     OPld_u64:  &evalu8,
6523     OPparam:   &elparam,
6524     OPsizeof:  &elzot,
6525     OParrow:   &elzot,
6526     OParrowstar: &elzot,
6527     OPcolon:   &elzot,
6528     OPcolon2:  &elzot,
6529     OPbool:    &elbool,
6530     OPcall:    &elcall,
6531     OPucall:   &elcall,
6532     OPcallns:  &elcall,
6533     OPucallns: &elcall,
6534     OPstrpar:  &elstruct,
6535     OPstrctor: &elzot,
6536     OPstrthis: &elzot,
6537     OPconst:   &elerr,
6538     OPvar:     &elerr,
6539     OPreg:     &elerr,
6540     OPnew:     &elerr,
6541     OPanew:    &elerr,
6542     OPdelete:  &elerr,
6543     OPadelete: &elerr,
6544     OPbrack:   &elerr,
6545     OPframeptr: &elzot,
6546     OPgot:     &elzot,
6547 
6548     OPbsf:     &elzot,
6549     OPbsr:     &elzot,
6550     OPbtst:    &elzot,
6551     OPbt:      &elzot,
6552     OPbtc:     &elzot,
6553     OPbtr:     &elzot,
6554     OPbts:     &elzot,
6555 
6556     OPbswap:   &evalu8,
6557     OPpopcnt:  &evalu8,
6558     OPvector:  &elzot,
6559     OPvecsto:  &elzot,
6560     OPvecfill: &elzot,
6561     OPva_start: &elvalist,
6562     OPprefetch: &elzot,
6563 ];