"Fossies" - the Fresh Open Source Software Archive

Member "dmd2/src/dmd/dmd/backend/cgelem.d" (20 Nov 2020, 187870 Bytes) of package /linux/misc/dmd.2.094.2.linux.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) D source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /**
    2  * Compiler implementation of the
    3  * $(LINK2 http://www.dlang.org, D programming language).
    4  *
    5  * Does strength reduction optimizations on the elem trees,
    6  * i.e. rewriting trees to less expensive trees.
    7  *
    8  * Copyright:   Copyright (C) 1985-1998 by Symantec
    9  *              Copyright (C) 2000-2020 by The D Language Foundation, All Rights Reserved
   10  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
   11  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
   12  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/cgelem.d, backend/cgelem.d)
   13  * Documentation:  https://dlang.org/phobos/dmd_backend_cgelem.html
   14  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/backend/cgelem.d
   15  *              Add coverage tests to https://github.com/dlang/dmd/blob/master/test/runnable/testcgelem.d
   16  */
   17 
   18 module dmd.backend.cgelem;
   19 
   20 version (SPP)
   21 {
   22 }
   23 else
   24 {
   25 
   26 import core.stdc.stdio;
   27 import core.stdc.stdlib;
   28 import core.stdc.string;
   29 
   30 import dmd.backend.cc;
   31 import dmd.backend.code;
   32 import dmd.backend.cdef;
   33 import dmd.backend.code_x86;
   34 import dmd.backend.oper;
   35 import dmd.backend.global;
   36 import dmd.backend.goh;
   37 import dmd.backend.el;
   38 import dmd.backend.outbuf;
   39 import dmd.backend.rtlsym;
   40 import dmd.backend.ty;
   41 import dmd.backend.type;
   42 
   43 import dmd.backend.dlist;
   44 import dmd.backend.dvec;
   45 
   46 version (SCPP)
   47     import tk.mem;
   48 else
   49 {
   50     extern (C)
   51     {
   52         nothrow void *mem_calloc(size_t);
   53     }
   54 }
   55 
   56 extern (C++):
   57 
   58 nothrow:
   59 
   60 elem * evalu8(elem *e, goal_t goal);
   61 
   62 
   63 /* Masks so we can easily check size */
   64 enum CHARMASK  = 0xFF;
   65 enum SHORTMASK = 0xFFFF;
   66 enum INTMASK   = SHORTMASK;
   67 enum LONGMASK  = 0xFFFFFFFF;
   68 
   69 /* Common constants often checked for */
   70 enum LLONGMASK = 0xFFFFFFFFFFFFFFFFL;
   71 enum ZEROLL    = 0L;
   72 
   73 private __gshared
   74 {
   75     bool again;
   76     bool topair;
   77     tym_t global_tyf;
   78 }
   79 
   80 private bool cnst(const elem* e) { return e.Eoper == OPconst; }
   81 int REGSIZE();
   82 
   83 version (MARS)
   84 {
   85     import dmd.backend.errors;
   86 }
   87 
   88 /*****************************
   89  */
   90 
   91 private elem * cgel_lvalue(elem *e)
   92 {
   93     //printf("cgel_lvalue()\n"); elem_print(e);
   94     elem *e1 = e.EV.E1;
   95     if (e1.Eoper == OPbit)
   96     {
   97         elem *e11 = e1.EV.E1;
   98 
   99         if (e11.Eoper == OPcomma)
  100         {
  101             // Replace (((e,v) bit x) op e2) with (e,((v bit x) op e2))
  102             e1.EV.E1 = e11.EV.E2;
  103             e11.EV.E2 = e;
  104             e11.Ety = e.Ety;
  105             e11.ET = e.ET;
  106             e = e11;
  107             goto L1;
  108         }
  109         else if (OTassign(e11.Eoper))
  110         {
  111             // Replace (((e op= v) bit x) op e2) with ((e op= v) , ((e bit x) op e2))
  112             e1.EV.E1 = el_copytree(e11.EV.E1);
  113             e = el_bin(OPcomma,e.Ety,e11,e);
  114             goto L1;
  115         }
  116     }
  117     else if (e1.Eoper == OPcomma)
  118     {
  119         // Replace ((e,v) op e2) with (e,(v op e2))
  120         const op = e.Eoper;
  121         e.Eoper = OPcomma;
  122         e1.Eoper = op;
  123         e1.Ety = e.Ety;
  124         e1.ET = e.ET;
  125         e.EV.E1 = e1.EV.E1;
  126         e1.EV.E1 = e1.EV.E2;
  127         e1.EV.E2 = e.EV.E2;
  128         e.EV.E2 = e1;
  129         goto L1;
  130     }
  131     else if (OTassign(e1.Eoper))
  132     {
  133         // Replace ((e op= v) op e2) with ((e op= v) , (e op e2))
  134         e.EV.E1 = el_copytree(e1.EV.E1);
  135         e = el_bin(OPcomma,e.Ety,e1,e);
  136     L1:
  137         e = optelem(e,GOALvalue);
  138     }
  139     return e;
  140 }
  141 
  142 
  143 /******************************
  144  * Scan down commas.
  145  */
  146 
  147 private elem * elscancommas(elem *e)
  148 {
  149     while (e.Eoper == OPcomma
  150            || e.Eoper == OPinfo
  151           )
  152         e = e.EV.E2;
  153     return e;
  154 }
  155 
  156 /*************************
  157  * Returns:
  158  *    true if elem is the constant 1.
  159  */
  160 
  161 int elemisone(elem *e)
  162 {
  163     if (e.Eoper == OPconst)
  164     {
  165         switch (tybasic(e.Ety))
  166         {
  167             case TYchar:
  168             case TYuchar:
  169             case TYschar:
  170             case TYchar16:
  171             case TYshort:
  172             case TYushort:
  173             case TYint:
  174             case TYuint:
  175             case TYlong:
  176             case TYulong:
  177             case TYllong:
  178             case TYullong:
  179             case TYnullptr:
  180             case TYsptr:
  181             case TYcptr:
  182             case TYhptr:
  183             case TYfptr:
  184             case TYvptr:
  185             case TYnptr:
  186             case TYimmutPtr:
  187             case TYsharePtr:
  188             case TYrestrictPtr:
  189             case TYfgPtr:
  190             case TYbool:
  191             case TYwchar_t:
  192             case TYdchar:
  193                 if (el_tolong(e) != 1)
  194                     goto nomatch;
  195                 break;
  196             case TYldouble:
  197             case TYildouble:
  198                 if (e.EV.Vldouble != 1)
  199                     goto nomatch;
  200                 break;
  201             case TYdouble:
  202             case TYidouble:
  203             case TYdouble_alias:
  204                 if (e.EV.Vdouble != 1)
  205                         goto nomatch;
  206                 break;
  207             case TYfloat:
  208             case TYifloat:
  209                 if (e.EV.Vfloat != 1)
  210                         goto nomatch;
  211                 break;
  212             default:
  213                 goto nomatch;
  214         }
  215         return true;
  216     }
  217 
  218 nomatch:
  219     return false;
  220 }
  221 
  222 /*************************
  223  * Returns: true if elem is the constant -1.
  224  */
  225 
  226 int elemisnegone(elem *e)
  227 {
  228     if (e.Eoper == OPconst)
  229     {
  230         switch (tybasic(e.Ety))
  231         {
  232             case TYchar:
  233             case TYuchar:
  234             case TYschar:
  235             case TYchar16:
  236             case TYshort:
  237             case TYushort:
  238             case TYint:
  239             case TYuint:
  240             case TYlong:
  241             case TYulong:
  242             case TYllong:
  243             case TYullong:
  244             case TYnullptr:
  245             case TYnptr:
  246             case TYsptr:
  247             case TYcptr:
  248             case TYhptr:
  249             case TYfptr:
  250             case TYvptr:
  251             case TYimmutPtr:
  252             case TYsharePtr:
  253             case TYrestrictPtr:
  254             case TYfgPtr:
  255             case TYbool:
  256             case TYwchar_t:
  257             case TYdchar:
  258                 if (el_tolong(e) != -1)
  259                     goto nomatch;
  260                 break;
  261             case TYldouble:
  262             //case TYildouble:
  263                 if (e.EV.Vldouble != -1)
  264                     goto nomatch;
  265                 break;
  266             case TYdouble:
  267             //case TYidouble:
  268             case TYdouble_alias:
  269                 if (e.EV.Vdouble != -1)
  270                         goto nomatch;
  271                 break;
  272             case TYfloat:
  273             //case TYifloat:
  274                 if (e.EV.Vfloat != -1)
  275                         goto nomatch;
  276                 break;
  277             default:
  278                 goto nomatch;
  279         }
  280         return true;
  281     }
  282 
  283 nomatch:
  284     return false;
  285 }
  286 
  287 /**********************************
  288  * Swap relational operators (like if we swapped the leaves).
  289  */
  290 
  291 OPER swaprel(OPER op)
  292 {
  293     assert(op < OPMAX);
  294     if (OTrel(op))
  295         op = rel_swap(op);
  296     return op;
  297 }
  298 
  299 /**************************
  300  * Replace e1 by t=e1, replace e2 by t.
  301  */
  302 
  303 private void fixside(elem **pe1,elem **pe2)
  304 {
  305     const tym = (*pe1).Ety;
  306     elem *tmp = el_alloctmp(tym);
  307     *pe1 = el_bin(OPeq,tym,tmp,*pe1);
  308     elem *e2 = el_copytree(tmp);
  309     el_free(*pe2);
  310     *pe2 = e2;
  311 }
  312 
  313 
  314 
  315 /****************************
  316  * Compute the 'cost' of evaluating a elem. Could be done
  317  * as Sethi-Ullman numbers, but that ain't worth the bother.
  318  * We'll fake it.
  319  */
  320 
  321 private int cost(const elem* n) { return opcost[n.Eoper]; }
  322 
  323 /*******************************
  324  * For floating point expressions, the cost would be the number
  325  * of registers in the FPU stack needed.
  326  */
  327 
  328 private int fcost(const elem *e)
  329 {
  330     int cost;
  331 
  332     //printf("fcost()\n");
  333     switch (e.Eoper)
  334     {
  335         case OPadd:
  336         case OPmin:
  337         case OPmul:
  338         case OPdiv:
  339         {
  340             const int cost1 = fcost(e.EV.E1);
  341             const int cost2 = fcost(e.EV.E2);
  342             cost = cost2 + 1;
  343             if (cost1 > cost)
  344                 cost = cost1;
  345             break;
  346         }
  347 
  348         case OPcall:
  349         case OPucall:
  350             cost = 8;
  351             break;
  352 
  353         case OPneg:
  354         case OPabs:
  355         case OPtoprec:
  356             return fcost(e.EV.E1);
  357 
  358         case OPvar:
  359         case OPconst:
  360         case OPind:
  361         default:
  362             return 1;
  363     }
  364     if (cost > 8)
  365         cost = 8;
  366     return cost;
  367 }
  368 
  369 /*******************************
  370  * The lvalue of an op= is a conversion operator. Since the code
  371  * generator cannot handle this, we will have to fix it here. The
  372  * general strategy is:
  373  *      (conv) e1 op= e2        =>      e1 = (conv) e1 op e2
  374  * Since e1 can only be evaluated once, if it is an expression we
  375  * must use a temporary.
  376  */
  377 
  378 private elem *fixconvop(elem *e)
  379 {
  380     static immutable ubyte[CNVOPMAX - CNVOPMIN + 1] invconvtab =
  381     [
  382         OPbool,         // OPb_8
  383         OPs32_d,        // OPd_s32
  384         OPd_s32,        // OPs32_d
  385         OPs16_d,        /* OPd_s16      */
  386         OPd_s16,        /* OPs16_d      */
  387         OPu16_d,        // OPd_u16
  388         OPd_u16,        // OPu16_d
  389         OPu32_d,        /* OPd_u32      */
  390         OPd_u32,        /* OPu32_d      */
  391         OPs64_d,        // OPd_s64
  392         OPd_s64,        // OPs64_d
  393         OPu64_d,        // OPd_u64
  394         OPd_u64,        // OPu64_d
  395         OPf_d,          // OPd_f
  396         OPd_f,          // OPf_d
  397         OP32_16,        // OPs16_32
  398         OP32_16,        // OPu16_32
  399         OPs16_32,       // OP32_16
  400         OP16_8,         // OPu8_16
  401         OP16_8,         // OPs8_16
  402         OPs8_16,        // OP16_8
  403         OP64_32,        // OPu32_64
  404         OP64_32,        // OPs32_64
  405         OPs32_64,       // OP64_32
  406         OP128_64,       // OPu64_128
  407         OP128_64,       // OPs64_128
  408         OPs64_128,      // OP128_64
  409 
  410         0,              /* OPvp_fp      */
  411         0,              /* OPcvp_fp     */
  412         OPnp_fp,        /* OPoffset     */
  413         OPoffset,       /* OPnp_fp      */
  414         OPf16p_np,      /* OPnp_f16p    */
  415         OPnp_f16p,      /* OPf16p_np    */
  416 
  417         OPd_ld,         // OPld_d
  418         OPld_d,         // OPd_ld
  419         OPu64_d,        // OPld_u64
  420     ];
  421 
  422     //print("fixconvop before\n");
  423     //elem_print(e);
  424     assert(invconvtab.length == CNVOPMAX - CNVOPMIN + 1);
  425     assert(e);
  426     tym_t tyme = e.Ety;
  427     const cop = e.EV.E1.Eoper;             /* the conversion operator      */
  428     assert(cop <= CNVOPMAX);
  429 
  430     if (e.EV.E1.EV.E1.Eoper == OPcomma)
  431     {   /* conv(a,b) op= e2
  432          *   =>
  433          * a, (conv(b) op= e2)
  434          */
  435         elem *ecomma = e.EV.E1.EV.E1;
  436         e.EV.E1.EV.E1 = ecomma.EV.E2;
  437         e.EV.E1.EV.E1.Ety = ecomma.Ety;
  438         ecomma.EV.E2 = e;
  439         ecomma.Ety = e.Ety;
  440         return optelem(ecomma, GOALvalue);
  441     }
  442 
  443     if (e.EV.E1.Eoper == OPd_f && OTconv(e.EV.E1.EV.E1.Eoper) && tyintegral(tyme))
  444     {
  445         elem *e1 = e.EV.E1;
  446         e.EV.E1 = e1.EV.E1;
  447         e.EV.E2 = el_una(OPf_d, e.EV.E1.Ety, e.EV.E2);
  448         e1.EV.E1 = null;
  449         el_free(e1);
  450         return fixconvop(e);
  451     }
  452 
  453     tym_t tycop = e.EV.E1.Ety;
  454     tym_t tym = e.EV.E1.EV.E1.Ety;
  455     e.EV.E1 = el_selecte1(e.EV.E1);     /* dump it for now              */
  456     elem *e1 = e.EV.E1;
  457     e1.Ety = tym;
  458     elem *e2 = e.EV.E2;
  459     assert(e1 && e2);
  460     /* select inverse conversion operator   */
  461     const icop = invconvtab[convidx(cop)];
  462 
  463     /* First, let's see if we can just throw it away.       */
  464     /* (unslng or shtlng) e op= e2  => e op= (lngsht) e2    */
  465     if (OTwid(e.Eoper) &&
  466             (cop == OPs16_32 || cop == OPu16_32 ||
  467              cop == OPu8_16 || cop == OPs8_16))
  468     {   if (e.Eoper != OPshlass && e.Eoper != OPshrass && e.Eoper != OPashrass)
  469             e.EV.E2 = el_una(icop,tym,e2);
  470         //print("after1\n");
  471         //elem_print(e);
  472         return e;
  473     }
  474 
  475     /* Oh well, just split up the op and the =.                     */
  476     const op = opeqtoop(e.Eoper); // convert op= to op
  477     e.Eoper = OPeq;                  // just plain =
  478     elem *ed = el_copytree(e1);       // duplicate e1
  479                                       // make: e1 = (icop) ((cop) ed op e2)
  480     e.EV.E2 = el_una(icop,e1.Ety,
  481                              el_bin(op,tycop,el_una(cop,tycop,ed),
  482                                                   e2));
  483 
  484     //printf("after1\n");
  485     //elem_print(e);
  486 
  487     if (op == OPdiv &&
  488         tybasic(e2.Ety) == TYcdouble)
  489     {
  490         if (tycop == TYdouble)
  491         {
  492             e.EV.E2.EV.E1.Ety = tybasic(e2.Ety);
  493             e.EV.E2.EV.E1 = el_una(OPc_r, tycop, e.EV.E2.EV.E1);
  494         }
  495         else if (tycop == TYidouble)
  496         {
  497             e.EV.E2.EV.E1.Ety = tybasic(e2.Ety);
  498             e.EV.E2.EV.E1 = el_una(OPc_i, tycop, e.EV.E2.EV.E1);
  499         }
  500     }
  501 
  502     if (op == OPdiv &&
  503         tybasic(e2.Ety) == TYcfloat)
  504     {
  505         if (tycop == TYfloat)
  506         {
  507             e.EV.E2.EV.E1.Ety = tybasic(e2.Ety);
  508             e.EV.E2.EV.E1 = el_una(OPc_r, tycop, e.EV.E2.EV.E1);
  509         }
  510         else if (tycop == TYifloat)
  511         {
  512             e.EV.E2.EV.E1.Ety = tybasic(e2.Ety);
  513             e.EV.E2.EV.E1 = el_una(OPc_i, tycop, e.EV.E2.EV.E1);
  514         }
  515     }
  516 
  517     // Handle case of multiple conversion operators on lvalue
  518     // (such as (intdbl 8int char += double))
  519     elem *ex = e;
  520     elem **pe = &e;
  521     while (OTconv(ed.Eoper))
  522     {
  523         const uint copx = ed.Eoper;
  524         const uint icopx = invconvtab[convidx(copx)];
  525         tym_t tymx = ex.EV.E1.EV.E1.Ety;
  526         ex.EV.E1 = el_selecte1(ex.EV.E1);       // dump it for now
  527         e1 = ex.EV.E1;
  528         e1.Ety = tymx;
  529         ex.EV.E2 = el_una(icopx,e1.Ety,ex.EV.E2);
  530         ex.Ety = tymx;
  531         tym = tymx;
  532 
  533         if (ex.Ety != tyme)
  534         {   *pe = el_una(copx, ed.Ety, ex);
  535             pe = &(*pe).EV.E1;
  536         }
  537 
  538         ed = ed.EV.E1;
  539     }
  540     //print("after2\n");
  541     //elem_print(e);
  542 
  543     e.Ety = tym;
  544     if (tym != tyme &&
  545         !(tyintegral(tym) && tyintegral(tyme) && tysize(tym) == tysize(tyme)))
  546         e = el_una(cop, tyme, e);
  547 
  548     if (ed.Eoper == OPbit)         // special handling
  549     {
  550         ed = ed.EV.E1;
  551         e1 = e1.EV.E1;            // go down one
  552     }
  553 
  554     /* If we have a *, must assign a temporary to the expression
  555      * underneath it (even if it's a var, as e2 may modify the var)
  556      */
  557     if (ed.Eoper == OPind)
  558     {
  559         elem *T = el_alloctmp(ed.EV.E1.Ety);    // make temporary
  560         ed.EV.E1 = el_bin(OPeq,T.Ety,T,ed.EV.E1); // ed: *(T=e)
  561         el_free(e1.EV.E1);
  562         e1.EV.E1 = el_copytree(T);
  563     }
  564     //print("after3\n");
  565     //elem_print(e);
  566     return e;
  567 }
  568 
  569 private elem * elerr(elem *e, goal_t goal)
  570 {
  571     debug elem_print(e);
  572     assert(0);
  573 }
  574 
  575 /* For ops with no optimizations */
  576 
  577 private elem * elzot(elem *e, goal_t goal)
  578 {
  579     return e;
  580 }
  581 
  582 /****************************
  583  */
  584 
  585 private elem * elstring(elem *e, goal_t goal)
  586 {
  587     return e;
  588 }
  589 
  590 /************************
  591  */
  592 
  593 /************************
  594  * Convert far pointer to pointer.
  595  */
  596 
  597 private void eltonear(elem **pe)
  598 {
  599     elem *e = *pe;
  600     const tym_t ty = e.EV.E1.Ety;
  601     e = el_selecte1(e);
  602     e.Ety = ty;
  603     *pe = optelem(e,GOALvalue);
  604 }
  605 
  606 /************************
  607  */
  608 
  609 private elem * elstrcpy(elem *e, goal_t goal)
  610 {
  611     elem_debug(e);
  612     switch (e.EV.E2.Eoper)
  613     {
  614         case OPnp_fp:
  615             if (OPTIMIZER)
  616             {
  617                 eltonear(&e.EV.E2);
  618                 e = optelem(e,GOALvalue);
  619             }
  620             break;
  621 
  622         case OPstring:
  623             /* Replace strcpy(e1,"string") with memcpy(e1,"string",sizeof("string")) */
  624             // As streq
  625             e.Eoper = OPstreq;
  626             type *t = type_allocn(TYarray, tstypes[TYchar]);
  627             t.Tdim = strlen(e.EV.E2.EV.Vstring) + 1;
  628             e.ET = t;
  629             t.Tcount++;
  630             e.EV.E1 = el_una(OPind,TYstruct,e.EV.E1);
  631             e.EV.E2 = el_una(OPind,TYstruct,e.EV.E2);
  632 
  633             e = el_bin(OPcomma,e.Ety,e,el_copytree(e.EV.E1.EV.E1));
  634             if (el_sideeffect(e.EV.E2))
  635                 fixside(&e.EV.E1.EV.E1.EV.E1,&e.EV.E2);
  636             e = optelem(e,GOALvalue);
  637             break;
  638 
  639         default:
  640             break;
  641     }
  642     return e;
  643 }
  644 
  645 /************************
  646  */
  647 
  648 private elem * elstrcmp(elem *e, goal_t goal)
  649 {
  650     elem_debug(e);
  651     if (OPTIMIZER)
  652     {
  653         if (e.EV.E1.Eoper == OPnp_fp)
  654             eltonear(&e.EV.E1);
  655         switch (e.EV.E2.Eoper)
  656         {
  657             case OPnp_fp:
  658                 eltonear(&e.EV.E2);
  659                 break;
  660 
  661             case OPstring:
  662                 // Replace strcmp(e1,"string") with memcmp(e1,"string",sizeof("string"))
  663                 e.Eoper = OPparam;
  664                 e = el_bin(OPmemcmp,e.Ety,e,el_long(TYint,strlen(e.EV.E2.EV.Vstring) + 1));
  665                 e = optelem(e,GOALvalue);
  666                 break;
  667 
  668             default:
  669                 break;
  670         }
  671     }
  672     return e;
  673 }
  674 
  675 /****************************
  676  * For OPmemcmp
  677  * memcmp(a, b, nbytes) => ((a param b) OPmemcmp nbytes)
  678  */
  679 
  680 private elem * elmemcmp(elem *e, goal_t goal)
  681 {
  682     elem_debug(e);
  683     if (!OPTIMIZER)
  684         return e;
  685 
  686     /* Hoist comma operators in `a` out of OPmemcmp
  687      */
  688     {
  689         elem* ec = e.EV.E1.EV.E1;
  690         if (ec.Eoper == OPcomma)
  691         {
  692             /* Rewrite: (((a,b) param c) OPmemcmp nbytes)
  693              * As: a,((b param c) OPmemcmp nbytes)
  694              */
  695             e.EV.E1.EV.E1 = ec.EV.E2;
  696             e.EV.E1.EV.E1.Ety = ec.Ety;
  697             e.EV.E1.EV.E1.ET = ec.ET;
  698             ec.EV.E2 = e;
  699             ec.Ety = e.Ety;
  700             return optelem(ec, goal);
  701         }
  702     }
  703 
  704     /* Hoist comma operators in `b` out of OPmemcmp
  705      */
  706     {
  707         elem* ec = e.EV.E1.EV.E2;
  708         if (ec.Eoper == OPcomma)
  709         {
  710             /* Have: ((a param (b,c)) OPmemcmp nbytes)
  711              */
  712             elem* a = e.EV.E1.EV.E1;
  713             elem* b = ec.EV.E1;
  714             if (a.canHappenAfter(b))
  715             {
  716                 /* Rewrite: ((a param (b,c)) OPmemcmp nbytes)
  717                  * As: b,((a param c) OPmemcmp nbytes)
  718                  */
  719                 e.EV.E1.EV.E2 = ec.EV.E2;
  720                 e.EV.E1.EV.E2.Ety = ec.Ety;
  721                 e.EV.E1.EV.E2.ET = ec.ET;
  722                 ec.EV.E2 = e;
  723                 ec.Ety = e.Ety;
  724                 return optelem(ec, goal);
  725             }
  726         }
  727     }
  728 
  729     elem *ex = e.EV.E1;
  730     if (ex.EV.E1.Eoper == OPnp_fp)
  731         eltonear(&ex.EV.E1);
  732     if (ex.EV.E2.Eoper == OPnp_fp)
  733         eltonear(&ex.EV.E2);
  734 
  735     return e;
  736 }
  737 
  738 /****************************
  739  * For OPmemset
  740  */
  741 
  742 private elem * elmemset(elem *e, goal_t goal)
  743 {
  744     elem_debug(e);
  745     if (OPTIMIZER)
  746     {
  747         elem *ex = e.EV.E1;
  748         if (ex.Eoper == OPnp_fp)
  749             eltonear(&ex);
  750         else
  751         {
  752             // lvalue OPmemset (nbytes param value)
  753             elem *enbytes = e.EV.E2.EV.E1;
  754             elem *evalue = e.EV.E2.EV.E2;
  755 
  756             version (MARS)
  757             if (enbytes.Eoper == OPconst && evalue.Eoper == OPconst)
  758             {
  759                 int nbytes = cast(int)el_tolong(enbytes);
  760                 targ_llong value = el_tolong(evalue);
  761                 elem *e1 = e.EV.E1;
  762 
  763                 if (e1.Eoper == OPcomma || OTassign(e1.Eoper))
  764                     return cgel_lvalue(e);    // replace (e,v)op=e2 with e,(v op= e2)
  765 
  766                 tym_t tym;
  767                 switch (nbytes)
  768                 {
  769                     case CHARSIZE:      tym = TYchar;   goto L1;
  770                     case SHORTSIZE:     tym = TYshort;  goto L1;
  771                     case LONGSIZE:      tym = TYlong;   goto L1;
  772                     case LLONGSIZE:     if (_tysize[TYint] == 2)
  773                                             goto Ldefault;
  774                                         tym = TYllong;  goto L1;
  775                     L1:
  776                     {
  777                         tym_t ety = e.Ety;
  778                         memset(&value, value & 0xFF, value.sizeof);
  779                         evalue.EV.Vullong = value;
  780                         evalue.Ety = tym;
  781                         e.Eoper = OPeq;
  782                         e.Ety = (e.Ety & ~mTYbasic) | tym;
  783                         if (tybasic(e1.Ety) == TYstruct)
  784                             e1.Ety = tym;
  785                         else
  786                             e.EV.E1 = el_una(OPind, tym, e1);
  787                         elem *tmp = el_same(&e.EV.E1);
  788                         tmp = el_una(OPaddr, ety, tmp);
  789                         e.EV.E2.Ety = tym;
  790                         e.EV.E2 = el_selecte2(e.EV.E2);
  791                         e = el_combine(e, tmp);
  792                         e = optelem(e,GOALvalue);
  793                         break;
  794                     }
  795 
  796                     default:
  797                     Ldefault:
  798                         break;
  799                 }
  800             }
  801         }
  802     }
  803     return e;
  804 }
  805 
  806 
  807 /****************************
  808  * For OPmemcpy
  809  *  OPmemcpy
  810  *   /   \
  811  * s1   OPparam
  812  *       /   \
  813  *      s2    n
  814  */
  815 
  816 private elem * elmemcpy(elem *e, goal_t goal)
  817 {
  818     elem_debug(e);
  819     if (OPTIMIZER)
  820     {
  821         elem *ex = e.EV.E1;
  822         if (ex.Eoper == OPnp_fp)
  823             eltonear(&e.EV.E1);
  824         ex = e.EV.E2;
  825         if (ex.EV.E1.Eoper == OPnp_fp)
  826             eltonear(&ex.EV.E1);
  827         if (ex.EV.E2.Eoper == OPconst)
  828         {
  829             if (!boolres(ex.EV.E2))
  830             {   // Copying 0 bytes, so remove memcpy
  831                 e.EV.E2 = e.EV.E1;
  832                 e.EV.E1 = ex.EV.E1;
  833                 ex.EV.E1 = null;
  834                 e.Eoper = OPcomma;
  835                 el_free(ex);
  836                 return optelem(e, GOALvalue);
  837             }
  838             // Convert OPmemcpy to OPstreq
  839             e.Eoper = OPstreq;
  840             type *t = type_allocn(TYarray, tstypes[TYchar]);
  841             t.Tdim = cast(uint)el_tolong(ex.EV.E2);
  842             e.ET = t;
  843             t.Tcount++;
  844             e.EV.E1 = el_una(OPind,TYstruct,e.EV.E1);
  845             e.EV.E2 = el_una(OPind,TYstruct,ex.EV.E1);
  846             ex.EV.E1 = null;
  847             el_free(ex);
  848             ex = el_copytree(e.EV.E1.EV.E1);
  849             if (tysize(e.Ety) > tysize(ex.Ety))
  850                 ex = el_una(OPnp_fp,e.Ety,ex);
  851             e = el_bin(OPcomma,e.Ety,e,ex);
  852             if (el_sideeffect(e.EV.E2))
  853                 fixside(&e.EV.E1.EV.E1.EV.E1,&e.EV.E2);
  854             return optelem(e,GOALvalue);
  855         }
  856 
  857         /+ The following fails the autotester for Linux32 and FreeBSD32
  858          + for unknown reasons I cannot reproduce
  859         // Convert to memcpy(s1, s2, n)
  860         elem* ep = el_params(e.EV.E2.EV.E2, e.EV.E2.EV.E1, e.EV.E1, null);
  861         const ty = e.Ety;
  862         e.EV.E1 = null;
  863         e.EV.E2.EV.E1 = null;
  864         e.EV.E2.EV.E2 = null;
  865         el_free(e);
  866         e = el_bin(OPcall, ty, el_var(getRtlsym(RTLSYM_MEMCPY)), ep);
  867          +/
  868     }
  869     return e;
  870 }
  871 
  872 
  873 /***********************
  874  *        +             #       (combine offsets with addresses)
  875  *       / \    =>      |
  876  *      #   c          v,c
  877  *      |
  878  *      v
  879  */
  880 
  881 private elem * eladd(elem *e, goal_t goal)
  882 {
  883     //printf("eladd(%p)\n",e);
  884     targ_size_t ptrmask = ~cast(targ_size_t)0;
  885     if (_tysize[TYnptr] <= 4)
  886         ptrmask = 0xFFFFFFFF;
  887 L1:
  888     elem *e1 = e.EV.E1;
  889     elem *e2 = e.EV.E2;
  890     if (e2.Eoper == OPconst)
  891     {
  892         if (e1.Eoper == OPrelconst && e1.EV.Vsym.Sfl == FLgot)
  893             return e;
  894         if (e1.Eoper == OPrelconst ||          // if (&v) + c
  895             e1.Eoper == OPstring)
  896         {
  897             e1.EV.Voffset += e2.EV.Vpointer;
  898             e1.EV.Voffset &= ptrmask;
  899             e = el_selecte1(e);
  900             return e;
  901         }
  902     }
  903     else if (e1.Eoper == OPconst)
  904     {
  905         if (e2.Eoper == OPrelconst && e2.EV.Vsym.Sfl == FLgot)
  906             return e;
  907         if (e2.Eoper == OPrelconst ||          // if c + (&v)
  908             e2.Eoper == OPstring)
  909         {
  910             e2.EV.Voffset += e1.EV.Vpointer;
  911             e2.EV.Voffset &= ptrmask;
  912             e = el_selecte2(e);
  913             return e;
  914         }
  915     }
  916 
  917     if (!OPTIMIZER)
  918         return e;
  919 
  920     // Replace ((e + &v) + c) with (e + (&v+c))
  921     if (e2.Eoper == OPconst && e1.Eoper == OPadd &&
  922        (e1.EV.E2.Eoper == OPrelconst || e1.EV.E2.Eoper == OPstring))
  923     {
  924         e1.EV.E2.EV.Voffset += e2.EV.Vpointer;
  925         e1.EV.E2.EV.Voffset &= ptrmask;
  926         e = el_selecte1(e);
  927         goto L1;
  928     }
  929     // Replace ((e + c) + &v) with (e + (&v+c))
  930     else if ((e2.Eoper == OPrelconst || e2.Eoper == OPstring) &&
  931              e1.Eoper == OPadd && cnst(e1.EV.E2))
  932     {
  933         e2.EV.Voffset += e1.EV.E2.EV.Vpointer;
  934         e2.EV.Voffset &= ptrmask;
  935         e.EV.E1 = el_selecte1(e1);
  936         goto L1;                        /* try and find some more       */
  937     }
  938     // Replace (e1 + -e) with (e1 - e)
  939     else if (e2.Eoper == OPneg)
  940     {
  941         e.EV.E2 = el_selecte1(e2);
  942         e.Eoper = OPmin;
  943         again = 1;
  944         return e;
  945     }
  946     // Replace (-v + e) with (e + -v)
  947     else if (e1.Eoper == OPneg && OTleaf(e1.EV.E1.Eoper))
  948     {
  949         e.EV.E1 = e2;
  950         e.EV.E2 = e1;                     /* swap leaves                  */
  951         goto L1;
  952     }
  953     /* Replace ((e - e2) + e2) with (e)
  954      * The optimizer sometimes generates this case
  955      */
  956     else if (!tyfloating(e.Ety) &&       /* no floating bugs             */
  957         e1.Eoper == OPmin &&
  958         el_match(e1.EV.E2,e2) &&
  959         !el_sideeffect(e2))
  960     {
  961         tym_t tym = e.Ety;
  962         e = el_selecte1(el_selecte1(e));
  963         e.Ety = tym;                   /* retain original type         */
  964         return e;
  965     }
  966     // Replace ((e - #v+c1) + #v+c2) with ((e - c1) + c2)
  967     else if (e2.Eoper == OPrelconst &&
  968            e1.Eoper == OPmin &&
  969            e1.EV.E2.Eoper == OPrelconst &&
  970            e1.EV.E2.EV.Vsym == e2.EV.Vsym)
  971     {
  972         e2.Eoper = OPconst;
  973         e2.Ety = TYint;
  974         e1.Ety = e1.EV.E1.Ety;
  975         e1.EV.E2.Eoper = OPconst;
  976         e1.EV.E2.Ety = TYint;
  977         {
  978             /* Watch out for pointer types changing, requiring a conversion */
  979             tym_t ety = tybasic(e.Ety);
  980             tym_t e11ty = tybasic(e1.EV.E1.Ety);
  981             if (typtr(ety) && typtr(e11ty) &&
  982                 _tysize[ety] != _tysize[e11ty])
  983             {
  984                 e = el_una((_tysize[ety] > _tysize[e11ty]) ? OPnp_fp : OPoffset,
  985                             e.Ety,e);
  986                 e.EV.E1.Ety = e1.Ety;
  987             }
  988         }
  989         again = 1;
  990         return e;
  991     }
  992     // Replace (e + e) with (e * 2)
  993     else if (el_match(e1,e2) && !el_sideeffect(e1) && !tyfloating(e1.Ety))
  994     {
  995         e.Eoper = OPmul;
  996         el_free(e2);
  997         e.EV.E2 = el_long(e1.Ety,2);
  998         again = 1;
  999         return e;
 1000     }
 1001 
 1002     // Replace ((e11 + c) + e2) with ((e11 + e2) + c)
 1003     if (e1.Eoper == OPadd && e1.EV.E2.Eoper == OPconst &&
 1004         (e2.Eoper == OPvar || !OTleaf(e2.Eoper)) &&
 1005         tysize(e1.Ety) == tysize(e2.Ety) &&
 1006         tysize(e1.EV.E2.Ety) == tysize(e2.Ety))
 1007     {
 1008         e.EV.E2 = e1.EV.E2;
 1009         e1.EV.E2 = e2;
 1010         e1.Ety = e.Ety;
 1011         return e;
 1012     }
 1013 
 1014     // Replace (~e1 + 1) with (-e1)
 1015     if (e1.Eoper == OPcom && e2.Eoper == OPconst && el_tolong(e2) == 1)
 1016     {
 1017         e = el_selecte1(e);
 1018         e.Eoper = OPneg;
 1019         e = optelem(e, goal);
 1020         return e;
 1021     }
 1022 
 1023     // Replace ((e11 - e12) + e2) with ((e11 + e2) - e12)
 1024     // (this should increase the number of LEA possibilities)
 1025     int sz = tysize(e.Ety);
 1026     if (e1.Eoper == OPmin &&
 1027         tysize(e1.Ety) == sz &&
 1028         tysize(e2.Ety) == sz &&
 1029         tysize(e1.EV.E1.Ety) == sz &&
 1030         tysize(e1.EV.E2.Ety) == sz &&
 1031         !tyfloating(e.Ety)
 1032        )
 1033     {
 1034         e.Eoper = OPmin;
 1035         e.EV.E2 = e1.EV.E2;
 1036         e1.EV.E2 = e2;
 1037         e1.Eoper = OPadd;
 1038     }
 1039 
 1040     return e;
 1041 }
 1042 
 1043 
 1044 /************************
 1045  * Multiply (for OPmul && OPmulass)
 1046  *      e * (c**2) => e << c    ;replace multiply by power of 2 with shift
 1047  */
 1048 
 1049 private elem * elmul(elem *e, goal_t goal)
 1050 {
 1051     tym_t tym = e.Ety;
 1052 
 1053     if (OPTIMIZER)
 1054     {
 1055         // Replace -a*-b with a*b.
 1056         // This is valid for all floating point types as well as integers.
 1057         if (tyarithmetic(tym) && e.EV.E2.Eoper == OPneg && e.EV.E1.Eoper == OPneg)
 1058         {
 1059             e.EV.E1 = el_selecte1(e.EV.E1);
 1060             e.EV.E2 = el_selecte1(e.EV.E2);
 1061         }
 1062     }
 1063 
 1064     elem *e2 = e.EV.E2;
 1065     if (e2.Eoper == OPconst)           // try to replace multiplies with shifts
 1066     {
 1067         if (OPTIMIZER)
 1068         {
 1069             elem *e1 = e.EV.E1;
 1070             uint op1 = e1.Eoper;
 1071 
 1072             if (tyintegral(tym) &&              // skip floating types
 1073                 OTbinary(op1) &&
 1074                 e1.EV.E2.Eoper == OPconst
 1075                )
 1076             {
 1077                 /* Attempt to replace ((e + c1) * c2) with (e * c2 + (c1 * c2))
 1078                  * because the + can be frequently folded out (merged into an
 1079                  * array offset, for example.
 1080                  */
 1081                 if (op1 == OPadd)
 1082                 {
 1083                     e.Eoper = OPadd;
 1084                     e1.Eoper = OPmul;
 1085                     e.EV.E2 = el_bin(OPmul,tym,e1.EV.E2,e2);
 1086                     e1.EV.E2 = el_copytree(e2);
 1087                     again = 1;
 1088                     return e;
 1089                 }
 1090 
 1091                 // ((e << c1) * c2) => e * ((1 << c1) * c2)
 1092                 if (op1 == OPshl)
 1093                 {
 1094                     e2.EV.Vullong *= cast(targ_ullong)1 << el_tolong(e1.EV.E2);
 1095                     e1.EV.E2.EV.Vullong = 0;
 1096                     again = 1;
 1097                     return e;
 1098                 }
 1099             }
 1100 
 1101             if (elemisnegone(e2))
 1102             {
 1103                 e.Eoper = (e.Eoper == OPmul) ? OPneg : OPnegass;
 1104                 e.EV.E2 = null;
 1105                 el_free(e2);
 1106                 return e;
 1107             }
 1108         }
 1109 
 1110         if (tyintegral(tym) && !tyvector(tym))
 1111         {
 1112             int i = ispow2(el_tolong(e2));      // check for power of 2
 1113             if (i != -1)                        // if it is a power of 2
 1114             {   e2.EV.Vint = i;
 1115                 e2.Ety = TYint;
 1116                 e.Eoper = (e.Eoper == OPmul)  /* convert to shift left */
 1117                         ? OPshl : OPshlass;
 1118                 again = 1;
 1119                 return e;
 1120             }
 1121             else if (el_allbits(e2,-1))
 1122                 goto Lneg;
 1123         }
 1124         else if (elemisnegone(e2) && !tycomplex(e.EV.E1.Ety))
 1125         {
 1126             goto Lneg;
 1127         }
 1128     }
 1129     return e;
 1130 
 1131 Lneg:
 1132     e.Eoper = (e.Eoper == OPmul)      /* convert to negate */
 1133             ? OPneg : OPnegass;
 1134     el_free(e.EV.E2);
 1135     e.EV.E2 = null;
 1136     again = 1;
 1137     return e;
 1138 }
 1139 
 1140 /************************
 1141  * Subtract
 1142  *        -               +
 1143  *       / \    =>       / \            (propagate minuses)
 1144  *      e   c           e   -c
 1145  */
 1146 
 1147 private elem * elmin(elem *e, goal_t goal)
 1148 {
 1149     elem *e2 = e.EV.E2;
 1150 
 1151     if (OPTIMIZER)
 1152     {
 1153         tym_t tym = e.Ety;
 1154         elem *e1 = e.EV.E1;
 1155         if (e2.Eoper == OPrelconst)
 1156         {
 1157             if (e1.Eoper == OPrelconst && e1.EV.Vsym == e2.EV.Vsym)
 1158             {
 1159                 e.Eoper = OPconst;
 1160                 e.EV.Vllong = e1.EV.Voffset - e2.EV.Voffset;
 1161                 el_free(e1);
 1162                 el_free(e2);
 1163                 return e;
 1164             }
 1165         }
 1166 
 1167         // Convert subtraction of long pointers to subtraction of integers
 1168         if (tyfv(e2.Ety) && tyfv(e1.Ety))
 1169         {
 1170             e.EV.E1 = el_una(OP32_16,tym,e1);
 1171             e.EV.E2 = el_una(OP32_16,tym,e2);
 1172             return optelem(e,GOALvalue);
 1173         }
 1174 
 1175         // Replace (0 - e2) with (-e2)
 1176         if (cnst(e1) && !boolres(e1) &&
 1177             !(tycomplex(tym) && !tycomplex(e1.Ety) && !tycomplex(e2.Ety)) &&
 1178             !tyvector(e1.Ety)
 1179            )
 1180         {
 1181             e.EV.E1 = e2;
 1182             e.EV.E2 = null;
 1183             e.Eoper = OPneg;
 1184             el_free(e1);
 1185             return optelem(e,GOALvalue);
 1186         }
 1187 
 1188         // Replace (e - e) with (0)
 1189         if (el_match(e1,e2) && !el_sideeffect(e1))
 1190         {
 1191             el_free(e);
 1192             e = el_calloc();
 1193             e.Eoper = OPconst;
 1194             e.Ety = tym;
 1195             return e;
 1196         }
 1197 
 1198         // Replace ((e1 + c) - e2) with ((e1 - e2) + c), but not
 1199         // for floating or far or huge pointers!
 1200         if (e1.Eoper == OPadd &&
 1201             cnst(e1.EV.E2) &&
 1202             (tyintegral(tym) ||
 1203              tybasic(tym) == TYnptr ||
 1204              tybasic(tym) == TYsptr ||
 1205              tybasic(tym) == TYfgPtr ||
 1206              tybasic(tym) == TYimmutPtr ||
 1207              tybasic(tym) == TYrestrictPtr ||
 1208              tybasic(tym) == TYsharePtr)
 1209            )
 1210         {
 1211             e.Eoper = OPadd;
 1212             e1.Eoper = OPmin;
 1213             elem* c = e1.EV.E2;
 1214             e1.EV.E2 = e2;
 1215             e.EV.E2 = c;
 1216             return optelem(e,GOALvalue);
 1217         }
 1218 
 1219         // Replace (e1 + c1) - (e2 + c2) with (e1 - e2) + (c1 - c2), but not
 1220         // for floating or far or huge pointers!
 1221         if (e1.Eoper == OPadd && e2.Eoper == OPadd &&
 1222             cnst(e1.EV.E2) && cnst(e2.EV.E2) &&
 1223             (tyintegral(tym) ||
 1224              tybasic(tym) == TYnptr ||
 1225              tybasic(tym) == TYsptr ||
 1226              tybasic(tym) == TYfgPtr ||
 1227              tybasic(tym) == TYimmutPtr ||
 1228              tybasic(tym) == TYrestrictPtr ||
 1229              tybasic(tym) == TYsharePtr)
 1230            )
 1231         {
 1232             e.Eoper = OPadd;
 1233             e1.Eoper = OPmin;
 1234             e2.Eoper = OPmin;
 1235             elem *tmp = e1.EV.E2;
 1236             e1.EV.E2 = e2.EV.E1;
 1237             e2.EV.E1 = tmp;
 1238             return optelem(e,GOALvalue);
 1239         }
 1240 
 1241         // Replace (-e1 - 1) with (~e1)
 1242         if (e1.Eoper == OPneg && e2.Eoper == OPconst && tyintegral(tym) && el_tolong(e2) == 1)
 1243         {
 1244             e = el_selecte1(e);
 1245             e.Eoper = OPcom;
 1246             e = optelem(e, goal);
 1247             return e;
 1248         }
 1249 
 1250         // Replace (-1 - e2) with (~e2)
 1251         if (e1.Eoper == OPconst && tyintegral(tym) && !tyvector(tym) && el_tolong(e1) == -1)
 1252         {
 1253             el_free(e1);
 1254             e.EV.E1 = e.EV.E2;
 1255             e.EV.E2 = null;
 1256             e.Eoper = OPcom;
 1257             e = optelem(e, goal);
 1258             return e;
 1259         }
 1260 
 1261         /* Replace e1 - (v * c) with e1 + (v * -c)
 1262          */
 1263         if (e2.Eoper == OPmul &&
 1264             e2.EV.E2.Eoper == OPconst)
 1265         {
 1266             e.Eoper = OPadd;
 1267             e2.EV.E2 = el_una(OPneg, e2.EV.E2.Ety, e2.EV.E2);
 1268             return optelem(e, goal);
 1269         }
 1270     }
 1271 
 1272     if (I16 && tybasic(e2.Ety) == TYhptr && tybasic(e.EV.E1.Ety) == TYhptr)
 1273     {   // Convert to _aNahdiff(e1,e2)
 1274         __gshared Symbol *hdiff;
 1275         if (!hdiff)
 1276         {
 1277             Symbol *s = symbol_calloc(LARGECODE ? "_aFahdiff".ptr : "_aNahdiff".ptr);
 1278             s.Stype = tsclib;
 1279             s.Sclass = SCextern;
 1280             s.Sfl = FLfunc;
 1281             s.Ssymnum = 0;
 1282             s.Sregsaved = mBX|mCX|mSI|mDI|mBP|mES;
 1283             hdiff = s;
 1284         }
 1285         e.Eoper = OPcall;
 1286         e.EV.E2 = el_bin(OPparam,TYint,e2,e.EV.E1);
 1287         e.EV.E1 = el_var(hdiff);
 1288         return e;
 1289     }
 1290 
 1291     /* Disallow the optimization on doubles. The - operator is not
 1292      * rearrangable by K+R, and can cause floating point problems if
 1293      * converted to an add ((a + 1.0) - 1.0 shouldn't be folded).
 1294      */
 1295     if (cnst(e2) && !tyfloating(e2.Ety) &&
 1296         !tyvector(e2.Ety)) // don't do vectors until we get constant folding for them
 1297     {
 1298         e.EV.E2 = el_una(OPneg,e2.Ety,e2);
 1299         e.Eoper = OPadd;
 1300         return optelem(e,GOALvalue);
 1301     }
 1302     return e;
 1303 }
 1304 
 1305 /*****************************
 1306  * OPand,OPor,OPxor
 1307  * This should be expanded to include long type stuff.
 1308  */
 1309 
 1310 private elem * elbitwise(elem *e, goal_t goal)
 1311 {
 1312     //printf("elbitwise(e = %p, goal = x%x)\n", e, goal);
 1313 
 1314     elem *e2 = e.EV.E2;
 1315     elem *e1 = e.EV.E1;
 1316     const op = e1.Eoper;
 1317     uint sz = tysize(e2.Ety);
 1318 
 1319     if (e2.Eoper == OPconst)
 1320     {
 1321         switch (sz)
 1322         {
 1323             case CHARSIZE:
 1324                 /* Replace (c & 0xFF) with (c)  */
 1325                 if (OPTIMIZER && e2.EV.Vuchar == CHARMASK)
 1326                 {
 1327                 L1:
 1328                     switch (e.Eoper)
 1329                     {   case OPand:     /* (c & 0xFF) => (c)    */
 1330                             return el_selecte1(e);
 1331                         case OPor:      /* (c | 0xFF) => (0xFF) */
 1332                             return el_selecte2(e);
 1333                         case OPxor:     /* (c ^ 0xFF) => (~c)   */
 1334                             return el_una(OPcom,e.Ety,el_selecte1(e));
 1335                         default:
 1336                             assert(0);
 1337                     }
 1338                 }
 1339                 break;
 1340 
 1341             case LONGSIZE:
 1342             {
 1343                 if (!OPTIMIZER)
 1344                     break;
 1345                 targ_ulong ul = e2.EV.Vulong;
 1346 
 1347                 if (ul == 0xFFFFFFFF)           /* if e1 & 0xFFFFFFFF   */
 1348                     goto L1;
 1349                 /* (x >> 16) & 0xFFFF => (cast(uint)x >> 16)       */
 1350                 if (ul == 0xFFFF && e.Eoper == OPand && (op == OPshr || op == OPashr) &&
 1351                     e1.EV.E2.Eoper == OPconst && el_tolong(e1.EV.E2) == 16)
 1352                 {
 1353                     elem *e11 = e1.EV.E1;
 1354                     e11.Ety = touns(e11.Ety) | (e11.Ety & ~mTYbasic);
 1355                     goto L1;
 1356                 }
 1357 
 1358                 /* Replace (L & 0x0000XXXX) with (unslng)((lngsht) & 0xXXXX) */
 1359                 if (_tysize[TYint] < LONGSIZE &&
 1360                     e.Eoper == OPand &&
 1361                     ul <= SHORTMASK)
 1362                 {
 1363                     tym_t tym = e.Ety;
 1364                     e.EV.E1 = el_una(OP32_16,TYushort,e.EV.E1);
 1365                     e.EV.E2 = el_una(OP32_16,TYushort,e.EV.E2);
 1366                     e.Ety = TYushort;
 1367                     e = el_una(OPu16_32,tym,e);
 1368                     goto Lopt;
 1369                 }
 1370 
 1371                 // Replace ((s8sht)L & 0xFF) with (u8sht)L
 1372                 if (ul == 0xFF && _tysize[TYint] == LONGSIZE && e.Eoper == OPand &&
 1373                     (op == OPs8_16 || op == OPu8_16)
 1374                    )
 1375                 {
 1376                     e1.Eoper = OPu8_16;
 1377                     e = el_selecte1(e);
 1378                     goto Lopt;
 1379                 }
 1380                 break;
 1381             }
 1382 
 1383             case SHORTSIZE:
 1384             {
 1385                 targ_short i = e2.EV.Vshort;
 1386                 if (i == cast(targ_short)SHORTMASK) // e2 & 0xFFFF
 1387                     goto L1;
 1388 
 1389                 /* (x >> 8) & 0xFF => ((uint short)x >> 8)          */
 1390                 if (OPTIMIZER && i == 0xFF && e.Eoper == OPand &&
 1391                     (op == OPshr || op == OPashr) && e1.EV.E2.Eoper == OPconst && e1.EV.E2.EV.Vint == 8)
 1392                 {
 1393                     elem *e11 = e1.EV.E1;
 1394                     e11.Ety = touns(e11.Ety) | (e11.Ety & ~mTYbasic);
 1395                     goto L1;
 1396                 }
 1397 
 1398                 // (s8_16(e) & 0xFF) => u8_16(e)
 1399                 if (OPTIMIZER && op == OPs8_16 && e.Eoper == OPand &&
 1400                     i == 0xFF)
 1401                 {
 1402                     e1.Eoper = OPu8_16;
 1403                     e = el_selecte1(e);
 1404                     goto Lopt;
 1405                 }
 1406 
 1407                 if (
 1408                     /* OK for uint if AND or high bits of i are 0   */
 1409                     op == OPu8_16 && (e.Eoper == OPand || !(i & ~0xFF)) ||
 1410                     /* OK for signed if i is 'sign-extended'    */
 1411                     op == OPs8_16 && cast(targ_short)cast(targ_schar)i == i
 1412                    )
 1413                 {
 1414                     /* Convert ((u8int) e) & i) to (u8int)(e & (int8) i) */
 1415                     /* or similar for s8int                              */
 1416                     e = el_una(e1.Eoper,e.Ety,e);
 1417                     e.EV.E1.Ety = e1.Ety = e1.EV.E1.Ety;
 1418                     e.EV.E1.EV.E1 = el_selecte1(e1);
 1419                     e.EV.E1.EV.E2 = el_una(OP16_8,e.EV.E1.Ety,e.EV.E1.EV.E2);
 1420                     goto Lopt;
 1421                 }
 1422                 break;
 1423             }
 1424 
 1425             case LLONGSIZE:
 1426                 if (OPTIMIZER)
 1427                 {
 1428                     if (e2.EV.Vullong == LLONGMASK)
 1429                         goto L1;
 1430                 }
 1431                 break;
 1432 
 1433             default:
 1434                 break;
 1435         }
 1436         if (OPTIMIZER && sz < 16)
 1437         {
 1438             targ_ullong ul = el_tolong(e2);
 1439 
 1440             if (e.Eoper == OPor && op == OPand && e1.EV.E2.Eoper == OPconst)
 1441             {
 1442                 // ((x & c1) | c2) => (x | c2)
 1443                 targ_ullong c3;
 1444 
 1445                 c3 = ul | e1.EV.E2.EV.Vullong;
 1446                 switch (sz)
 1447                 {
 1448                     case CHARSIZE:
 1449                         if ((c3 & CHARMASK) == CHARMASK)
 1450                             goto L2;
 1451                         break;
 1452 
 1453                     case SHORTSIZE:
 1454                         if ((c3 & SHORTMASK) == SHORTMASK)
 1455                             goto L2;
 1456                         break;
 1457 
 1458                     case LONGSIZE:
 1459                         if ((c3 & LONGMASK) == LONGMASK)
 1460                         {
 1461                         L2:
 1462                             e1.EV.E2.EV.Vullong = c3;
 1463                             e.EV.E1 = elbitwise(e1, GOALvalue);
 1464                             goto Lopt;
 1465                         }
 1466                         break;
 1467 
 1468                     case LLONGSIZE:
 1469                         if ((c3 & LLONGMASK) == LLONGMASK)
 1470                             goto L2;
 1471                         break;
 1472 
 1473                     default:
 1474                         assert(0);
 1475                 }
 1476             }
 1477 
 1478             if (op == OPs16_32 && (ul & 0xFFFFFFFFFFFF8000L) == 0 ||
 1479                 op == OPu16_32 && (ul & 0xFFFFFFFFFFFF0000L) == 0 ||
 1480                 op == OPs8_16  && (ul & 0xFFFFFFFFFFFFFF80L) == 0 ||
 1481                 op == OPu8_16  && (ul & 0xFFFFFFFFFFFFFF00L) == 0 ||
 1482                 op == OPs32_64 && (ul & 0xFFFFFFFF80000000L) == 0 ||
 1483                 op == OPu32_64 && (ul & 0xFFFFFFFF00000000L) == 0
 1484                )
 1485             {
 1486                 if (e.Eoper == OPand)
 1487                 {
 1488                     if (op == OPs16_32 && (ul & 0x8000) == 0)
 1489                         e1.Eoper = OPu16_32;
 1490                     else if (op == OPs8_16  && (ul & 0x80) == 0)
 1491                         e1.Eoper = OPu8_16;
 1492                     else if (op == OPs32_64 && (ul & 0x80000000) == 0)
 1493                         e1.Eoper = OPu32_64;
 1494                 }
 1495 
 1496                 // ((shtlng)s & c) => ((shtlng)(s & c)
 1497                 e1.Ety = e.Ety;
 1498                 e.Ety = e2.Ety = e1.EV.E1.Ety;
 1499                 e.EV.E1 = e1.EV.E1;
 1500                 e1.EV.E1 = e;
 1501                 e = e1;
 1502                 goto Lopt;
 1503             }
 1504 
 1505             // Replace (((a & b) ^ c) & d) with ((a ^ c) & e), where
 1506             // e is (b&d).
 1507             if (e.Eoper == OPand && op == OPxor && e1.EV.E1.Eoper == OPand &&
 1508                 e1.EV.E1.EV.E2.Eoper == OPconst)
 1509             {
 1510                 e2.EV.Vullong &= e1.EV.E1.EV.E2.EV.Vullong;
 1511                 e1.EV.E1 = el_selecte1(e1.EV.E1);
 1512                 goto Lopt;
 1513             }
 1514 
 1515             // Replace ((a >> b) & 1) with (a btst b)
 1516             if ((I32 || I64) &&
 1517                 e.Eoper == OPand &&
 1518                 ul == 1 &&
 1519                 (e.EV.E1.Eoper == OPshr || e.EV.E1.Eoper == OPashr) &&
 1520                 sz <= REGSIZE &&
 1521                 tysize(e1.Ety) >= 2     // BT doesn't work on byte operands
 1522                )
 1523             {
 1524                 e.EV.E1.Eoper = OPbtst;
 1525                 e = el_selecte1(e);
 1526                 goto Lopt;
 1527             }
 1528         }
 1529     }
 1530 
 1531     if (OPTIMIZER && goal & GOALflags && (I32 || I64) && e.Eoper == OPand &&
 1532         (sz == 4 || sz == 8))
 1533     {
 1534         /* These should all compile to a BT instruction when -O, for -m32 and -m64
 1535          * int bt32(uint *p, uint b) { return ((p[b >> 5] & (1 << (b & 0x1F)))) != 0; }
 1536          * int bt64a(ulong *p, uint b) { return ((p[b >> 6] & (1L << (b & 63)))) != 0; }
 1537          * int bt64b(ulong *p, size_t b) { return ((p[b >> 6] & (1L << (b & 63)))) != 0; }
 1538          */
 1539 
 1540         static bool ELCONST(elem* e, long c) { return e.Eoper == OPconst && el_tolong(e) == c; }
 1541         int pow2sz = ispow2(sz);
 1542 
 1543         if (e1.Eoper == OPind)
 1544         {   // Swap e1 and e2 so that e1 is the mask and e2 is the memory location
 1545             e2 = e1;
 1546             e1 = e.EV.E2;
 1547         }
 1548 
 1549         /* Replace:
 1550          *  ((1 << (b & 31))   &   *(((b >>> 5) << 2) + p)
 1551          * with:
 1552          *  p bt b
 1553          */
 1554         elem *e12;              // the (b & 31), which may be preceded by (64_32)
 1555         elem *e2111;            // the (b >>> 5), which may be preceded by (u32_64)
 1556         if (e1.Eoper == OPshl &&
 1557             ELCONST(e1.EV.E1,1) &&
 1558             (((e12 = e1.EV.E2).Eoper == OP64_32 ? (e12 = e12.EV.E1) : e12).Eoper == OPand) &&
 1559             ELCONST(e12.EV.E2,sz * 8 - 1) &&
 1560             tysize(e12.Ety) <= sz &&
 1561 
 1562             e2.Eoper == OPind &&
 1563             e2.EV.E1.Eoper == OPadd &&
 1564             e2.EV.E1.EV.E1.Eoper == OPshl &&
 1565             ELCONST(e2.EV.E1.EV.E1.EV.E2,pow2sz) &&
 1566             (((e2111 = e2.EV.E1.EV.E1.EV.E1).Eoper == OPu32_64 ? (e2111 = e2111.EV.E1) : e2111).Eoper == OPshr) &&
 1567             ELCONST(e2111.EV.E2,pow2sz + 3)
 1568            )
 1569         {
 1570             elem **pb1 = &e12.EV.E1;
 1571             elem **pb2 = &e2111.EV.E1;
 1572             elem **pp  = &e2.EV.E1.EV.E2;
 1573 
 1574             if (el_match(*pb1, *pb2) &&
 1575                 !el_sideeffect(*pb1))
 1576             {
 1577                 e.Eoper = OPbt;
 1578                 e.EV.E1 = *pp;            // p
 1579                 *pp = null;
 1580                 e.EV.E2 = *pb1;           // b
 1581                 *pb1 = null;
 1582                 *pb2 = null;
 1583                 el_free(e1);
 1584                 el_free(e2);
 1585                 return optelem(e,goal);
 1586             }
 1587         }
 1588 
 1589         /* Replace:
 1590          *  (1 << a) & b
 1591          * with:
 1592          *  b btst a
 1593          */
 1594         if (e1.Eoper == OPshl &&
 1595             ELCONST(e1.EV.E1,1) &&
 1596             tysize(e.EV.E1.Ety) <= REGSIZE)
 1597         {
 1598             const int sz1 = tysize(e.EV.E1.Ety);
 1599             e.Eoper = OPbtst;
 1600             e.Ety = TYbool;
 1601             e.EV.E1 = e2;
 1602             e.EV.E2 = e1.EV.E2;
 1603             //e.EV.E2.Ety = e.EV.E1.Ety; // leave type as int
 1604             e1.EV.E2 = null;
 1605             el_free(e1);
 1606 
 1607             if (sz1 >= 2)
 1608                 e = el_una(OPu8_16, TYushort, e);
 1609             if (sz1 >= 4)
 1610                 e = el_una(OPu16_32, TYulong, e);
 1611             if (sz1 >= 8)
 1612                 e = el_una(OPu32_64, TYullong, e);
 1613 
 1614             return optelem(e, goal);
 1615         }
 1616     }
 1617 
 1618     return e;
 1619 
 1620 Lopt:
 1621     debug
 1622     {
 1623         __gshared int nest;
 1624         nest++;
 1625         if (nest > 100)
 1626         {   elem_print(e);
 1627             assert(0);
 1628         }
 1629         e = optelem(e,GOALvalue);
 1630         nest--;
 1631         return e;
 1632     }
 1633     else
 1634         return optelem(e,GOALvalue);
 1635 }
 1636 
 1637 /***************************************
 1638  * Fill in ops[maxops] with operands of repeated operator oper.
 1639  * Returns:
 1640  *      true    didn't fail
 1641  *      false   more than maxops operands
 1642  */
 1643 
 1644 bool fillinops(elem **ops, int *opsi, int maxops, int oper, elem *e)
 1645 {
 1646     if (e.Eoper == oper)
 1647     {
 1648         if (!fillinops(ops, opsi, maxops, oper, e.EV.E1) ||
 1649             !fillinops(ops, opsi, maxops, oper, e.EV.E2))
 1650             return false;
 1651     }
 1652     else
 1653     {
 1654         if (*opsi >= maxops)
 1655             return false;       // error, too many
 1656         ops[*opsi] = e;
 1657         *opsi += 1;
 1658     }
 1659     return true;
 1660 }
 1661 
 1662 
 1663 /*************************************
 1664  * Replace shift|shift with rotate.
 1665  */
 1666 
 1667 private elem *elor(elem *e, goal_t goal)
 1668 {
 1669     //printf("elor()\n");
 1670     /* ROL:     (a << shift) | (a >> (sizeof(a) * 8 - shift))
 1671      * ROR:     (a >> shift) | (a << (sizeof(a) * 8 - shift))
 1672      */
 1673     elem *e1 = e.EV.E1;
 1674     elem *e2 = e.EV.E2;
 1675     uint sz = tysize(e.Ety);
 1676     if (sz <= REGSIZE)
 1677     {
 1678         if (e1.Eoper == OPshl && e2.Eoper == OPshr &&
 1679             tyuns(e2.EV.E1.Ety) && e2.EV.E2.Eoper == OPmin &&
 1680             e2.EV.E2.EV.E1.Eoper == OPconst &&
 1681             el_tolong(e2.EV.E2.EV.E1) == sz * 8 &&
 1682             el_match5(e1.EV.E1, e2.EV.E1) &&
 1683             el_match5(e1.EV.E2, e2.EV.E2.EV.E2) &&
 1684             !el_sideeffect(e)
 1685            )
 1686         {
 1687             e1.Eoper = OProl;
 1688             return el_selecte1(e);
 1689         }
 1690         if (e1.Eoper == OPshr && e2.Eoper == OPshl &&
 1691             tyuns(e1.EV.E1.Ety) && e2.EV.E2.Eoper == OPmin &&
 1692             e2.EV.E2.EV.E1.Eoper == OPconst &&
 1693             el_tolong(e2.EV.E2.EV.E1) == sz * 8 &&
 1694             el_match5(e1.EV.E1, e2.EV.E1) &&
 1695             el_match5(e1.EV.E2, e2.EV.E2.EV.E2) &&
 1696             !el_sideeffect(e)
 1697            )
 1698         {
 1699             e1.Eoper = OPror;
 1700             return el_selecte1(e);
 1701         }
 1702         // rotate left by a constant
 1703         if (e1.Eoper == OPshl && e2.Eoper == OPshr &&
 1704             tyuns(e2.EV.E1.Ety) &&
 1705             e1.EV.E2.Eoper == OPconst &&
 1706             e2.EV.E2.Eoper == OPconst &&
 1707             el_tolong(e2.EV.E2) == sz * 8 - el_tolong(e1.EV.E2) &&
 1708             el_match5(e1.EV.E1, e2.EV.E1) &&
 1709             !el_sideeffect(e)
 1710            )
 1711         {
 1712             e1.Eoper = OProl;
 1713             return el_selecte1(e);
 1714         }
 1715         // rotate right by a constant
 1716         if (e1.Eoper == OPshr && e2.Eoper == OPshl &&
 1717             tyuns(e2.EV.E1.Ety) &&
 1718             e1.EV.E2.Eoper == OPconst &&
 1719             e2.EV.E2.Eoper == OPconst &&
 1720             el_tolong(e2.EV.E2) == sz * 8 - el_tolong(e1.EV.E2) &&
 1721             el_match5(e1.EV.E1, e2.EV.E1) &&
 1722             !el_sideeffect(e)
 1723            )
 1724         {
 1725             e1.Eoper = OPror;
 1726             return el_selecte1(e);
 1727         }
 1728     }
 1729 
 1730     /* Recognize the following function and replace it with OPbswap:
 1731         ushort byteswap(ushort x) { return cast(ushort)(((x >> 8) & 0xFF) | ((x << 8) & 0xFF00)); }
 1732 
 1733          |  TYunsigned short
 1734           &  TYshort
 1735            32_16  TYshort
 1736             >>  TYint
 1737              u16_32  TYint
 1738               var  TYunsigned short  x
 1739              const  TYint 8L
 1740            const  TYshort 255
 1741           &  TYshort
 1742            <<  TYshort
 1743             var  TYshort  x
 1744             const  TYshort 8
 1745            const  TYshort 0xFF00
 1746      */
 1747     if (sz == 2 && OPTIMIZER)
 1748     {
 1749         if (e.Eoper == OPor &&
 1750             e1.Eoper == OPand &&
 1751             e2.Eoper == OPand)
 1752         {
 1753             elem* evar;
 1754             elem* evar2;
 1755             auto e11 = e1.EV.E1;
 1756             auto e12 = e1.EV.E2;
 1757             if (e11.Eoper == OP32_16 &&
 1758                 e12.Eoper == OPconst && el_tolong(e12) == 0xFF)
 1759             {
 1760                 auto e111 = e11.EV.E1;
 1761                 if (e111.Eoper == OPshr || e111.Eoper == OPashr)
 1762                 {
 1763                     auto e1111 = e111.EV.E1;
 1764                     auto e1112 = e111.EV.E2;
 1765                     if (e1112.Eoper == OPconst && el_tolong(e1112) == 8 &&
 1766                         e1111.Eoper == OPu16_32)
 1767                         evar = e1111.EV.E1;
 1768                 }
 1769             }
 1770 
 1771             if (evar)
 1772             {
 1773                 auto e22 = e2.EV.E2;
 1774                 if (e22.Eoper == OPconst && el_tolong(e22) == 0xFF00)
 1775                 {
 1776                     auto e21 = e2.EV.E1;
 1777                     if (e21.Eoper == OPshl)
 1778                     {
 1779                         auto e211 = e21.EV.E1;
 1780                         auto e212 = e21.EV.E2;
 1781                         if (e212.Eoper == OPconst && el_tolong(e212) == 8)
 1782                         {
 1783                             if (el_match5(evar, e211) && !el_sideeffect(e211))
 1784                             {
 1785                                 evar2 = e211;
 1786                                 e21.EV.E1 = null;
 1787                             }
 1788                         }
 1789                     }
 1790                 }
 1791             }
 1792 
 1793             if (evar2)
 1794             {
 1795                 el_free(e1);
 1796                 el_free(e2);
 1797                 e.Eoper = OPbswap;
 1798                 e.EV.E1 = evar2;
 1799                 e.EV.E2 = null;
 1800                 //printf("Matched byteswap(ushort)\n");
 1801                 return e;
 1802             }
 1803         }
 1804     }
 1805 
 1806     /* BSWAP: (data[0]<< 24) | (data[1]<< 16) | (data[2]<< 8) | (data[3]<< 0)
 1807      */
 1808     if (sz == 4 && OPTIMIZER)
 1809     {
 1810         elem*[4] ops;
 1811         int opsi = 0;
 1812         if (fillinops(ops.ptr, &opsi, 4, OPor, e) && opsi == 4)
 1813         {
 1814             elem *ex = null;
 1815             uint bmask = 0;
 1816             for (int i = 0; i < 4; i++)
 1817             {
 1818                 elem *eo = ops[i];
 1819                 elem *eo2;
 1820                 int shift;
 1821                 elem *eo111;
 1822                 if (eo.Eoper == OPu8_16 &&
 1823                     eo.EV.E1.Eoper == OPind)
 1824                 {
 1825                     eo111 = eo.EV.E1.EV.E1;
 1826                     shift = 0;
 1827                 }
 1828                 else if (eo.Eoper == OPshl &&
 1829                     eo.EV.E1.Eoper == OPu8_16 &&
 1830                     (eo2 = eo.EV.E2).Eoper == OPconst &&
 1831                     eo.EV.E1.EV.E1.Eoper == OPind)
 1832                 {
 1833                     shift = cast(int)el_tolong(eo2);
 1834                     switch (shift)
 1835                     {
 1836                         case 8:
 1837                         case 16:
 1838                         case 24:
 1839                             break;
 1840 
 1841                         default:
 1842                             goto L1;
 1843                     }
 1844                     eo111 = eo.EV.E1.EV.E1.EV.E1;
 1845                 }
 1846                 else
 1847                     goto L1;
 1848 
 1849                 uint off;
 1850                 elem *ed;
 1851                 if (eo111.Eoper == OPadd)
 1852                 {
 1853                     ed = eo111.EV.E1;
 1854                     if (eo111.EV.E2.Eoper != OPconst)
 1855                         goto L1;
 1856                     off = cast(uint)el_tolong(eo111.EV.E2);
 1857                     if (off < 1 || off > 3)
 1858                         goto L1;
 1859                 }
 1860                 else
 1861                 {
 1862                     ed = eo111;
 1863                     off = 0;
 1864                 }
 1865                 switch ((off << 5) | shift)
 1866                 {
 1867                     // BSWAP
 1868                     case (0 << 5) | 24: bmask |= 1; break;
 1869                     case (1 << 5) | 16: bmask |= 2; break;
 1870                     case (2 << 5) |  8: bmask |= 4; break;
 1871                     case (3 << 5) |  0: bmask |= 8; break;
 1872 
 1873                     // No swap
 1874                     case (0 << 5) |  0: bmask |= 0x10; break;
 1875                     case (1 << 5) |  8: bmask |= 0x20; break;
 1876                     case (2 << 5) | 16: bmask |= 0x40; break;
 1877                     case (3 << 5) | 24: bmask |= 0x80; break;
 1878 
 1879                     default:
 1880                         goto L1;
 1881                 }
 1882                 if (ex)
 1883                 {
 1884                     if (!el_match(ex, ed))
 1885                         goto L1;
 1886                 }
 1887                 else
 1888                 {   if (el_sideeffect(ed))
 1889                         goto L1;
 1890                     ex = ed;
 1891                 }
 1892             }
 1893             /* Got a match, build:
 1894              *   BSWAP(*ex)
 1895              */
 1896             if (bmask == 0x0F)
 1897                 e = el_una(OPbswap, e.Ety, el_una(OPind, e.Ety, ex));
 1898             else if (bmask == 0xF0)
 1899                 e = el_una(OPind, e.Ety, ex);
 1900             else
 1901                 goto L1;
 1902             return e;
 1903         }
 1904     }
 1905   L1:
 1906 
 1907     return elbitwise(e, goal);
 1908 }
 1909 
 1910 /*************************************
 1911  */
 1912 
 1913 private elem *elxor(elem *e, goal_t goal)
 1914 {
 1915     if (OPTIMIZER)
 1916     {
 1917         elem *e1 = e.EV.E1;
 1918         elem *e2 = e.EV.E2;
 1919 
 1920         /* Recognize:
 1921          *    (a & c) ^ (b & c)  =>  (a ^ b) & c
 1922          */
 1923         if (e1.Eoper == OPand && e2.Eoper == OPand &&
 1924             el_match5(e1.EV.E2, e2.EV.E2) &&
 1925             (e2.EV.E2.Eoper == OPconst || (!el_sideeffect(e2.EV.E1) && !el_sideeffect(e2.EV.E2))))
 1926         {
 1927             el_free(e1.EV.E2);
 1928             e1.EV.E2 = e2.EV.E1;
 1929             e1.Eoper = OPxor;
 1930             e.Eoper = OPand;
 1931             e.EV.E2 = e2.EV.E2;
 1932             e2.EV.E1 = null;
 1933             e2.EV.E2 = null;
 1934             el_free(e2);
 1935             return optelem(e, GOALvalue);
 1936         }
 1937     }
 1938     return elbitwise(e, goal);
 1939 }
 1940 
 1941 /**************************
 1942  * Optimize nots.
 1943  *      ! ! e => bool e
 1944  *      ! bool e => ! e
 1945  *      ! OTrel => !OTrel       (invert the condition)
 1946  *      ! OTconv => !
 1947  */
 1948 
 1949 private elem * elnot(elem *e, goal_t goal)
 1950 {
 1951     elem *e1 = e.EV.E1;
 1952     const op = e1.Eoper;
 1953     switch (op)
 1954     {
 1955         case OPnot:                     // ! ! e => bool e
 1956         case OPbool:                    // ! bool e => ! e
 1957             e1.Eoper = cast(ubyte)(op ^ (OPbool ^ OPnot));
 1958             /* That was a clever substitute for the following:  */
 1959             /* e.Eoper = (op == OPnot) ? OPbool : OPnot;               */
 1960             e = optelem(el_selecte1(e), goal);
 1961             break;
 1962 
 1963         default:
 1964             if (OTrel(op))                      /* ! OTrel => !OTrel            */
 1965             {
 1966                   /* Find the logical negation of the operator  */
 1967                   auto op2 = rel_not(op);
 1968                   if (!tyfloating(e1.EV.E1.Ety))
 1969                   {   op2 = rel_integral(op2);
 1970                       assert(OTrel(op2));
 1971                   }
 1972                   e1.Eoper = cast(ubyte)op2;
 1973                   e = optelem(el_selecte1(e), goal);
 1974             }
 1975             else if (tybasic(e1.Ety) == TYbool && tysize(e.Ety) == 1)
 1976             {
 1977                 // !e1 => (e1 ^ 1)
 1978                 e.Eoper = OPxor;
 1979                 e.EV.E2 = el_long(e1.Ety,1);
 1980                 e = optelem(e, goal);
 1981             }
 1982             else
 1983             {
 1984                 static if (0)
 1985                 {
 1986                     // Can't use this because what if OPd_s32?
 1987                     // Note: !(long)(.1) != !(.1)
 1988                     if (OTconv(op))             // don't use case because of differ target
 1989                     {   // conversion operators
 1990                         e1.Eoper = e.Eoper;
 1991                         e = optelem(el_selecte1(e), goal);
 1992                         break;
 1993                     }
 1994                 }
 1995             }
 1996             break;
 1997 
 1998         case OPs32_d:
 1999         case OPs16_d:
 2000         case OPu16_d:
 2001         case OPu32_d:
 2002         case OPf_d:
 2003         case OPs16_32:
 2004         case OPu16_32:
 2005         case OPu8_16:
 2006         case OPs8_16:
 2007         case OPu32_64:
 2008         case OPs32_64:
 2009         case OPvp_fp:
 2010         case OPcvp_fp:
 2011         case OPnp_fp:
 2012             e1.Eoper = e.Eoper;
 2013             e = optelem(el_selecte1(e), goal);
 2014             break;
 2015 
 2016         case OPcomma:
 2017             /* !(a,b) => (a,!b) */
 2018             e.Eoper = OPcomma;
 2019             e.EV.E1 = e1.EV.E1;             // a
 2020             e.EV.E2 = e1;                 // !
 2021             e1.Eoper = OPnot;
 2022             e1.Ety = e.Ety;
 2023             e1.EV.E1 = e1.EV.E2;            // b
 2024             e1.EV.E2 = null;
 2025             e = optelem(e, goal);
 2026             break;
 2027     }
 2028     return e;
 2029 }
 2030 
 2031 /*************************
 2032  * Complement
 2033  *      ~ ~ e => e
 2034  */
 2035 
 2036 private elem * elcom(elem *e, goal_t goal)
 2037 {
 2038     elem *e1 = e.EV.E1;
 2039     if (e1.Eoper == OPcom)                       // ~ ~ e => e
 2040         // Typing problem here
 2041         e = el_selecte1(el_selecte1(e));
 2042     return e;
 2043 }
 2044 
 2045 /*************************
 2046  * If it is a conditional of a constant
 2047  * then we know which exp to evaluate.
 2048  * BUG:
 2049  *      doesn't detect ("string" ? et : ef)
 2050  */
 2051 
 2052 private elem * elcond(elem *e, goal_t goal)
 2053 {
 2054     elem *e1 = e.EV.E1;
 2055     switch (e1.Eoper)
 2056     {
 2057         case OPconst:
 2058             if (boolres(e1))
 2059             L1:
 2060                 e = el_selecte1(el_selecte2(e));
 2061             else
 2062                 e = el_selecte2(el_selecte2(e));
 2063             break;
 2064 
 2065         case OPrelconst:
 2066         case OPstring:
 2067             goto L1;
 2068 
 2069         case OPcomma:
 2070             // ((a,b) ? c) => (a,(b ? c))
 2071             e.Eoper = OPcomma;
 2072             e.EV.E1 = e1.EV.E1;
 2073             e1.EV.E1 = e1.EV.E2;
 2074             e1.EV.E2 = e.EV.E2;
 2075             e.EV.E2 = e1;
 2076             e1.Eoper = OPcond;
 2077             e1.Ety = e.Ety;
 2078             return optelem(e,GOALvalue);
 2079 
 2080         case OPnot:
 2081         {
 2082             // (!a ? b : c) => (a ? c : b)
 2083             elem *ex = e.EV.E2.EV.E1;
 2084             e.EV.E2.EV.E1 = e.EV.E2.EV.E2;
 2085             e.EV.E2.EV.E2 = ex;
 2086             goto L2;
 2087         }
 2088 
 2089         default:
 2090             if (OTboolnop(e1.Eoper))
 2091             {
 2092         L2:
 2093                 e.EV.E1 = e1.EV.E1;
 2094                 e1.EV.E1 = null;
 2095                 el_free(e1);
 2096                 return elcond(e,goal);
 2097             }
 2098             if (!OPTIMIZER)
 2099                 break;
 2100 
 2101         {
 2102             tym_t ty = e.Ety;
 2103             elem *ec1 = e.EV.E2.EV.E1;
 2104             elem *ec2 = e.EV.E2.EV.E2;
 2105 
 2106             if (tyintegral(ty) && ec1.Eoper == OPconst && ec2.Eoper == OPconst)
 2107             {
 2108                 targ_llong i1 = el_tolong(ec1);
 2109                 targ_llong i2 = el_tolong(ec2);
 2110                 tym_t ty1 = tybasic(e1.Ety);
 2111 
 2112                 if ((ty1 == TYbool && !OTlogical(e1.Eoper) || e1.Eoper == OPand && e1.EV.E2.Eoper == OPconst) &&
 2113                     tysize(ty) == tysize(ec1.Ety))
 2114                 {
 2115                     targ_llong b = ty1 == TYbool ? 1 : el_tolong(e1.EV.E2);
 2116 
 2117                     if (b == 1 && ispow2(i1 - i2) != -1)
 2118                     {
 2119                         // replace (e1 ? i1 : i2) with (i1 + (e1 ^ 1) * (i2 - i1))
 2120                         // replace (e1 ? i2 : i1) with (i1 + e1 * (i2 - i1))
 2121                         int sz = tysize(e1.Ety);
 2122                         while (sz < tysize(ec1.Ety))
 2123                         {
 2124                             // Increase the size of e1 until it matches the size of ec1
 2125                             switch (sz)
 2126                             {
 2127                                 case 1:
 2128                                     e1 = el_una(OPu8_16, TYushort, e1);
 2129                                     sz = 2;
 2130                                     break;
 2131                                 case 2:
 2132                                     e1 = el_una(OPu16_32, TYulong, e1);
 2133                                     sz = 4;
 2134                                     break;
 2135                                 case 4:
 2136                                     e1 = el_una(OPu32_64, TYullong, e1);
 2137                                     sz = 8;
 2138                                     break;
 2139                                 default:
 2140                                     assert(0);
 2141                             }
 2142                         }
 2143                         if (i1 < i2)
 2144                         {
 2145                             ec2.EV.Vllong = i2 - i1;
 2146                             e1 = el_bin(OPxor,e1.Ety,e1,el_long(e1.Ety,1));
 2147                         }
 2148                         else
 2149                         {
 2150                             ec1.EV.Vllong = i2;
 2151                             ec2.EV.Vllong = i1 - i2;
 2152                         }
 2153                         e.EV.E1 = ec1;
 2154                         e.EV.E2.Eoper = OPmul;
 2155                         e.EV.E2.Ety = ty;
 2156                         e.EV.E2.EV.E1 = e1;
 2157                         e.Eoper = OPadd;
 2158                         return optelem(e,GOALvalue);
 2159                     }
 2160 
 2161                     /* If b is an integer with only 1 bit set then
 2162                      *   replace ((a & b) ? b : 0) with (a & b)
 2163                      *   replace ((a & b) ? 0 : b) with ((a & b) ^ b)
 2164                      */
 2165                     if (e1.Eoper == OPand && e1.EV.E2.Eoper == OPconst && ispow2(b) != -1) // if only 1 bit is set
 2166                     {
 2167                         if (b == i1 && i2 == 0)
 2168                         {   e = el_selecte1(e);
 2169                             e.EV.E1.Ety = ty;
 2170                             e.EV.E2.Ety = ty;
 2171                             e.EV.E2.EV.Vllong = b;
 2172                             return optelem(e,GOALvalue);
 2173                         }
 2174                         else if (i1 == 0 && b == i2)
 2175                         {
 2176                             e1.Ety = ty;
 2177                             e1.EV.E1.Ety = ty;
 2178                             e1.EV.E2.Ety = ty;
 2179                             e1.EV.E2.EV.Vllong = b;
 2180                             e.EV.E1 = el_bin(OPxor,ty,e1,el_long(ty,b));
 2181                             e = el_selecte1(e);
 2182                             return optelem(e,GOALvalue);
 2183                         }
 2184                     }
 2185                 }
 2186 
 2187                 /* Replace ((a relop b) ? 1 : 0) with (a relop b)       */
 2188                 else if (OTrel(e1.Eoper) &&
 2189                     tysize(ty) <= tysize(TYint))
 2190                 {
 2191                     if (i1 == 1 && i2 == 0)
 2192                         e = el_selecte1(e);
 2193                     else if (i1 == 0 && i2 == 1)
 2194                     {
 2195                         e.EV.E1 = el_una(OPnot,ty,e1);
 2196                         e = optelem(el_selecte1(e),GOALvalue);
 2197                     }
 2198                 }
 2199 
 2200                 // The next two optimizations attempt to replace with an
 2201                 // uint compare, which the code generator can generate
 2202                 // code for without using jumps.
 2203 
 2204                 // Try to replace (!e1) with (e1 < 1)
 2205                 else if (e1.Eoper == OPnot && !OTrel(e1.EV.E1.Eoper) && e1.EV.E1.Eoper != OPand)
 2206                 {
 2207                     e.EV.E1 = el_bin(OPlt,TYint,e1.EV.E1,el_long(touns(e1.EV.E1.Ety),1));
 2208                     e1.EV.E1 = null;
 2209                     el_free(e1);
 2210                 }
 2211                 // Try to replace (e1) with (e1 >= 1)
 2212                 else if (!OTrel(e1.Eoper) && e1.Eoper != OPand)
 2213                 {
 2214                     if (tyfv(e1.Ety))
 2215                     {
 2216                         if (tysize(e.Ety) == tysize(TYint))
 2217                         {
 2218                             if (i1 == 1 && i2 == 0)
 2219                             {   e.Eoper = OPbool;
 2220                                 el_free(e.EV.E2);
 2221                                 e.EV.E2 = null;
 2222                             }
 2223                             else if (i1 == 0 && i2 == 1)
 2224                             {   e.Eoper = OPnot;
 2225                                 el_free(e.EV.E2);
 2226                                 e.EV.E2 = null;
 2227                             }
 2228                         }
 2229                     }
 2230                     else if(tyintegral(e1.Ety))
 2231                         e.EV.E1 = el_bin(OPge,TYint,e1,el_long(touns(e1.Ety),1));
 2232                 }
 2233             }
 2234 
 2235             // Try to detect absolute value expression
 2236             // (a < 0) -a : a
 2237             else if ((e1.Eoper == OPlt || e1.Eoper == OPle) &&
 2238                 e1.EV.E2.Eoper == OPconst &&
 2239                 !boolres(e1.EV.E2) &&
 2240                 !tyuns(e1.EV.E1.Ety) &&
 2241                 !tyuns(e1.EV.E2.Ety) &&
 2242                 ec1.Eoper == OPneg &&
 2243                 !el_sideeffect(ec2) &&
 2244                 el_match(e.EV.E1.EV.E1,ec2) &&
 2245                 el_match(ec1.EV.E1,ec2) &&
 2246                 tysize(ty) >= _tysize[TYint]
 2247                )
 2248             {   e.EV.E2.EV.E2 = null;
 2249                 el_free(e);
 2250                 e = el_una(OPabs,ty,ec2);
 2251             }
 2252             // (a >= 0) a : -a
 2253             else if ((e1.Eoper == OPge || e1.Eoper == OPgt) &&
 2254                 e1.EV.E2.Eoper == OPconst &&
 2255                 !boolres(e1.EV.E2) &&
 2256                 !tyuns(e1.EV.E1.Ety) &&
 2257                 !tyuns(e1.EV.E2.Ety) &&
 2258                 ec2.Eoper == OPneg &&
 2259                 !el_sideeffect(ec1) &&
 2260                 el_match(e.EV.E1.EV.E1,ec1) &&
 2261                 el_match(ec2.EV.E1,ec1) &&
 2262                 tysize(ty) >= _tysize[TYint]
 2263                )
 2264             {   e.EV.E2.EV.E1 = null;
 2265                 el_free(e);
 2266                 e = el_una(OPabs,ty,ec1);
 2267             }
 2268 
 2269             /* Replace:
 2270              *    a ? noreturn : c
 2271              * with:
 2272              *    (a && noreturn), c
 2273              * because that means fewer noreturn cases for the data flow analysis to deal with
 2274              */
 2275             else if (!el_returns(ec1))
 2276             {
 2277                 e.Eoper = OPcomma;
 2278                 e.EV.E1 = e.EV.E2;
 2279                 e.EV.E2 = ec2;
 2280                 e.EV.E1.Eoper = OPandand;
 2281                 e.EV.E1.Ety = TYvoid;
 2282                 e.EV.E1.EV.E2 = ec1;
 2283                 e.EV.E1.EV.E1 = e1;
 2284             }
 2285 
 2286             /* Replace:
 2287              *    a ? b : noreturn
 2288              * with:
 2289              *    (a || noreturn), b
 2290              */
 2291             else if (!el_returns(ec2))
 2292             {
 2293                 e.Eoper = OPcomma;
 2294                 e.EV.E1 = e.EV.E2;
 2295                 e.EV.E2 = ec1;
 2296                 e.EV.E1.Eoper = OPoror;
 2297                 e.EV.E1.Ety = TYvoid;
 2298                 e.EV.E1.EV.E2 = ec2;
 2299                 e.EV.E1.EV.E1 = e1;
 2300             }
 2301 
 2302             break;
 2303         }
 2304     }
 2305     return e;
 2306 }
 2307 
 2308 
 2309 /****************************
 2310  * Comma operator.
 2311  *        ,      e
 2312  *       / \  =>                expression with no effect
 2313  *      c   e
 2314  *        ,               ,
 2315  *       / \    =>       / \    operators with no effect
 2316  *      +   e           ,   e
 2317  *     / \             / \
 2318  *    e   e           e   e
 2319  */
 2320 
 2321 private elem * elcomma(elem *e, goal_t goal)
 2322 {
 2323     int changes = -1;
 2324 L1:
 2325     changes++;
 2326 L2:
 2327     //printf("elcomma()\n");
 2328     elem *e2 = e.EV.E2;
 2329     elem **pe1 = &(e.EV.E1);
 2330     elem *e1 = *pe1;
 2331     int e1op = e1.Eoper;
 2332 
 2333   // c,e => e
 2334     if (OTleaf(e1op) && !OTsideff(e1op) && !(e1.Ety & (mTYvolatile | mTYshared)))
 2335     {
 2336         e2.Ety = e.Ety;
 2337         e = el_selecte2(e);
 2338         goto Lret;
 2339     }
 2340 
 2341     // ((a op b),e2) => ((a,b),e2)        if op has no side effects
 2342     if (!el_sideeffect(e1) && e1op != OPcomma && e1op != OPandand &&
 2343         e1op != OPoror && e1op != OPcond)
 2344     {
 2345         if (OTunary(e1op))
 2346             *pe1 = el_selecte1(e1); /* get rid of e1                */
 2347         else
 2348         {
 2349             e1.Eoper = OPcomma;
 2350             e1.Ety = e1.EV.E2.Ety;
 2351         }
 2352         goto L1;
 2353     }
 2354 
 2355     if (!OPTIMIZER)
 2356         goto Lret;
 2357 
 2358     /* Replace (a,b),e2 with a,(b,e2)   */
 2359     if (e1op == OPcomma)
 2360     {
 2361         e1.Ety = e.Ety;
 2362         e.EV.E1 = e1.EV.E1;
 2363         e1.EV.E1 = e1.EV.E2;
 2364         e1.EV.E2 = e2;
 2365         e.EV.E2 = elcomma(e1, GOALvalue);
 2366         goto L2;
 2367     }
 2368 
 2369     if ((OTopeq(e1op) || e1op == OPeq) &&
 2370         (e1.EV.E1.Eoper == OPvar || e1.EV.E1.Eoper == OPind) &&
 2371         !el_sideeffect(e1.EV.E1)
 2372        )
 2373     {
 2374         if (el_match(e1.EV.E1,e2))
 2375             // ((a = b),a) => (a = b)
 2376             e = el_selecte1(e);
 2377         else if (OTrel(e2.Eoper) &&
 2378                  OTleaf(e2.EV.E2.Eoper) &&
 2379                  el_match(e1.EV.E1,e2.EV.E1)
 2380                 )
 2381         {   // ((a = b),(a < 0)) => ((a = b) < 0)
 2382             e1.Ety = e2.EV.E1.Ety;
 2383             e.EV.E1 = e2.EV.E1;
 2384             e2.EV.E1 = e1;
 2385             goto L1;
 2386         }
 2387         else if ((e2.Eoper == OPandand ||
 2388                   e2.Eoper == OPoror   ||
 2389                   e2.Eoper == OPcond) &&
 2390                  el_match(e1.EV.E1,e2.EV.E1)
 2391                 )
 2392         {
 2393             /* ((a = b),(a || c)) => ((a = b) || c)     */
 2394             e1.Ety = e2.EV.E1.Ety;
 2395             e.EV.E1 = e2.EV.E1;
 2396             e2.EV.E1 = e1;
 2397             e = el_selecte2(e);
 2398             changes++;
 2399             goto Lret;
 2400         }
 2401         else if (e1op == OPeq)
 2402         {
 2403             /* Replace ((a = b),(c = a)) with a,(c = (a = b))   */
 2404             for (; e2.Eoper == OPcomma; e2 = e2.EV.E1)
 2405             { }
 2406             if ((OTopeq(e2.Eoper) || e2.Eoper == OPeq) &&
 2407                 el_match(e1.EV.E1,e2.EV.E2) &&
 2408                 //!(e1.EV.E1.Eoper == OPvar && el_appears(e2.EV.E1,e1.EV.E1.EV.Vsym)) &&
 2409                 ERTOL(e2))
 2410             {
 2411                 e.EV.E1 = e2.EV.E2;
 2412                 e1.Ety = e2.EV.E2.Ety;
 2413                 e2.EV.E2 = e1;
 2414                 goto L1;
 2415             }
 2416         }
 2417         else
 2418         {
 2419           static if (1) // This optimization is undone in eleq().
 2420           {
 2421             // Replace ((a op= b),(a op= c)) with (0,a = (a op b) op c)
 2422             for (; e2.Eoper == OPcomma; e2 = e2.EV.E1)
 2423             { }
 2424             if ((OTopeq(e2.Eoper)) &&
 2425                 el_match(e1.EV.E1,e2.EV.E1))
 2426             {
 2427                 elem *ex;
 2428                 e.EV.E1 = el_long(TYint,0);
 2429                 e1.Eoper = cast(ubyte)opeqtoop(e1op);
 2430                 e2.EV.E2 = el_bin(opeqtoop(e2.Eoper),e2.Ety,e1,e2.EV.E2);
 2431                 e2.Eoper = OPeq;
 2432                 goto L1;
 2433             }
 2434           }
 2435         }
 2436     }
 2437 Lret:
 2438     again = changes != 0;
 2439     return e;
 2440 }
 2441 
 2442 /********************************
 2443  */
 2444 
 2445 private elem * elremquo(elem *e, goal_t goal)
 2446 {
 2447     static if (0) version (MARS)
 2448     if (cnst(e.EV.E2) && !boolres(e.EV.E2))
 2449         error(e.Esrcpos.Sfilename, e.Esrcpos.Slinnum, e.Esrcpos.Scharnum, "divide by zero\n");
 2450 
 2451     return e;
 2452 }
 2453 
 2454 /********************************
 2455  */
 2456 
 2457 private elem * elmod(elem *e, goal_t goal)
 2458 {
 2459     tym_t tym = e.EV.E1.Ety;
 2460     if (!tyfloating(tym))
 2461         return eldiv(e, goal);
 2462     return e;
 2463 }
 2464 
 2465 /*****************************
 2466  * Convert divides to >> if power of 2.
 2467  * Can handle OPdiv, OPdivass, OPmod.
 2468  */
 2469 
 2470 private elem * eldiv(elem *e, goal_t goal)
 2471 {
 2472     //printf("eldiv()\n");
 2473     elem *e2 = e.EV.E2;
 2474     tym_t tym = e.EV.E1.Ety;
 2475     int uns = tyuns(tym) | tyuns(e2.Ety);
 2476     if (cnst(e2))
 2477     {
 2478         static if (0) version (MARS)
 2479         if (!boolres(e2))
 2480             error(e.Esrcpos.Sfilename, e.Esrcpos.Slinnum, e.Esrcpos.Scharnum, "divide by zero\n");
 2481 
 2482         if (uns)
 2483         {
 2484             e2.Ety = touns(e2.Ety);
 2485             int i = ispow2(el_tolong(e2));
 2486             if (i != -1)
 2487             {
 2488                 OPER op;
 2489                 switch (e.Eoper)
 2490                 {   case OPdiv:
 2491                         op = OPshr;
 2492                         goto L1;
 2493 
 2494                     case OPdivass:
 2495                         op = OPshrass;
 2496                     L1:
 2497                         e2.EV.Vint = i;
 2498                         e2.Ety = TYint;
 2499                         e.EV.E1.Ety = touns(tym);
 2500                         break;
 2501 
 2502                     case OPmod:
 2503                         op = OPand;
 2504                         goto L3;
 2505                     case OPmodass:
 2506                         op = OPandass;
 2507                     L3:
 2508                         e2.EV.Vullong = el_tolong(e2) - 1;
 2509                         break;
 2510 
 2511                     default:
 2512                         assert(0);
 2513                 }
 2514                 e.Eoper = cast(ubyte)op;
 2515                 return optelem(e,GOALvalue);
 2516             }
 2517         }
 2518     }
 2519 
 2520     if (OPTIMIZER)
 2521     {
 2522         const int SQRT_INT_MAX = 0xB504;
 2523         const uint SQRT_UINT_MAX = 0x10000;
 2524         elem *e1 = e.EV.E1;
 2525         if (tyintegral(tym) && e.Eoper == OPdiv && e2.Eoper == OPconst &&
 2526             e1.Eoper == OPdiv && e1.EV.E2.Eoper == OPconst)
 2527         {
 2528             /* Replace:
 2529              *   (e / c1) / c2
 2530              * With:
 2531              *   e / (c1 * c2)
 2532              */
 2533             targ_llong c1 = el_tolong(e1.EV.E2);
 2534             targ_llong c2 = el_tolong(e2);
 2535             bool uns1 = tyuns(e1.EV.E1.Ety) || tyuns(e1.EV.E2.Ety);
 2536             bool uns2 = tyuns(e1.Ety) || tyuns(e2.Ety);
 2537             if (uns1 == uns2)   // identity doesn't hold for mixed sign case
 2538             {
 2539                 // The transformation will fail if c1*c2 overflows. This substitutes
 2540                 // for a proper overflow check.
 2541                 if (uns1 ? (c1 < SQRT_UINT_MAX && c2 < SQRT_UINT_MAX)
 2542                          : (-SQRT_INT_MAX < c1 && c1 < SQRT_INT_MAX && -SQRT_INT_MAX < c2 && c2 < SQRT_INT_MAX))
 2543                 {
 2544                     e.EV.E1 = e1.EV.E1;
 2545                     e1.EV.E1 = e1.EV.E2;
 2546                     e1.EV.E2 = e2;
 2547                     e.EV.E2 = e1;
 2548                     e1.Eoper = OPmul;
 2549                     return optelem(e, GOALvalue);
 2550                 }
 2551             }
 2552         }
 2553 
 2554         if (tyintegral(tym) && e.Eoper == OPdiv && e2.Eoper == OPconst &&
 2555             e1.Eoper == OP64_32 &&
 2556             e1.EV.E1.Eoper == OPremquo && e1.EV.E1.EV.E2.Eoper == OPconst)
 2557         {
 2558             /* Replace:
 2559              *   (64_32 (e /% c1)) / c2
 2560              * With:
 2561              *   e / (c1 * c2)
 2562              */
 2563             elem *erq = e1.EV.E1;
 2564             targ_llong c1 = el_tolong(erq.EV.E2);
 2565             targ_llong c2 = el_tolong(e2);
 2566             bool uns1 = tyuns(erq.EV.E1.Ety) || tyuns(erq.EV.E2.Ety);
 2567             bool uns2 = tyuns(e1.Ety) || tyuns(e2.Ety);
 2568             if (uns1 == uns2)   // identity doesn't hold for mixed sign case
 2569             {
 2570                 // The transformation will fail if c1*c2 overflows. This substitutes
 2571                 // for a proper overflow check.
 2572                 if (uns1 ? (c1 < SQRT_UINT_MAX && c2 < SQRT_UINT_MAX)
 2573                          : (-SQRT_INT_MAX < c1 && c1 < SQRT_INT_MAX && -SQRT_INT_MAX < c2 && c2 < SQRT_INT_MAX))
 2574                 {
 2575                     e.EV.E1 = erq.EV.E1;
 2576                     erq.EV.E1 = erq.EV.E2;
 2577                     erq.EV.E2 = e2;
 2578                     e.EV.E2 = erq;
 2579                     erq.Eoper = OPmul;
 2580                     erq.Ety = e1.Ety;
 2581                     e1.EV.E1 = null;
 2582                     el_free(e1);
 2583                     return optelem(e, GOALvalue);
 2584                 }
 2585             }
 2586         }
 2587 
 2588         /* Convert if(e1/e2) to if(e1>=e2) iff uint division.
 2589          */
 2590         if (goal == GOALflags && uns && e.Eoper == OPdiv)
 2591         {
 2592             e.Eoper = OPge;
 2593             e.Ety = TYbool;
 2594             return e;
 2595         }
 2596 
 2597         /* TODO: (i*c1)/c2 => i*(c1/c2) if (c1%c2)==0
 2598          * TODO: i/(x?c1:c2) => i>>(x?log2(c1):log2(c2)) if c1 and c2 are powers of 2
 2599          */
 2600 
 2601         if (tyintegral(tym) && (e.Eoper == OPdiv || e.Eoper == OPmod))
 2602         {
 2603             int sz = tysize(tym);
 2604 
 2605             // See if we can replace with OPremquo
 2606             if (sz == REGSIZE
 2607                 // Currently don't allow this because OPmsw doesn't work for the case
 2608                 //|| (I64 && sz == 4)
 2609                 )
 2610             {
 2611                 // Don't do it if there are special code sequences in the
 2612                 // code generator (see cdmul())
 2613                 int pow2;
 2614                 if (e2.Eoper == OPconst &&
 2615                     !uns &&
 2616                     (pow2 = ispow2(el_tolong(e2))) != -1 &&
 2617                     !(config.target_cpu < TARGET_80286 && pow2 != 1 && e.Eoper == OPdiv)
 2618                    )
 2619                 { }
 2620                 else
 2621                 {
 2622                     assert(sz == 2 || sz == 4 || sz == 8);
 2623                     OPER op = OPmsw;
 2624                     if (e.Eoper == OPdiv)
 2625                     {
 2626                         op = (sz == 2) ? OP32_16 : (sz == 4) ? OP64_32 : OP128_64;
 2627                     }
 2628                     e.Eoper = OPremquo;
 2629                     e = el_una(op, tym, e);
 2630                     e.EV.E1.Ety = (sz == 2) ? TYlong : (sz == 4) ? TYllong : TYcent;
 2631                     return e;
 2632                 }
 2633             }
 2634         }
 2635     }
 2636 
 2637     return e;
 2638 }
 2639 
 2640 /**************************
 2641  * Convert (a op b) op c to a op (b op c).
 2642  */
 2643 
 2644 private elem * swaplog(elem *e, goal_t goal)
 2645 {
 2646     elem *e1 = e.EV.E1;
 2647     e.EV.E1 = e1.EV.E2;
 2648     e1.EV.E2 = e;
 2649     return optelem(e1,goal);
 2650 }
 2651 
 2652 private elem * eloror(elem *e, goal_t goal)
 2653 {
 2654     tym_t ty1,ty2;
 2655 
 2656     elem *e1 = e.EV.E1;
 2657     if (OTboolnop(e1.Eoper))
 2658     {
 2659         e.EV.E1 = e1.EV.E1;
 2660         e1.EV.E1 = null;
 2661         el_free(e1);
 2662         return eloror(e, goal);
 2663     }
 2664 
 2665     elem *e2 = e.EV.E2;
 2666     if (OTboolnop(e2.Eoper))
 2667     {
 2668         e.EV.E2 = e2.EV.E1;
 2669         e2.EV.E1 = null;
 2670         el_free(e2);
 2671         return eloror(e, goal);
 2672     }
 2673 
 2674     if (OPTIMIZER)
 2675     {
 2676         if (e1.Eoper == OPbool)
 2677         {   ty1 = e1.EV.E1.Ety;
 2678             e1 = e.EV.E1 = el_selecte1(e1);
 2679             e1.Ety = ty1;
 2680         }
 2681         if (e1.Eoper == OPoror)
 2682         {   /* convert (a||b)||c to a||(b||c). This will find more CSEs.    */
 2683             return swaplog(e, goal);
 2684         }
 2685         e2 = elscancommas(e2);
 2686         e1 = elscancommas(e1);
 2687     }
 2688 
 2689     tym_t t = e.Ety;
 2690     if (e2.Eoper == OPconst || e2.Eoper == OPrelconst || e2.Eoper == OPstring)
 2691     {
 2692         if (boolres(e2))                /* e1 || 1  => e1 , 1           */
 2693         {
 2694             if (e.EV.E2 == e2)
 2695                 goto L2;
 2696         }
 2697         else                            /* e1 || 0  =>  bool e1         */
 2698         {
 2699             if (e.EV.E2 == e2)
 2700             {
 2701                 el_free(e.EV.E2);
 2702                 e.EV.E2 = null;
 2703                 e.Eoper = OPbool;
 2704                 goto L3;
 2705             }
 2706         }
 2707     }
 2708 
 2709     if (e1.Eoper == OPconst || e1.Eoper == OPrelconst || e1.Eoper == OPstring)
 2710     {
 2711         if (boolres(e1))                /* (x,1) || e2  =>  (x,1),1     */
 2712         {
 2713             if (tybasic(e.EV.E2.Ety) == TYvoid)
 2714             {
 2715                 assert(!goal);
 2716                 el_free(e);
 2717                 return null;
 2718             }
 2719             else
 2720             {
 2721             L2:
 2722                 e.Eoper = OPcomma;
 2723                 el_free(e.EV.E2);
 2724                 e.EV.E2 = el_long(t,1);
 2725             }
 2726         }
 2727         else                            /* (x,0) || e2  =>  (x,0),(bool e2) */
 2728         {
 2729             e.Eoper = OPcomma;
 2730             if (tybasic(e.EV.E2.Ety) != TYvoid)
 2731                 e.EV.E2 = el_una(OPbool,t,e.EV.E2);
 2732         }
 2733   }
 2734   else if (OPTIMIZER &&
 2735         e.EV.E2.Eoper == OPvar &&
 2736         !OTlogical(e1.Eoper) &&
 2737         tysize(ty2 = e2.Ety) == tysize(ty1 = e1.Ety) &&
 2738         tysize(ty1) <= _tysize[TYint] &&
 2739         !tyfloating(ty2) &&
 2740         !tyfloating(ty1) &&
 2741         !(ty2 & (mTYvolatile | mTYshared)))
 2742     {   /* Convert (e1 || e2) => (e1 | e2)      */
 2743         e.Eoper = OPor;
 2744         e.Ety = ty1;
 2745         e = el_una(OPbool,t,e);
 2746     }
 2747     else if (OPTIMIZER &&
 2748              e1.Eoper == OPand && e2.Eoper == OPand &&
 2749              tysize(e1.Ety) == tysize(e2.Ety) &&
 2750              el_match(e1.EV.E1,e2.EV.E1) && !el_sideeffect(e1.EV.E1) &&
 2751              !el_sideeffect(e2.EV.E2)
 2752             )
 2753     {   // Convert ((a & b) || (a & c)) => bool(a & (b | c))
 2754         e.Eoper = OPbool;
 2755         e.EV.E2 = null;
 2756         e2.Eoper = OPor;
 2757         el_free(e2.EV.E1);
 2758         e2.EV.E1 = e1.EV.E2;
 2759         e1.EV.E2 = e2;
 2760     }
 2761     else
 2762         goto L1;
 2763 L3:
 2764     e = optelem(e,GOALvalue);
 2765 L1:
 2766     return e;
 2767 }
 2768 
 2769 /**********************************************
 2770  * Try to rewrite sequence of || and && with faster operations, such as BT.
 2771  * Returns:
 2772  *      false   nothing changed
 2773  *      true    *pe is rewritten
 2774  */
 2775 
 2776 private bool optim_loglog(elem **pe)
 2777 {
 2778     if (I16)
 2779         return false;
 2780     elem *e = *pe;
 2781     const op = e.Eoper;
 2782     assert(op == OPandand || op == OPoror);
 2783     size_t n = el_opN(e, op);
 2784     if (n <= 3)
 2785         return false;
 2786     uint ty = e.Ety;
 2787     elem **array = cast(elem **)malloc(n * (elem *).sizeof);
 2788     assert(array);
 2789     elem **p = array;
 2790     el_opArray(&p, e, op);
 2791 
 2792     bool any = false;
 2793     size_t first, last;
 2794     targ_ullong emin, emax;
 2795     int cmpop = op == OPandand ? OPne : OPeqeq;
 2796     for (size_t i = 0; i < n; ++i)
 2797     {
 2798         elem *eq = array[i];
 2799         if (eq.Eoper == cmpop &&
 2800             eq.EV.E2.Eoper == OPconst &&
 2801             tyintegral(eq.EV.E2.Ety) &&
 2802             !el_sideeffect(eq.EV.E1))
 2803         {
 2804             targ_ullong m = el_tolong(eq.EV.E2);
 2805             if (any)
 2806             {
 2807                 if (el_match(array[first].EV.E1, eq.EV.E1))
 2808                 {
 2809                     last = i;
 2810                     if (m < emin)
 2811                         emin = m;
 2812                     if (m > emax)
 2813                         emax = m;
 2814                 }
 2815                 else if (last - first > 2)
 2816                     break;
 2817                 else
 2818                 {
 2819                     first = last = i;
 2820                     emin = emax = m;
 2821                 }
 2822             }
 2823             else
 2824             {
 2825                 any = true;
 2826                 first = last = i;
 2827                 emin = emax = m;
 2828             }
 2829         }
 2830         else if (any && last - first > 2)
 2831             break;
 2832         else
 2833             any = false;
 2834     }
 2835 
 2836     //printf("n = %d, count = %d, min = %d, max = %d\n", (int)n, last - first + 1, (int)emin, (int)emax);
 2837     if (any && last - first > 2 && emax - emin < REGSIZE * 8)
 2838     {
 2839         /**
 2840          * Transforms expressions of the form x==c1 || x==c2 || x==c3 || ... into a single
 2841          * comparison by using a bitmapped representation of data, as follows. First, the
 2842          * smallest constant of c1, c2, ... (call it min) is subtracted from all constants
 2843          * and also from x (this step may be elided if all constants are small enough). Then,
 2844          * the test is expressed as
 2845          *   (1 << (x-min)) | ((1 << (c1-min)) | (1 << (c2-min)) | ...)
 2846          * The test is guarded for overflow (x must be no larger than the largest of c1, c2, ...).
 2847          * Since each constant is encoded as a displacement in a bitmap, hitting any bit yields
 2848          * true for the expression.
 2849          *
 2850          * I.e. replace:
 2851          *   e==c1 || e==c2 || e==c3 ...
 2852          * with:
 2853          *   (e - emin) <= (emax - emin) && (1 << (int)(e - emin)) & bits
 2854          * where bits is:
 2855          *   (1<<(c1-emin)) | (1<<(c2-emin)) | (1<<(c3-emin)) ...
 2856          *
 2857          * For the case of:
 2858          *  x!=c1 && x!=c2 && x!=c3 && ...
 2859          * using De Morgan's theorem, rewrite as:
 2860          *   (e - emin) > (emax - emin) || ((1 << (int)(e - emin)) & ~bits)
 2861          */
 2862 
 2863         // Delete all the || nodes that are no longer referenced
 2864         el_opFree(e, op);
 2865 
 2866         if (emax < 32)                  // if everything fits in a 32 bit register
 2867             emin = 0;                   // no need for bias
 2868 
 2869         // Compute bit mask
 2870         targ_ullong bits = 0;
 2871         for (size_t i = first; i <= last; ++i)
 2872         {
 2873             elem *eq = array[i];
 2874             if (0 && eq.EV.E2.Eoper != OPconst)
 2875             {
 2876                 printf("eq = %p, eq.EV.E2 = %p\n", eq, eq.EV.E2);
 2877                 printf("first = %d, i = %d, last = %d, Eoper = %d\n", cast(int)first, cast(int)i, cast(int)last, eq.EV.E2.Eoper);
 2878                 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);
 2879             }
 2880             assert(eq.EV.E2.Eoper == OPconst);
 2881             bits |= cast(targ_ullong)1 << (el_tolong(eq.EV.E2) - emin);
 2882         }
 2883         //printf("n = %d, count = %d, min = %d, max = %d\n", cast(int)n, last - first + 1, cast(int)emin, cast(int)emax);
 2884         //printf("bits = x%llx\n", bits);
 2885 
 2886         if (op == OPandand)
 2887             bits = ~bits;
 2888 
 2889         uint tyc = array[first].EV.E1.Ety;
 2890 
 2891         elem *ex = el_bin(OPmin, tyc, array[first].EV.E1, el_long(tyc,emin));
 2892         ex = el_bin(op == OPandand ? OPgt : OPle, TYbool, ex, el_long(touns(tyc), emax - emin));
 2893         elem *ey = el_bin(OPmin, tyc, array[first + 1].EV.E1, el_long(tyc,emin));
 2894 
 2895         tym_t tybits = TYuint;
 2896         if ((emax - emin) >= 32)
 2897         {
 2898             assert(I64);                // need 64 bit BT
 2899             tybits = TYullong;
 2900         }
 2901 
 2902         // Shift count must be an int
 2903         switch (tysize(tyc))
 2904         {
 2905             case 1:
 2906                 ey = el_una(OPu8_16,TYint,ey);
 2907                 goto case 2;
 2908 
 2909             case 2:
 2910                 ey = el_una(OPu16_32,TYint,ey);
 2911                 break;
 2912 
 2913             case 4:
 2914                 break;
 2915 
 2916             case 8:
 2917                 ey = el_una(OP64_32,TYint,ey);
 2918                 break;
 2919 
 2920             default:
 2921                 assert(0);
 2922         }
 2923         ey = el_bin(OPbtst,TYbool,el_long(tybits,bits),ey);
 2924         ex = el_bin(op == OPandand ? OPoror : OPandand, ty, ex, ey);
 2925 
 2926         /* Free unneeded nodes
 2927          */
 2928         array[first].EV.E1 = null;
 2929         el_free(array[first]);
 2930         array[first + 1].EV.E1 = null;
 2931         el_free(array[first + 1]);
 2932         for (size_t i = first + 2; i <= last; ++i)
 2933             el_free(array[i]);
 2934 
 2935         array[first] = ex;
 2936 
 2937         for (size_t i = first + 1; i + (last - first) < n; ++i)
 2938             array[i] = array[i + (last - first)];
 2939         n -= last - first;
 2940         (*pe) = el_opCombine(array, n, op, ty);
 2941 
 2942         free(array);
 2943         return true;
 2944     }
 2945 
 2946     free(array);
 2947     return false;
 2948 }
 2949 
 2950 private elem * elandand(elem *e, goal_t goal)
 2951 {
 2952     elem *e1 = e.EV.E1;
 2953     if (OTboolnop(e1.Eoper))
 2954     {
 2955         e.EV.E1 = e1.EV.E1;
 2956         e1.EV.E1 = null;
 2957         el_free(e1);
 2958         return elandand(e, goal);
 2959     }
 2960     elem *e2 = e.EV.E2;
 2961     if (OTboolnop(e2.Eoper))
 2962     {
 2963         e.EV.E2 = e2.EV.E1;
 2964         e2.EV.E1 = null;
 2965         el_free(e2);
 2966         return elandand(e, goal);
 2967     }
 2968     if (OPTIMIZER)
 2969     {
 2970         /* Recognize: (a >= c1 && a < c2)
 2971          */
 2972         if ((e1.Eoper == OPge || e1.Eoper == OPgt) &&
 2973             (e2.Eoper == OPlt || e2.Eoper == OPle) &&
 2974             e1.EV.E2.Eoper == OPconst && e2.EV.E2.Eoper == OPconst &&
 2975             !el_sideeffect(e1.EV.E1) && el_match(e1.EV.E1, e2.EV.E1) &&
 2976             tyintegral(e1.EV.E1.Ety) &&
 2977             tybasic(e1.EV.E2.Ety) == tybasic(e2.EV.E2.Ety) &&
 2978             tysize(e1.EV.E1.Ety) == _tysize[TYnptr])
 2979         {
 2980             /* Replace with: ((a - c1) < (c2 - c1))
 2981              */
 2982             targ_llong c1 = el_tolong(e1.EV.E2);
 2983             if (e1.Eoper == OPgt)
 2984                 ++c1;
 2985             targ_llong c2 = el_tolong(e2.EV.E2);
 2986             if (0 <= c1 && c1 <= c2)
 2987             {
 2988                 e1.Eoper = OPmin;
 2989                 e1.Ety = e1.EV.E1.Ety;
 2990                 e1.EV.E2.EV.Vllong = c1;
 2991                 e.EV.E2 = el_long(touns(e2.EV.E2.Ety), c2 - c1);
 2992                 e.Eoper = e2.Eoper;
 2993                 el_free(e2);
 2994                 return optelem(e, GOALvalue);
 2995             }
 2996         }
 2997 
 2998         // Look for (!(e >>> c) && ...)
 2999         if (e1.Eoper == OPnot && e1.EV.E1.Eoper == OPshr &&
 3000             e1.EV.E1.EV.E2.Eoper == OPconst)
 3001         {
 3002             // Replace (e >>> c) with (e & x)
 3003             elem *e11 = e1.EV.E1;
 3004 
 3005             targ_ullong shift = el_tolong(e11.EV.E2);
 3006             if (shift < _tysize[TYint] * 8)
 3007             {
 3008                 targ_ullong m;
 3009                 m = ~0L << cast(int)shift;
 3010                 e11.Eoper = OPand;
 3011                 e11.EV.E2.EV.Vullong = m;
 3012                 e11.EV.E2.Ety = e11.Ety;
 3013                 return optelem(e,GOALvalue);
 3014             }
 3015         }
 3016 
 3017         if (e1.Eoper == OPbool)
 3018         {
 3019             tym_t t = e1.EV.E1.Ety;
 3020             e1 = e.EV.E1 = el_selecte1(e1);
 3021             e1.Ety = t;
 3022         }
 3023         if (e1.Eoper == OPandand)
 3024         {   // convert (a&&b)&&c to a&&(b&&c). This will find more CSEs.
 3025             return swaplog(e, goal);
 3026         }
 3027         e2 = elscancommas(e2);
 3028 
 3029         while (1)
 3030         {
 3031             e1 = elscancommas(e1);
 3032             if (e1.Eoper == OPeq)
 3033                 e1 = e1.EV.E2;
 3034             else
 3035                 break;
 3036         }
 3037     }
 3038 
 3039     if (e2.Eoper == OPconst || e2.Eoper == OPrelconst || e2.Eoper == OPstring)
 3040     {
 3041         if (boolres(e2))        // e1 && (x,1)  =>  e1 ? ((x,1),1) : 0
 3042         {
 3043             if (e2 == e.EV.E2)    // if no x, replace e with (bool e1)
 3044             {
 3045                 el_free(e2);
 3046                 e.EV.E2 = null;
 3047                 e.Eoper = OPbool;
 3048                 goto L3;
 3049             }
 3050         }
 3051         else                            // e1 && (x,0)  =>  e1 , (x,0)
 3052         {
 3053             if (e2 == e.EV.E2)
 3054             {   e.Eoper = OPcomma;
 3055                 goto L3;
 3056             }
 3057         }
 3058     }
 3059 
 3060   if (e1.Eoper == OPconst || e1.Eoper == OPrelconst || e1.Eoper == OPstring)
 3061   {
 3062         e.Eoper = OPcomma;
 3063         if (boolres(e1))                // (x,1) && e2  =>  (x,1),bool e2
 3064         {
 3065             if (tybasic(e.EV.E2.Ety) != TYvoid)
 3066                 e.EV.E2 = el_una(OPbool,e.Ety,e.EV.E2);
 3067         }
 3068         else                            // (x,0) && e2  =>  (x,0),0
 3069         {
 3070             if (tybasic(e.EV.E2.Ety) == TYvoid)
 3071             {
 3072                 assert(!goal);
 3073                 el_free(e);
 3074                 return null;
 3075             }
 3076             else
 3077             {
 3078                 el_free(e.EV.E2);
 3079                 e.EV.E2 = el_long(e.Ety,0);
 3080             }
 3081         }
 3082     }
 3083     else
 3084         goto L1;
 3085 L3:
 3086     e = optelem(e,GOALvalue);
 3087 L1:
 3088     return e;
 3089 }
 3090 
 3091 /**************************
 3092  * Reference to bit field
 3093  *       bit
 3094  *       / \    =>      ((e << c) >> b) & m
 3095  *      e  w,b
 3096  *
 3097  * Note that this routine can handle long bit fields, though this may
 3098  * not be supported later on.
 3099  */
 3100 
 3101 private elem * elbit(elem *e, goal_t goal)
 3102 {
 3103 
 3104     tym_t tym1 = e.EV.E1.Ety;
 3105     uint sz = tysize(tym1) * 8;
 3106     elem *e2 = e.EV.E2;
 3107     uint wb = e2.EV.Vuns;
 3108 
 3109     uint w = (wb >> 8) & 0xFF;               // width in bits of field
 3110     targ_ullong m = (cast(targ_ullong)1 << w) - 1;   // mask w bits wide
 3111     uint b = wb & 0xFF;                      // bits to right of field
 3112     uint c = 0;
 3113     assert(w + b <= sz);
 3114 
 3115     if (tyuns(tym1))                      // if uint bit field
 3116     {
 3117         // Should use a more general solution to this
 3118         if (w == 8 && sz == 16 && b == 0)
 3119         {
 3120             e.EV.E1 = el_una(OP16_8,TYuchar,e.EV.E1);
 3121             e.Eoper = OPu8_16;
 3122             e.EV.E2 = null;
 3123             el_free(e2);
 3124             goto L1;
 3125         }
 3126 
 3127         if (w + b == sz)                // if field is left-justified
 3128             m = ~cast(targ_ullong)0;    // no need to mask
 3129     }
 3130     else                                // signed bit field
 3131     {
 3132         if (w == 8 && sz == 16 && b == 0)
 3133         {
 3134             e.EV.E1 = el_una(OP16_8,TYschar,e.EV.E1);
 3135             e.Eoper = OPs8_16;
 3136             e.EV.E2 = null;
 3137             el_free(e2);
 3138             goto L1;
 3139         }
 3140         m = ~cast(targ_ullong)0;
 3141         c = sz - (w + b);
 3142         b = sz - w;
 3143     }
 3144 
 3145     e.Eoper = OPand;
 3146 
 3147     e2.EV.Vullong = m;                   // mask w bits wide
 3148     e2.Ety = e.Ety;
 3149 
 3150     e.EV.E1 = el_bin(OPshr,tym1,
 3151                 el_bin(OPshl,tym1,e.EV.E1,el_long(TYint,c)),
 3152                 el_long(TYint,b));
 3153 L1:
 3154     return optelem(e,GOALvalue);         // optimize result
 3155 }
 3156 
 3157 /*****************
 3158  * Indirection
 3159  *      * & e => e
 3160  */
 3161 
 3162 private elem * elind(elem *e, goal_t goal)
 3163 {
 3164     tym_t tym = e.Ety;
 3165     elem *e1 = e.EV.E1;
 3166     switch (e1.Eoper)
 3167     {
 3168         case OPrelconst:
 3169             e.EV.E1.ET = e.ET;
 3170             e = el_selecte1(e);
 3171             e.Eoper = OPvar;
 3172             e.Ety = tym;               /* preserve original type       */
 3173             break;
 3174 
 3175         case OPadd:
 3176             if (OPTIMIZER)
 3177             {   /* Try to convert far pointer to stack pointer  */
 3178                 elem *e12 = e1.EV.E2;
 3179 
 3180                 if (e12.Eoper == OPrelconst &&
 3181                     tybasic(e12.Ety) == TYfptr &&
 3182                     /* If symbol is located on the stack        */
 3183                     sytab[e12.EV.Vsym.Sclass] & SCSS)
 3184                 {   e1.Ety = (e1.Ety & (mTYconst | mTYvolatile | mTYimmutable | mTYshared | mTYLINK)) | TYsptr;
 3185                     e12.Ety = (e12.Ety & (mTYconst | mTYvolatile | mTYimmutable | mTYshared | mTYLINK)) | TYsptr;
 3186                 }
 3187             }
 3188             break;
 3189 
 3190         case OPcomma:
 3191             // Replace (*(ea,eb)) with (ea,*eb)
 3192             e.EV.E1.ET = e.ET;
 3193             type *t = e.ET;
 3194             e = el_selecte1(e);
 3195             e.Ety = tym;
 3196             e.EV.E2 = el_una(OPind,tym,e.EV.E2);
 3197             e.EV.E2.ET = t;
 3198             again = 1;
 3199             return e;
 3200 
 3201         default:
 3202             break;
 3203     }
 3204     topair |= (config.fpxmmregs && tycomplex(tym));
 3205     return e;
 3206 }
 3207 
 3208 /*****************
 3209  * Address of.
 3210  *      & v => &v
 3211  *      & * e => e
 3212  *      & (v1 = v2) => ((v1 = v2), &v1)
 3213  */
 3214 
 3215 private elem * eladdr(elem *e, goal_t goal)
 3216 {
 3217     tym_t tym = e.Ety;
 3218     elem *e1 = e.EV.E1;
 3219     elem_debug(e1);
 3220     switch (e1.Eoper)
 3221     {
 3222         case OPvar:
 3223             e1.Eoper = OPrelconst;
 3224             e1.EV.Vsym.Sflags &= ~(SFLunambig | GTregcand);
 3225             e1.Ety = tym;
 3226             e = optelem(el_selecte1(e),GOALvalue);
 3227             break;
 3228 
 3229         case OPind:
 3230         {
 3231             tym_t tym2 = e1.EV.E1.Ety;
 3232 
 3233             // Watch out for conversions between near and far pointers
 3234             int sz = tysize(tym) - tysize(tym2);
 3235             if (sz != 0)
 3236             {
 3237                 OPER op;
 3238                 if (sz > 0)                         // if &far * near
 3239                     op = OPnp_fp;
 3240                 else                                // else &near * far
 3241                     op = OPoffset;
 3242                 e.Ety = tym2;
 3243                 e = el_una(op,tym,e);
 3244                 goto L1;
 3245             }
 3246 
 3247             e = el_selecte1(el_selecte1(e));
 3248             e.Ety = tym;
 3249             break;
 3250         }
 3251 
 3252         case OPcomma:
 3253             // Replace (&(ea,eb)) with (ea,&eb)
 3254             e = el_selecte1(e);
 3255             e.Ety = tym;
 3256             e.EV.E2 = el_una(OPaddr,tym,e.EV.E2);
 3257         L1:
 3258             e = optelem(e,GOALvalue);
 3259             break;
 3260 
 3261         case OPnegass:
 3262             assert(0);
 3263 
 3264         default:
 3265             if (OTassign(e1.Eoper))
 3266             {
 3267         case OPstreq:
 3268                 //  & (v1 = e) => ((v1 = e), &v1)
 3269                 if (e1.EV.E1.Eoper == OPvar)
 3270                 {
 3271                     e.Eoper = OPcomma;
 3272                     e.EV.E2 = el_una(OPaddr,tym,el_copytree(e1.EV.E1));
 3273                     goto L1;
 3274                 }
 3275                 //  & (*p1 = e) => ((*(t = p1) = e), t)
 3276                 else if (e1.EV.E1.Eoper == OPind)
 3277                 {
 3278                     const tym_t tym111 = e1.EV.E1.EV.E1.Ety;
 3279                     elem *tmp = el_alloctmp(tym111);
 3280                     e1.EV.E1.EV.E1 = el_bin(OPeq,tym111,tmp,e1.EV.E1.EV.E1);
 3281                     e.Eoper = OPcomma;
 3282                     e.EV.E2 = el_copytree(tmp);
 3283                     goto L1;
 3284                 }
 3285             }
 3286             break;
 3287 
 3288         case OPcond:
 3289         {   // Replace &(x ? y : z) with (x ? &y : &z)
 3290             elem *ecolon = e1.EV.E2;
 3291             ecolon.Ety = tym;
 3292             ecolon.EV.E1 = el_una(OPaddr,tym,ecolon.EV.E1);
 3293             ecolon.EV.E2 = el_una(OPaddr,tym,ecolon.EV.E2);
 3294             e = el_selecte1(e);
 3295             e = optelem(e,GOALvalue);
 3296             break;
 3297         }
 3298 
 3299         case OPinfo:
 3300             // Replace &(e1 info e2) with (e1 info &e2)
 3301             e = el_selecte1(e);
 3302             e.EV.E2 = el_una(OPaddr,tym,e.EV.E2);
 3303             e = optelem(e,GOALvalue);
 3304             break;
 3305     }
 3306     return e;
 3307 }
 3308 
 3309 /*******************************************
 3310  */
 3311 
 3312 private elem * elneg(elem *e, goal_t goal)
 3313 {
 3314     if (e.EV.E1.Eoper == OPneg)
 3315     {
 3316         e = el_selecte1(e);
 3317         e = el_selecte1(e);
 3318     }
 3319     /* Convert -(e1 + c) to (-e1 - c)
 3320      */
 3321     else if (e.EV.E1.Eoper == OPadd && e.EV.E1.EV.E2.Eoper == OPconst)
 3322     {
 3323         e.Eoper = OPmin;
 3324         e.EV.E2 = e.EV.E1.EV.E2;
 3325         e.EV.E1.Eoper = OPneg;
 3326         e.EV.E1.EV.E2 = null;
 3327         e = optelem(e,goal);
 3328     }
 3329     else
 3330         e = evalu8(e, goal);
 3331     return e;
 3332 }
 3333 
 3334 private elem * elcall(elem *e, goal_t goal)
 3335 {
 3336     if (e.EV.E1.Eoper == OPcomma || OTassign(e.EV.E1.Eoper))
 3337         e = cgel_lvalue(e);
 3338     return e;
 3339 }
 3340 
 3341 /***************************
 3342  * Walk tree, converting types to tym.
 3343  */
 3344 
 3345 private void elstructwalk(elem *e,tym_t tym)
 3346 {
 3347     tym_t ety;
 3348 
 3349     while ((ety = tybasic(e.Ety)) == TYstruct ||
 3350            ety == TYarray)
 3351     {   elem_debug(e);
 3352         e.Ety = (e.Ety & ~mTYbasic) | tym;
 3353         switch (e.Eoper)
 3354         {
 3355             case OPcomma:
 3356             case OPcond:
 3357             case OPinfo:
 3358                 break;
 3359 
 3360             case OPeq:
 3361             case OPcolon:
 3362             case OPcolon2:
 3363                 elstructwalk(e.EV.E1,tym);
 3364                 break;
 3365 
 3366             default:
 3367                 return;
 3368         }
 3369         e = e.EV.E2;
 3370     }
 3371 }
 3372 
 3373 /*******************************
 3374  * See if we can replace struct operations with simpler ones.
 3375  * For OPstreq and OPstrpar.
 3376  */
 3377 
 3378 elem * elstruct(elem *e, goal_t goal)
 3379 {
 3380     //printf("elstruct(%p)\n", e);
 3381     //elem_print(e);
 3382     if (e.Eoper == OPstreq && (e.EV.E1.Eoper == OPcomma || OTassign(e.EV.E1.Eoper)))
 3383         return cgel_lvalue(e);
 3384 
 3385     if (e.Eoper == OPstreq && e.EV.E2.Eoper == OPcomma)
 3386     {
 3387         /* Replace (e1 streq (e21, e22)) with (e21, (e1 streq e22))
 3388          */
 3389         e.EV.E2.Eoper = e.Eoper;
 3390         e.EV.E2.Ety = e.Ety;
 3391         e.EV.E2.ET = e.ET;
 3392         e.Eoper = OPcomma;
 3393         elem *etmp = e.EV.E1;
 3394         e.EV.E1 = e.EV.E2.EV.E1;
 3395         e.EV.E2.EV.E1 = etmp;
 3396         return optelem(e, goal);
 3397     }
 3398 
 3399     if (!e.ET)
 3400         return e;
 3401     //printf("\tnumbytes = %d\n", (int)type_size(e.ET));
 3402 
 3403     type *t = e.ET;
 3404     tym_t tym = ~0;
 3405     tym_t ty = tybasic(t.Tty);
 3406 
 3407     uint sz = (e.Eoper == OPstrpar && type_zeroSize(t, global_tyf)) ? 0 : cast(uint)type_size(t);
 3408     //printf("\tsz = %d\n", (int)sz);
 3409 
 3410     type *targ1 = null;
 3411     type *targ2 = null;
 3412     if (ty == TYstruct)
 3413     {   // If a struct is a wrapper for another type, prefer that other type
 3414         targ1 = t.Ttag.Sstruct.Sarg1type;
 3415         targ2 = t.Ttag.Sstruct.Sarg2type;
 3416     }
 3417 
 3418     if (ty == TYarray && sz && config.exe != EX_WIN64)
 3419     {
 3420         argtypes(t, targ1, targ2);
 3421         if (!targ1)
 3422             goto Ldefault;
 3423         goto L1;
 3424     }
 3425     //if (targ1) { printf("targ1\n"); type_print(targ1); }
 3426     //if (targ2) { printf("targ2\n"); type_print(targ2); }
 3427     switch (cast(int)sz)
 3428     {
 3429         case 1:  tym = TYchar;   goto L1;
 3430         case 2:  tym = TYshort;  goto L1;
 3431         case 4:  tym = TYlong;   goto L1;
 3432         case 8:  if (_tysize[TYint] == 2)
 3433                      goto Ldefault;
 3434                  tym = TYllong;  goto L1;
 3435 
 3436         case 3:  tym = TYlong;  goto L2;
 3437         case 5:
 3438         case 6:
 3439         case 7:  tym = TYllong;
 3440         L2:
 3441             if (e.Eoper == OPstrpar && config.exe == EX_WIN64)
 3442             {
 3443                  goto L1;
 3444             }
 3445             if (I64 && config.exe != EX_WIN64)
 3446             {
 3447                 goto L1;
 3448             }
 3449             tym = ~0;
 3450             goto Ldefault;
 3451 
 3452         case 10:
 3453         case 12:
 3454             if (tysize(TYldouble) == sz && targ1 && !targ2 && tybasic(targ1.Tty) == TYldouble)
 3455             {
 3456                 tym = TYldouble;
 3457                 goto L1;
 3458             }
 3459             goto case 9;
 3460 
 3461         case 9:
 3462         case 11:
 3463         case 13:
 3464         case 14:
 3465         case 15:
 3466             if (I64 && config.exe != EX_WIN64)
 3467             {
 3468                 goto L1;
 3469             }
 3470             goto Ldefault;
 3471 
 3472         case 16:
 3473             if (I64 && (ty == TYstruct || (ty == TYarray && config.exe == EX_WIN64)))
 3474             {
 3475                 tym = TYucent;
 3476                 goto L1;
 3477             }
 3478             if (config.exe == EX_WIN64)
 3479                 goto Ldefault;
 3480             if (targ1 && !targ2)
 3481                 goto L1;
 3482             goto Ldefault;
 3483 
 3484         L1:
 3485             if (ty == TYstruct || ty == TYarray)
 3486             {
 3487                 // This needs to match what TypeFunction::retStyle() does
 3488                 if (config.exe == EX_WIN64)
 3489                 {
 3490                     //if (t.Ttag.Sstruct.Sflags & STRnotpod)
 3491                         //goto Ldefault;
 3492                 }
 3493                 // If a struct is a wrapper for another type, prefer that other type
 3494                 else if (targ1 && !targ2)
 3495                     tym = targ1.Tty;
 3496                 else if (I64 && !targ1 && !targ2)
 3497                 {
 3498                     if (t.Ttag.Sstruct.Sflags & STRnotpod)
 3499                     {
 3500                         // In-memory only
 3501                         goto Ldefault;
 3502                     }
 3503 //                    if (type_size(t) == 16)
 3504                         goto Ldefault;
 3505                 }
 3506                 else if (I64 && targ1 && targ2)
 3507                 {
 3508                     if (tyfloating(tybasic(targ1.Tty)))
 3509                         tym = TYcdouble;
 3510                     else
 3511                         tym = TYucent;
 3512                     if ((0 == tyfloating(targ1.Tty)) ^ (0 == tyfloating(targ2.Tty)))
 3513                     {
 3514                         tym |= tyfloating(targ1.Tty) ? mTYxmmgpr : mTYgprxmm;
 3515                     }
 3516                 }
 3517                 else if (I32 && targ1 && targ2)
 3518                     tym = TYllong;
 3519                 assert(tym != TYstruct);
 3520             }
 3521             assert(tym != ~0);
 3522             switch (e.Eoper)
 3523             {
 3524                 case OPstreq:
 3525                     if (sz != tysize(tym))
 3526                     {
 3527                         // we can't optimize OPstreq in this case,
 3528                         // there will be memory corruption in the assignment
 3529                         elem *e2 = e.EV.E2;
 3530                         if (e2.Eoper != OPvar && e2.Eoper != OPind)
 3531                         {
 3532                             // the source may come in registers. ex: returned from a function.
 3533                             assert(tyaggregate(e2.Ety));
 3534                             e2 = optelem(e2, GOALvalue);
 3535                             e2 = elstruct(e2, GOALvalue);
 3536                             e2 = exp2_copytotemp(e2); // (tmp = e2, tmp)
 3537                             e2.EV.E2.EV.Vsym.Sfl = FLauto;
 3538                             e2.Ety = e2.EV.E2.Ety = e.Ety;
 3539                             e2.ET = e2.EV.E2.ET = e.ET;
 3540                             e.EV.E2 = e2;
 3541                         }
 3542                         break;
 3543                     }
 3544                     e.Eoper = OPeq;
 3545                     e.Ety = (e.Ety & ~mTYbasic) | tym;
 3546                     elstructwalk(e.EV.E1,tym);
 3547                     elstructwalk(e.EV.E2,tym);
 3548                     e = optelem(e,GOALvalue);
 3549                     break;
 3550 
 3551                 case OPstrpar:
 3552                     e = el_selecte1(e);
 3553                     goto default;
 3554 
 3555                 default:                /* called by doptelem()         */
 3556                     elstructwalk(e,tym);
 3557                     break;
 3558             }
 3559             break;
 3560 
 3561         case 0:
 3562             if (e.Eoper == OPstreq)
 3563             {
 3564                 e.Eoper = OPcomma;
 3565                 e = optelem(e,GOALvalue);
 3566                 again = 1;
 3567             }
 3568             else
 3569                 goto Ldefault;
 3570             break;
 3571 
 3572         default:
 3573         Ldefault:
 3574         {
 3575             elem **pe2;
 3576             if (e.Eoper == OPstreq)
 3577                 pe2 = &e.EV.E2;
 3578             else if (e.Eoper == OPstrpar)
 3579                 pe2 = &e.EV.E1;
 3580             else
 3581                 break;
 3582             while ((*pe2).Eoper == OPcomma)
 3583                 pe2 = &(*pe2).EV.E2;
 3584             elem *e2 = *pe2;
 3585 
 3586             if (e2.Eoper == OPvar)
 3587                 e2.EV.Vsym.Sflags &= ~GTregcand;
 3588 
 3589             // Convert (x streq (a?y:z)) to (x streq *(a ? &y : &z))
 3590             if (e2.Eoper == OPcond)
 3591             {
 3592                 tym_t ty2 = e2.Ety;
 3593 
 3594                 /* We should do the analysis to see if we can use
 3595                    something simpler than TYfptr.
 3596                  */
 3597                 tym_t typ = (_tysize[TYint] == LONGSIZE) ? TYnptr : TYfptr;
 3598                 e2 = el_una(OPaddr,typ,e2);
 3599                 e2 = optelem(e2,GOALvalue);          /* distribute & to x and y leaves */
 3600                 *pe2 = el_una(OPind,ty2,e2);
 3601                 break;
 3602             }
 3603             break;
 3604         }
 3605     }
 3606     return e;
 3607 }
 3608 
 3609 /**************************
 3610  * Assignment. Replace bit field assignment with
 3611  * equivalent tree.
 3612  *              =
 3613  *            /  \
 3614  *           /    r
 3615  *        bit
 3616  *       /   \
 3617  *      l     w,b
 3618  *
 3619  * becomes:
 3620  *          ,
 3621  *         / \
 3622  *        =   (r&m)
 3623  *       / \
 3624  *      l   |
 3625  *         / \
 3626  *  (r&m)<<b  &
 3627  *           / \
 3628  *          l  ~(m<<b)
 3629  * Note:
 3630  *      This depends on the expression (r&m)<<b before l. This is because
 3631  *      of expressions like (l.a = l.b = n). It is an artifact of the way
 3632  *      we do things that this works (cost() will rate the << as more
 3633  *      expensive than the &, and so it will wind up on the left).
 3634  */
 3635 
 3636 private elem * eleq(elem *e, goal_t goal)
 3637 {
 3638     goal_t wantres = goal;
 3639     elem *e1 = e.EV.E1;
 3640 
 3641     if (e1.Eoper == OPcomma || OTassign(e1.Eoper))
 3642         return cgel_lvalue(e);
 3643 
 3644 static if (0)  // Doesn't work too well, removed
 3645 {
 3646     // Replace (*p++ = e2) with ((*p = e2),*p++)
 3647     if (OPTIMIZER && e1.Eoper == OPind &&
 3648       (e1.EV.E1.Eoper == OPpostinc || e1.EV.E1.Eoper == OPpostdec) &&
 3649       !el_sideeffect(e1.EV.E1.EV.E1)
 3650        )
 3651     {
 3652         e = el_bin(OPcomma,e.Ety,e,e1);
 3653         e.EV.E1.EV.E1 = el_una(OPind,e1.Ety,el_copytree(e1.EV.E1.EV.E1));
 3654         return optelem(e,GOALvalue);
 3655     }
 3656 }
 3657 
 3658     if (OPTIMIZER)
 3659     {
 3660         elem *e2 = e.EV.E2;
 3661         int op2 = e2.Eoper;
 3662 
 3663         // Replace (e1 = *p++) with (e1 = *p, p++, e1)
 3664         elem *ei = e2;
 3665         if (e1.Eoper == OPvar &&
 3666             (op2 == OPind || (OTunary(op2) && (ei = e2.EV.E1).Eoper == OPind)) &&
 3667             (ei.EV.E1.Eoper == OPpostinc || ei.EV.E1.Eoper == OPpostdec) &&
 3668             !el_sideeffect(e1) &&
 3669             !el_sideeffect(ei.EV.E1.EV.E1)
 3670            )
 3671         {
 3672            e = el_bin(OPcomma,e.Ety,
 3673                 e,
 3674                 el_bin(OPcomma,e.Ety,ei.EV.E1,el_copytree(e1)));
 3675            ei.EV.E1 = el_copytree(ei.EV.E1.EV.E1);            // copy p
 3676            return optelem(e,GOALvalue);
 3677         }
 3678 
 3679         /* Replace (e = e) with (e,e)   */
 3680         if (el_match(e1,e2))
 3681         {
 3682             e.Eoper = OPcomma;
 3683         L1:
 3684             return optelem(e,GOALvalue);
 3685         }
 3686 
 3687         // Replace (e1 = (e21 , e22)) with (e21 , (e1 = e22))
 3688         if (op2 == OPcomma)
 3689         {
 3690             e2.Ety = e.Ety;
 3691             e.EV.E2 = e2.EV.E2;
 3692             e2.EV.E2 = e;
 3693             e = e2;
 3694             goto L1;
 3695         }
 3696 
 3697         if (OTop(op2) && !el_sideeffect(e1)
 3698             && op2 != OPdiv && op2 != OPmod
 3699            )
 3700         {
 3701             tym_t ty;
 3702 
 3703             version (MARS)
 3704                 enum side = false; // don't allow side effects in e2.EV.E2 because of
 3705                                    // D order-of-evaluation rules
 3706             else
 3707                 enum side = true;  // ok in C and C++
 3708 
 3709             // Replace (e1 = e1 op e) with (e1 op= e)
 3710             if (el_match(e1,e2.EV.E1) &&
 3711                 (side || !el_sideeffect(e2.EV.E2)))
 3712             {
 3713                 ty = e2.EV.E2.Ety;
 3714                 e.EV.E2 = el_selecte2(e2);
 3715             L2:
 3716                 e.EV.E2.Ety = ty;
 3717                 e.Eoper = cast(ubyte)optoopeq(op2);
 3718                 goto L1;
 3719             }
 3720             if (OTcommut(op2))
 3721             {
 3722                 /* Replace (e1 = e op e1) with (e1 op= e)       */
 3723                 if (el_match(e1,e2.EV.E2))
 3724                 {   ty = e2.EV.E1.Ety;
 3725                     e.EV.E2 = el_selecte1(e2);
 3726                     goto L2;
 3727                 }
 3728             }
 3729 
 3730 static if (0)
 3731 {
 3732 // Note that this optimization is undone in elcomma(), this results in an
 3733 // infinite loop. This optimization is preferable if e1 winds up a register
 3734 // variable, the inverse in elcomma() is preferable if e1 winds up in memory.
 3735             // Replace (e1 = (e1 op3 ea) op2 eb) with (e1 op3= ea),(e1 op2= eb)
 3736             int op3 = e2.EV.E1.Eoper;
 3737             if (OTop(op3) && el_match(e1,e2.EV.E1.EV.E1) && !el_depends(e1,e2.EV.E2))
 3738             {
 3739                 e.Eoper = OPcomma;
 3740                 e.EV.E1 = e2.EV.E1;
 3741                 e.EV.E1.Eoper = optoopeq(op3);
 3742                 e2.EV.E1 = e1;
 3743                 e1.Ety = e.EV.E1.Ety;
 3744                 e2.Eoper = optoopeq(op2);
 3745                 e2.Ety = e.Ety;
 3746                 goto L1;
 3747             }
 3748 }
 3749         }
 3750 
 3751         if (op2 == OPneg && el_match(e1,e2.EV.E1) && !el_sideeffect(e1))
 3752         {
 3753             // Replace (i = -i) with (negass i)
 3754             e.Eoper = OPnegass;
 3755             e.EV.E2 = null;
 3756             el_free(e2);
 3757             return optelem(e, GOALvalue);
 3758         }
 3759 
 3760         // Replace (x = (y ? z : x)) with ((y && (x = z)),x)
 3761         if (op2 == OPcond && el_match(e1,e2.EV.E2.EV.E2))
 3762         {
 3763             elem *e22 = e2.EV.E2;         // e22 is the OPcond
 3764             e.Eoper = OPcomma;
 3765             e.EV.E2 = e1;
 3766             e.EV.E1 = e2;
 3767             e2.Eoper = OPandand;
 3768             e2.Ety = TYint;
 3769             e22.Eoper = OPeq;
 3770             e22.Ety = e.Ety;
 3771             e1 = e22.EV.E1;
 3772             e22.EV.E1 = e22.EV.E2;
 3773             e22.EV.E2 = e1;
 3774             return optelem(e,GOALvalue);
 3775         }
 3776 
 3777         // Replace (x = (y ? x : z)) with ((y || (x = z)),x)
 3778         if (op2 == OPcond && el_match(e1,e2.EV.E2.EV.E1))
 3779         {
 3780             elem *e22 = e2.EV.E2;         // e22 is the OPcond
 3781             e.Eoper = OPcomma;
 3782             e.EV.E2 = e1;
 3783             e.EV.E1 = e2;
 3784             e2.Eoper = OPoror;
 3785             e2.Ety = TYint;
 3786             e22.Eoper = OPeq;
 3787             e22.Ety = e.Ety;
 3788             return optelem(e,GOALvalue);
 3789         }
 3790 
 3791         // If floating point, replace (x = -y) with (x = y ^ signbit)
 3792         if (op2 == OPneg && (tyreal(e2.Ety) || tyimaginary(e2.Ety)) &&
 3793             (e2.EV.E1.Eoper == OPvar || e2.EV.E1.Eoper == OPind) &&
 3794            /* Turned off for XMM registers because they don't play well with
 3795             * int registers.
 3796             */
 3797            !config.fpxmmregs)
 3798         {
 3799             tym_t ty;
 3800 
 3801             elem *es = el_calloc();
 3802             es.Eoper = OPconst;
 3803             switch (tysize(e2.Ety))
 3804             {
 3805                 case FLOATSIZE:
 3806                     ty = TYlong;
 3807                     es.EV.Vlong = 0x80000000;
 3808                     break;
 3809 
 3810                 case DOUBLESIZE:
 3811                     if (I32)
 3812                     {
 3813                         ty = TYllong;
 3814                         es.EV.Vllong = 0x8000000000000000L;
 3815                         break;
 3816                     }
 3817                     goto default;
 3818 
 3819                 default:
 3820                     el_free(es);
 3821                     goto L8;
 3822             }
 3823             es.Ety = ty;
 3824             e1.Ety = ty;
 3825             e2.Ety = ty;
 3826             e2.EV.E1.Ety = ty;
 3827             e2.EV.E2 = es;
 3828             e2.Eoper = OPxor;
 3829             return optelem(e,GOALvalue);
 3830 
 3831         L8:
 3832         }
 3833 
 3834         // Replace (a=(r1 pair r2)) with (a1=r1), (a2=r2)
 3835         if (tysize(e1.Ety) == 2 * REGSIZE &&
 3836             e1.Eoper == OPvar &&
 3837             (e2.Eoper == OPpair || e2.Eoper == OPrpair) &&
 3838             goal == GOALnone &&
 3839             !el_appears(e2, e1.EV.Vsym) &&
 3840 // this clause needs investigation because the code doesn't match the comment
 3841             // Disable this rewrite if we're using x87 and `e1` is a FP-value
 3842             // but `e2` is not, or vice versa
 3843             // https://issues.dlang.org/show_bug.cgi?id=18197
 3844             (config.fpxmmregs ||
 3845              (tyfloating(e2.EV.E1.Ety) != 0) == (tyfloating(e2.Ety) != 0))
 3846            )
 3847         {
 3848             // printf("** before:\n"); elem_print(e); printf("\n");
 3849             tym_t ty = (REGSIZE == 8) ? TYllong : TYint;
 3850             if (tyfloating(e1.Ety) && REGSIZE >= 4)
 3851                 ty = (REGSIZE == 8) ? TYdouble : TYfloat;
 3852             ty |= e1.Ety & ~mTYbasic;
 3853             e2.Ety = ty;
 3854             e.Ety = ty;
 3855             e1.Ety = ty;
 3856             elem *eb = el_copytree(e1);
 3857             eb.EV.Voffset += REGSIZE;
 3858 
 3859             if (e2.Eoper == OPpair)
 3860             {
 3861                 e.EV.E2 = e2.EV.E1;
 3862                 eb = el_bin(OPeq,ty,eb,e2.EV.E2);
 3863                 e2.EV.E1 = e;
 3864                 e2.EV.E2 = eb;
 3865             }
 3866             else
 3867             {
 3868                 e.EV.E2 = e2.EV.E2;
 3869                 eb = el_bin(OPeq,ty,eb,e2.EV.E1);
 3870                 e2.EV.E1 = eb;
 3871                 e2.EV.E2 = e;
 3872             }
 3873 
 3874             e2.Eoper = OPcomma;
 3875             // printf("** after:\n"); elem_print(e2); printf("\n");
 3876             return optelem(e2,goal);
 3877         }
 3878 
 3879         // Replace (a=b) with (a1=b1),(a2=b2)
 3880         if (tysize(e1.Ety) == 2 * REGSIZE &&
 3881             e1.Eoper == OPvar &&
 3882             e2.Eoper == OPvar &&
 3883             goal == GOALnone &&
 3884             !tyfloating(e1.Ety) && !tyvector(e1.Ety)
 3885            )
 3886         {
 3887             tym_t ty = (REGSIZE == 8) ? TYllong : TYint;
 3888             ty |= e1.Ety & ~mTYbasic;
 3889             e2.Ety = ty;
 3890             e.Ety = ty;
 3891             e1.Ety = ty;
 3892 
 3893             elem *eb = el_copytree(e);
 3894             eb.EV.E1.EV.Voffset += REGSIZE;
 3895             eb.EV.E2.EV.Voffset += REGSIZE;
 3896 
 3897             e = el_bin(OPcomma,ty,e,eb);
 3898             return optelem(e,goal);
 3899         }
 3900     }
 3901 
 3902    if (e1.Eoper == OPcomma)
 3903         return cgel_lvalue(e);
 3904 version (MARS)
 3905 {
 3906     // No bit fields to deal with
 3907     return e;
 3908 }
 3909 else
 3910 {
 3911   if (e1.Eoper != OPbit)
 3912         return e;
 3913   if (e1.EV.E1.Eoper == OPcomma || OTassign(e1.EV.E1.Eoper))
 3914         return cgel_lvalue(e);
 3915 
 3916     uint t = e.Ety;
 3917     elem *l = e1.EV.E1;                           // lvalue
 3918     elem *r = e.EV.E2;
 3919     tym_t tyl = l.Ety;
 3920     uint sz = tysize(tyl) * 8;
 3921     uint w = (e1.EV.E2.EV.Vuns >> 8);        // width in bits of field
 3922     targ_ullong m = (cast(targ_ullong)1 << w) - 1;  // mask w bits wide
 3923     uint b = e1.EV.E2.EV.Vuns & 0xFF;        // bits to shift
 3924 
 3925     elem *l2;
 3926     elem *r2;
 3927     elem *eres =  el_bin(OPeq,t,
 3928                 l,
 3929                 el_bin(OPor,t,
 3930                         el_bin(OPshl,t,
 3931                                 (r2 = el_bin(OPand,t,r,el_long(t,m))),
 3932                                 el_long(TYint,b)
 3933                         ),
 3934                         el_bin(OPand,t,
 3935                                 (l2 = el_copytree(l)),
 3936                                 el_long(t,~(m << b))
 3937                         )
 3938                 )
 3939           );
 3940     eres.Esrcpos = e.Esrcpos;           // save line information
 3941     if (OPTIMIZER && w + b == sz)
 3942         r2.EV.E2.EV.Vllong = ~ZEROLL;    // no need to mask if left justified
 3943     if (wantres)
 3944     {
 3945         uint c;
 3946         elem **pe;
 3947         elem *e2;
 3948 
 3949         r = el_copytree(r);
 3950         if (tyuns(tyl))                 /* uint bit field           */
 3951         {
 3952             e2 = el_bin(OPand,t,r,el_long(t,m));
 3953             pe = &e2.EV.E1;
 3954         }
 3955         else                            /* signed bit field             */
 3956         {
 3957             c = sz - w;                 /* e2 = (r << c) >> c           */
 3958             e2 = el_bin(OPshr,t,el_bin(OPshl,tyl,r,el_long(TYint,c)),el_long(TYint,c));
 3959             pe = &e2.EV.E1.EV.E1;
 3960         }
 3961         eres = el_bin(OPcomma,t,eres,e2);
 3962         if (!OTleaf(r.Eoper))
 3963             fixside(&(r2.EV.E1),pe);
 3964     }
 3965 
 3966     if (!OTleaf(l.Eoper) && !OTleaf(l.EV.E1.Eoper))
 3967         fixside(&(l2.EV.E1),&(l.EV.E1));
 3968     e1.EV.E1 = e.EV.E2 = null;
 3969     el_free(e);
 3970     return optelem(eres,GOALvalue);
 3971 }
 3972 }
 3973 
 3974 /**********************************
 3975  */
 3976 
 3977 private elem * elnegass(elem *e, goal_t goal)
 3978 {
 3979     e = cgel_lvalue(e);
 3980     return e;
 3981 }
 3982 
 3983 /**************************
 3984  * Add assignment. Replace bit field assignment with
 3985  * equivalent tree.
 3986  *             +=
 3987  *            /  \
 3988  *           /    r
 3989  *        bit
 3990  *       /   \
 3991  *      l     w,b
 3992  *
 3993  * becomes:
 3994  *                   =
 3995  *                  / \
 3996  *                 l   |
 3997  *                    / \
 3998  *                  <<   \
 3999  *                 /  \   \
 4000  *                &    b   &
 4001  *               / \      / \
 4002  *             op   m    l   ~(m<<b)
 4003  *            /  \
 4004  *           &    r
 4005  *          / \
 4006  *        >>   m
 4007  *       /  \
 4008  *      l    b
 4009  */
 4010 
 4011 private elem * elopass(elem *e, goal_t goal)
 4012 {
 4013     elem *e1 = e.EV.E1;
 4014     if (OTconv(e1.Eoper))
 4015     {   e = fixconvop(e);
 4016         return optelem(e,GOALvalue);
 4017     }
 4018 version (SCPP)   // have bit fields to worry about?
 4019 {
 4020     goal_t wantres = goal;
 4021     if (e1.Eoper == OPbit)
 4022     {
 4023         const op = opeqtoop(e.Eoper);
 4024 
 4025         // Make sure t is uint
 4026         // so >> doesn't have to be masked
 4027         tym_t t = touns(e.Ety);
 4028 
 4029         assert(tyintegral(t));
 4030         elem *l = e1.EV.E1;                       // lvalue
 4031         tym_t tyl = l.Ety;
 4032         elem *r = e.EV.E2;
 4033         uint w = (e1.EV.E2.EV.Vuns >> 8) & 0xFF; // width in bits of field
 4034         targ_llong m = (cast(targ_llong)1 << w) - 1;    // mask w bits wide
 4035         uint b = e1.EV.E2.EV.Vuns & 0xFF;        // bits to shift
 4036 
 4037         elem* l2,l3,op2,eres;
 4038 
 4039         if (tyuns(tyl))
 4040         {
 4041             eres = el_bin(OPeq,t,
 4042                     l,
 4043                     el_bin(OPor,t,
 4044                             (op2=el_bin(OPshl,t,
 4045                                     el_bin(OPand,t,
 4046                                             el_bin(op,t,
 4047                                                     el_bin(OPand,t,
 4048                                                         el_bin(OPshr,t,
 4049                                                             (l2=el_copytree(l)),
 4050                                                             el_long(TYint,b)
 4051                                                         ),
 4052                                                         el_long(t,m)
 4053                                                     ),
 4054                                                     r
 4055                                             ),
 4056                                             el_long(t,m)
 4057                                     ),
 4058                                     el_long(TYint,b)
 4059                             )),
 4060                             el_bin(OPand,t,
 4061                                     l3=el_copytree(l),
 4062                                     el_long(t,~(m << b))
 4063                             )
 4064                     )
 4065                 );
 4066 
 4067             if (wantres)
 4068             {
 4069                 eres = el_bin(OPcomma,t,eres,el_copytree(op2.EV.E1));
 4070                 fixside(&(op2.EV.E1),&(eres.EV.E2));
 4071             }
 4072         }
 4073         else
 4074         {   /* signed bit field
 4075                rewrite to:      (l bit w,b) = ((l bit w,b) op r)
 4076              */
 4077             e.Eoper = OPeq;
 4078             e.EV.E2 = el_bin(op,t,el_copytree(e1),r);
 4079             if (l.Eoper == OPind)
 4080                 fixside(&e.EV.E2.EV.E1.EV.E1.EV.E1,&l.EV.E1);
 4081             eres = e;
 4082             goto ret;
 4083         }
 4084 
 4085         if (!OTleaf(l.Eoper) && !OTleaf(l.EV.E1.Eoper))
 4086         {
 4087             fixside(&(l2.EV.E1),&(l.EV.E1));
 4088             el_free(l3.EV.E1);
 4089             l3.EV.E1 = el_copytree(l.EV.E1);
 4090         }
 4091 
 4092         e1.EV.E1 = e.EV.E2 = null;
 4093         el_free(e);
 4094     ret:
 4095         e = optelem(eres,GOALvalue);
 4096         return e;
 4097     }
 4098 }
 4099     {
 4100         if (e1.Eoper == OPcomma || OTassign(e1.Eoper))
 4101             e = cgel_lvalue(e);    // replace (e,v)op=e2 with e,(v op= e2)
 4102         else
 4103         {
 4104             switch (e.Eoper)
 4105             {
 4106                 case OPmulass:
 4107                     e = elmul(e,GOALvalue);
 4108                     break;
 4109 
 4110                 case OPdivass:
 4111                     // Replace r/=c with r=r/c
 4112                     if (tycomplex(e.EV.E2.Ety) && !tycomplex(e1.Ety))
 4113                     {
 4114                         elem *ed;
 4115                         e.Eoper = OPeq;
 4116                         if (e1.Eoper == OPind)
 4117                         {   // ed: *(tmp=e1.EV.E1)
 4118                             // e1: *tmp
 4119                             elem *tmp = el_alloctmp(e1.EV.E1.Ety);
 4120                             ed = el_bin(OPeq, tmp.Ety, tmp, e1.EV.E1);
 4121                             e1.EV.E1 = el_copytree(tmp);
 4122                             ed = el_una(OPind, e1.Ety, ed);
 4123                         }
 4124                         else
 4125                             ed = el_copytree(e1);
 4126                         // e: e1=ed/e2
 4127                         e.EV.E2 = el_bin(OPdiv, e.EV.E2.Ety, ed, e.EV.E2);
 4128                         if (tyreal(e1.Ety))
 4129                             e.EV.E2 = el_una(OPc_r, e1.Ety, e.EV.E2);
 4130                         else
 4131                             e.EV.E2 = el_una(OPc_i, e1.Ety, e.EV.E2);
 4132                         return optelem(e, GOALvalue);
 4133                     }
 4134                     // Replace x/=y with x=x/y
 4135                     if (OPTIMIZER &&
 4136                         tyintegral(e.EV.E1.Ety) &&
 4137                         e.EV.E1.Eoper == OPvar &&
 4138                         !el_sideeffect(e.EV.E1))
 4139                     {
 4140                         e.Eoper = OPeq;
 4141                         e.EV.E2 = el_bin(OPdiv, e.EV.E2.Ety, el_copytree(e.EV.E1), e.EV.E2);
 4142                         return optelem(e, GOALvalue);
 4143                     }
 4144                     e = eldiv(e, GOALvalue);
 4145                     break;
 4146 
 4147                 case OPmodass:
 4148                     // Replace x%=y with x=x%y
 4149                     if (OPTIMIZER &&
 4150                         tyintegral(e.EV.E1.Ety) &&
 4151                         e.EV.E1.Eoper == OPvar &&
 4152                         !el_sideeffect(e.EV.E1))
 4153                     {
 4154                         e.Eoper = OPeq;
 4155                         e.EV.E2 = el_bin(OPmod, e.EV.E2.Ety, el_copytree(e.EV.E1), e.EV.E2);
 4156                         return optelem(e, GOALvalue);
 4157                     }
 4158                     break;
 4159 
 4160                 default:
 4161                     break;
 4162             }
 4163         }
 4164     }
 4165     return e;
 4166 }
 4167 
 4168 /**************************
 4169  * Add assignment. Replace bit field post assignment with
 4170  * equivalent tree.
 4171  *      (l bit w,b) ++ r
 4172  * becomes:
 4173  *      (((l bit w,b) += r) - r) & m
 4174  */
 4175 
 4176 private elem * elpost(elem *e, goal_t goal)
 4177 {
 4178     elem *e1 = e.EV.E1;
 4179     if (e1.Eoper != OPbit)
 4180     {
 4181         if (e1.Eoper == OPcomma || OTassign(e1.Eoper))
 4182             return cgel_lvalue(e);    // replace (e,v)op=e2 with e,(v op= e2)
 4183         return e;
 4184     }
 4185 
 4186     assert(e.EV.E2.Eoper == OPconst);
 4187     targ_llong r = el_tolong(e.EV.E2);
 4188 
 4189     uint w = (e1.EV.E2.EV.Vuns >> 8) & 0xFF;  // width in bits of field
 4190     targ_llong m = (cast(targ_llong)1 << w) - 1;     // mask w bits wide
 4191 
 4192     tym_t ty = e.Ety;
 4193     if (e.Eoper != OPpostinc)
 4194         r = -r;
 4195     e.Eoper = (e.Eoper == OPpostinc) ? OPaddass : OPminass;
 4196     e = el_bin(OPmin,ty,e,el_long(ty,r));
 4197     if (tyuns(e1.EV.E1.Ety))             /* if uint bit field        */
 4198         e = el_bin(OPand,ty,e,el_long(ty,m));
 4199     return optelem(e,GOALvalue);
 4200 }
 4201 
 4202 /***************************
 4203  * Take care of compares.
 4204  *      (e == 0) => (!e)
 4205  *      (e != 0) => (bool e)
 4206  */
 4207 
 4208 private elem * elcmp(elem *e, goal_t goal)
 4209 {
 4210     elem *e2 = e.EV.E2;
 4211     elem *e1 = e.EV.E1;
 4212 
 4213     //printf("elcmp(%p)\n",e); elem_print(e);
 4214 
 4215     if (OPTIMIZER)
 4216     {
 4217         auto op = e.Eoper;
 4218 
 4219         // Convert comparison of OPrelconsts of the same symbol to comparisons
 4220         // of their offsets.
 4221         if (e1.Eoper == OPrelconst && e2.Eoper == OPrelconst &&
 4222             e1.EV.Vsym == e2.EV.Vsym)
 4223         {
 4224             e1.Eoper = OPconst;
 4225             e1.Ety = TYptrdiff;
 4226             e2.Eoper = OPconst;
 4227             e2.Ety = TYptrdiff;
 4228             return optelem(e,GOALvalue);
 4229         }
 4230 
 4231         // Convert comparison of long pointers to comparison of integers
 4232         if ((op == OPlt || op == OPle || op == OPgt || op == OPge) &&
 4233             tyfv(e2.Ety) && tyfv(e1.Ety))
 4234         {
 4235             e.EV.E1 = el_una(OP32_16,e.Ety,e1);
 4236             e.EV.E2 = el_una(OP32_16,e.Ety,e2);
 4237             return optelem(e,GOALvalue);
 4238         }
 4239 
 4240         // Convert ((e & 1) == 1) => (e & 1)
 4241         if (op == OPeqeq && e2.Eoper == OPconst && e1.Eoper == OPand)
 4242         {
 4243             elem *e12 = e1.EV.E2;
 4244 
 4245             if (e12.Eoper == OPconst && el_tolong(e2) == 1 && el_tolong(e12) == 1)
 4246             {
 4247                 tym_t ty = e.Ety;
 4248                 tym_t ty1 = e1.Ety;
 4249                 e = el_selecte1(e);
 4250                 e.Ety = ty1;
 4251                 int sz = tysize(ty);
 4252                 for (int sz1 = tysize(ty1); sz1 != sz; sz1 = tysize(e.Ety))
 4253                 {
 4254                     switch (sz1)
 4255                     {
 4256                         case 1:
 4257                             e = el_una(OPu8_16,TYshort,e);
 4258                             break;
 4259                         case 2:
 4260                             if (sz > 2)
 4261                                 e = el_una(OPu16_32,TYlong,e);
 4262                             else
 4263                                 e = el_una(OP16_8,TYuchar,e);
 4264                             break;
 4265                         case 4:
 4266                             if (sz > 2)
 4267                                 e = el_una(OPu32_64,TYshort,e);
 4268                             else
 4269                                 e = el_una(OP32_16,TYshort,e);
 4270                             break;
 4271                         case 8:
 4272                             e = el_una(OP64_32,TYlong,e);
 4273                             break;
 4274                         default:
 4275                             assert(0);
 4276                     }
 4277                 }
 4278                 e.Ety = ty;
 4279                 return optelem(e,GOALvalue);
 4280             }
 4281         }
 4282     }
 4283 
 4284     int uns = tyuns(e1.Ety) | tyuns(e2.Ety);
 4285     if (cnst(e2))
 4286     {
 4287         tym_t tym;
 4288         int sz = tysize(e2.Ety);
 4289 
 4290         if (e1.Eoper == OPu16_32 && e2.EV.Vulong <= cast(targ_ulong) SHORTMASK ||
 4291             e1.Eoper == OPs16_32 &&
 4292             e2.EV.Vlong == cast(targ_short) e2.EV.Vlong)
 4293         {
 4294             tym = (uns || e1.Eoper == OPu16_32) ? TYushort : TYshort;
 4295             e.EV.E2 = el_una(OP32_16,tym,e2);
 4296             goto L2;
 4297         }
 4298 
 4299         /* Try to convert to byte/word comparison for ((x & c)==d)
 4300            when mask c essentially casts x to a smaller type
 4301          */
 4302         if (OPTIMIZER &&
 4303             e1.Eoper == OPand &&
 4304             e1.EV.E2.Eoper == OPconst &&
 4305             sz > CHARSIZE)
 4306         {
 4307             OPER op;
 4308             assert(tyintegral(e2.Ety) || typtr(e2.Ety));
 4309             /* ending up with byte ops in A regs */
 4310             if (!(el_tolong(e2) & ~CHARMASK) &&
 4311                 !(el_tolong(e1.EV.E2) & ~CHARMASK)
 4312                )
 4313             {
 4314                 if (sz == LLONGSIZE)
 4315                 {
 4316                     e1.EV.E1 = el_una(OP64_32,TYulong,e1.EV.E1);
 4317                     e1.EV.E1 = el_una(OP32_16,TYushort,e1.EV.E1);
 4318                 }
 4319                 else if (sz == LONGSIZE)
 4320                     e1.EV.E1 = el_una(OP32_16,TYushort,e1.EV.E1);
 4321                 tym = TYuchar;
 4322                 op = OP16_8;
 4323                 goto L4;
 4324             }
 4325             if (_tysize[TYint] == SHORTSIZE && /* not a win when regs are long */
 4326                 sz == LONGSIZE &&
 4327                 !(e2.EV.Vulong & ~SHORTMASK) &&
 4328                 !(e1.EV.E2.EV.Vulong & ~SHORTMASK)
 4329                )
 4330             {
 4331                 tym = TYushort;
 4332                 op = OP32_16;
 4333             L4:
 4334                 e2.Ety = tym;
 4335                 e1.Ety = tym;
 4336                 e1.EV.E2.Ety = tym;
 4337                 e1.EV.E1 = el_una(op,tym,e1.EV.E1);
 4338                 e = optelem(e,GOALvalue);
 4339                 goto ret;
 4340             }
 4341         }
 4342 
 4343         /* Convert (ulong > uint.max) to (msw(ulong) != 0)
 4344          */
 4345         if (OPTIMIZER && I32 && e.Eoper == OPgt && sz == LLONGSIZE && e2.EV.Vullong == 0xFFFFFFFF)
 4346         {
 4347             e.Eoper = OPne;
 4348             e2.Ety = TYulong;
 4349             e2.EV.Vulong = 0;
 4350             e.EV.E1 = el_una(OPmsw,TYulong,e1);
 4351             e = optelem(e,GOALvalue);
 4352             goto ret;
 4353         }
 4354 
 4355         if (e1.Eoper == OPu8_16 && e2.EV.Vuns < 256 ||
 4356             e1.Eoper == OPs8_16 &&
 4357             e2.EV.Vint == cast(targ_schar) e2.EV.Vint)
 4358         {
 4359             tym = (uns || e1.Eoper == OPu8_16) ? TYuchar : TYschar;
 4360             e.EV.E2 = el_una(OP16_8,tym,e2);
 4361         L2:
 4362             tym |= e1.Ety & ~mTYbasic;
 4363             e.EV.E1 = el_selecte1(e1);
 4364             e.EV.E1.Ety = tym;
 4365             e = optelem(e,GOALvalue);
 4366         }
 4367         else if (!boolres(e2))
 4368         {
 4369             targ_int i;
 4370             switch (e.Eoper)
 4371             {
 4372                 case OPle:              // (u <= 0) becomes (u == 0)
 4373                     if (!uns)
 4374                         break;
 4375                     goto case OPeqeq;
 4376 
 4377                 case OPeqeq:
 4378                     e.Eoper = OPnot;
 4379                     goto L5;
 4380 
 4381                 case OPgt:              // (u > 0) becomes (u != 0)
 4382                     if (!uns)
 4383                         break;
 4384                     goto case OPne;
 4385 
 4386                 case OPne:
 4387                     e.Eoper = OPbool;
 4388                 L5: el_free(e2);
 4389                     e.EV.E2 = null;
 4390                     e = optelem(e,GOALvalue);
 4391                     break;
 4392 
 4393                 case OPge:
 4394                     i = 1;              // (u >= 0) becomes (u,1)
 4395                     goto L3;
 4396 
 4397                 case OPlt:              // (u < 0) becomes (u,0)
 4398                     i = 0;
 4399                 L3:
 4400                     if (uns)
 4401                     {
 4402                         e2.EV.Vint = i;
 4403                         e2.Ety = TYint;
 4404                         e.Eoper = OPcomma;
 4405                         e = optelem(e,GOALvalue);
 4406                     }
 4407                     else
 4408                     {
 4409                         if (tyintegral(e1.Ety) && sz == 2 * REGSIZE)
 4410                         {
 4411                             // Only need to examine MSW
 4412                             tym_t ty = sz == 4 ? TYint :
 4413                                        sz == 8 ? TYint :
 4414                                                  TYlong;        // for TYcent's
 4415                             e.EV.E1 = el_una(OPmsw, ty, e1);
 4416                             e2.Ety = ty;
 4417                             return optelem(e, GOALvalue);
 4418                         }
 4419                     }
 4420                     break;
 4421 
 4422                 default:
 4423                     break;
 4424             }
 4425         }
 4426         else if (OPTIMIZER && uns && tysize(e2.Ety) == 2 &&
 4427                  cast(ushort)e2.EV.Vuns == 0x8000 &&
 4428                  (e.Eoper == OPlt || e.Eoper == OPge)
 4429                 )
 4430         {
 4431             // Convert to signed comparison against 0
 4432             tym_t ty = tybasic(e2.Ety);
 4433             switch (_tysize[ty])
 4434             {
 4435                 case 1:     ty = TYschar;   break;
 4436                 case 2:     ty = TYshort;   break;
 4437                 default:    assert(0);
 4438             }
 4439             e.Eoper ^= (OPlt ^ OPge);      // switch between them
 4440             e2.EV.Vuns = 0;
 4441             e2.Ety = ty | (e2.Ety & ~mTYbasic);
 4442             e1.Ety = ty | (e1.Ety & ~mTYbasic);
 4443         }
 4444         else if (OPTIMIZER && e1.Eoper == OPeq &&
 4445                  e1.EV.E2.Eoper == OPconst)
 4446         {    // Convert ((x = c1) rel c2) to ((x = c1),(c1 rel c2)
 4447              elem *ec = el_copytree(e1.EV.E2);
 4448              ec.Ety = e1.Ety;
 4449              e.EV.E1 = ec;
 4450              e = el_bin(OPcomma,e.Ety,e1,e);
 4451              e = optelem(e,GOALvalue);
 4452         }
 4453     }
 4454     else if ((
 4455              (e1.Eoper == OPu8_16 ||
 4456               e1.Eoper == OPs8_16)||
 4457              (e1.Eoper == OPu16_32 ||
 4458               e1.Eoper == OPs16_32)
 4459              ) &&
 4460              e1.Eoper == e2.Eoper)
 4461     {
 4462         if (uns)
 4463         {
 4464             e1.EV.E1.Ety = touns(e1.EV.E1.Ety);
 4465             e2.EV.E1.Ety = touns(e2.EV.E1.Ety);
 4466         }
 4467         e1.Ety = e1.EV.E1.Ety;
 4468         e2.Ety = e2.EV.E1.Ety;
 4469         e.EV.E1 = el_selecte1(e1);
 4470         e.EV.E2 = el_selecte1(e2);
 4471         e = optelem(e,GOALvalue);
 4472     }
 4473 ret:
 4474     return e;
 4475 }
 4476 
 4477 /*****************************
 4478  * Boolean operator.
 4479  *      OPbool
 4480  */
 4481 
 4482 private elem * elbool(elem *e, goal_t goal)
 4483 {
 4484     //printf("elbool()\n");
 4485     if (OTlogical(e.EV.E1.Eoper) ||
 4486         // bool bool => bool
 4487         (tybasic(e.EV.E1.Ety) == TYbool && tysize(e.Ety) == 1)
 4488        )
 4489         return el_selecte1(e);
 4490 
 4491     if (OPTIMIZER)
 4492     {
 4493         int shift;
 4494 
 4495         // Replace bool(x,1) with (x,1),1
 4496         elem *e1 = elscancommas(e.EV.E1);
 4497         if (cnst(e1) || e1.Eoper == OPrelconst)
 4498         {
 4499             int i = boolres(e1) != 0;
 4500             e.Eoper = OPcomma;
 4501             e.EV.E2 = el_long(e.Ety,i);
 4502             e = optelem(e,GOALvalue);
 4503             return e;
 4504         }
 4505 
 4506         // Replace bool(e & 1) with (uint char)(e & 1)
 4507         else if (e.EV.E1.Eoper == OPand && e.EV.E1.EV.E2.Eoper == OPconst && el_tolong(e.EV.E1.EV.E2) == 1)
 4508         {
 4509         L1:
 4510             uint sz = tysize(e.EV.E1.Ety);
 4511             tym_t ty = e.Ety;
 4512             switch (sz)
 4513             {
 4514                 case 1:
 4515                     e = el_selecte1(e);
 4516                     break;
 4517 
 4518                 case 2:
 4519                     e.Eoper = OP16_8;
 4520                     break;
 4521 
 4522                 case 4:
 4523                     e.Eoper = OP32_16;
 4524                     e.Ety = TYushort;
 4525                     e = el_una(OP16_8, ty, e);
 4526                     break;
 4527 
 4528                 case 8:
 4529                     e.Eoper = OP64_32;
 4530                     e.Ety = TYulong;
 4531                     e = el_una(OP32_16, TYushort, e);
 4532                     e = el_una(OP16_8, ty, e);
 4533                     break;
 4534 
 4535                 default:
 4536                     assert(0);
 4537             }
 4538             e = optelem(e,GOALvalue);
 4539         }
 4540 
 4541         // Replace bool(e % 2) with (uint char)(e & 1)
 4542         else if (e.EV.E1.Eoper == OPmod && e.EV.E1.EV.E2.Eoper == OPconst && el_tolong(e.EV.E1.EV.E2) == 2
 4543             && !tyfloating(e.EV.E1.Ety)) // dont optimize fmod()
 4544         {
 4545             uint sz = tysize(e.EV.E1.Ety);
 4546             tym_t ty = e.Ety;
 4547             e.EV.E1.Eoper = OPand;
 4548             e.EV.E1.EV.E2.EV.Vullong = 1;
 4549             switch (sz)
 4550             {
 4551                 case 1:
 4552                     e = el_selecte1(e);
 4553                     break;
 4554 
 4555                 case 2:
 4556                     e.Eoper = OP16_8;
 4557                     break;
 4558 
 4559                 case 4:
 4560                     e.Eoper = OP32_16;
 4561                     e.Ety = TYushort;
 4562                     e = el_una(OP16_8, ty, e);
 4563                     break;
 4564 
 4565                 case 8:
 4566                     e.Eoper = OP64_32;
 4567                     e.Ety = TYulong;
 4568                     e = el_una(OP32_16, TYushort, e);
 4569                     e = el_una(OP16_8, ty, e);
 4570                     break;
 4571 
 4572                 default:
 4573                     assert(0);
 4574             }
 4575             e = optelem(e,GOALvalue);
 4576         }
 4577 
 4578         // Replace bool((1<<c)&b) with -(b btst c)
 4579         else if ((I32 || I64) &&
 4580                  e.EV.E1.Eoper == OPand &&
 4581                  e.EV.E1.EV.E1.Eoper == OPshl &&
 4582                  e.EV.E1.EV.E1.EV.E1.Eoper == OPconst && el_tolong(e.EV.E1.EV.E1.EV.E1) == 1 &&
 4583                  tysize(e.EV.E1.Ety) <= REGSIZE
 4584                 )
 4585         {
 4586             tym_t ty = e.Ety;
 4587             elem *ex = e.EV.E1.EV.E1;
 4588             ex.Eoper = OPbtst;
 4589             e.EV.E1.EV.E1 = null;
 4590             ex.EV.E1 = e.EV.E1.EV.E2;
 4591             e.EV.E1.EV.E2 = null;
 4592             ex.Ety = e.Ety;
 4593             el_free(e);
 4594             e = ex;
 4595             return optelem(e,GOALvalue);
 4596         }
 4597 
 4598         // Replace bool(a & c) when c is a power of 2 with ((a >> shift) & 1)
 4599         else if (e.EV.E1.Eoper == OPand &&
 4600                  e.EV.E1.EV.E2.Eoper == OPconst &&
 4601                  (shift = ispow2(el_tolong(e.EV.E1.EV.E2))) != -1
 4602                 )
 4603         {
 4604             e.EV.E1.EV.E1 = el_bin(OPshr, e.EV.E1.EV.E1.Ety, e.EV.E1.EV.E1, el_long(TYint, shift));
 4605             e.EV.E1.EV.E2.EV.Vullong = 1;
 4606             goto L1;
 4607         }
 4608     }
 4609     return e;
 4610 }
 4611 
 4612 
 4613 /*********************************
 4614  * Conversions of pointers to far pointers.
 4615  */
 4616 
 4617 private elem * elptrlptr(elem *e, goal_t goal)
 4618 {
 4619     if (e.EV.E1.Eoper == OPrelconst || e.EV.E1.Eoper == OPstring)
 4620     {
 4621         e.EV.E1.Ety = e.Ety;
 4622         e = el_selecte1(e);
 4623     }
 4624     return e;
 4625 }
 4626 
 4627 
 4628 /*********************************
 4629  * Conversions of handle pointers to far pointers.
 4630  */
 4631 private elem * elvptrfptr(elem *e, goal_t goal)
 4632 {
 4633     elem *e1 = e.EV.E1;
 4634     if (e1.Eoper == OPadd || e1.Eoper == OPmin)
 4635     {
 4636         elem *e12 = e1.EV.E2;
 4637         if (tybasic(e12.Ety) != TYvptr)
 4638         {
 4639             /* Rewrite (vtof(e11 + e12)) to (vtof(e11) + e12)   */
 4640             const op = e.Eoper;
 4641             e.Eoper = e1.Eoper;
 4642             e.EV.E2 = e12;
 4643             e1.Ety = e.Ety;
 4644             e1.Eoper = cast(ubyte)op;
 4645             e1.EV.E2 = null;
 4646             e = optelem(e,GOALvalue);
 4647         }
 4648     }
 4649     return e;
 4650 }
 4651 
 4652 
 4653 /************************
 4654  * Optimize conversions of longs to ints.
 4655  * Also used for (OPoffset) (TYfptr|TYvptr).
 4656  * Also used for conversions of ints to bytes.
 4657  */
 4658 
 4659 private elem * ellngsht(elem *e, goal_t goal)
 4660 {
 4661     //printf("ellngsht()\n");
 4662     tym_t ty = e.Ety;
 4663     elem *e1 = e.EV.E1;
 4664     switch (e1.Eoper)
 4665     {
 4666     case OPs16_32:
 4667     case OPu16_32:
 4668     case OPu8_16:
 4669     case OPs8_16:
 4670         // This fix is not quite right. For example, it fails
 4671         // if e.Ety != e.EV.E1.EV.E1.Ety. The difference is when
 4672         // one is uint and the other isn't.
 4673         if (tysize(ty) != tysize(e.EV.E1.EV.E1.Ety))
 4674             break;
 4675         e = el_selecte1(el_selecte1(e));
 4676         e.Ety = ty;
 4677         return e;
 4678 
 4679     case OPvar:                 // simply paint type of variable
 4680         // Do not paint type of ints into bytes, as this causes
 4681         // many CSEs to be missed, resulting in bad code.
 4682         // Loading a word anyway is just as fast as loading a byte.
 4683         // for 68000 byte is swapped, load byte != load word
 4684         if (e.Eoper == OP16_8)
 4685         {
 4686             // Mark symbol as being used sometimes as a byte to
 4687             // 80X86 - preclude using SI or DI
 4688             // 68000 - preclude using An
 4689             e1.EV.Vsym.Sflags |= GTbyte;
 4690         }
 4691         else
 4692             e1.Ety = ty;
 4693         e = el_selecte1(e);
 4694         break;
 4695 
 4696     case OPind:
 4697         e = el_selecte1(e);
 4698         break;
 4699 
 4700     case OPnp_fp:
 4701         if (e.Eoper != OPoffset)
 4702             goto case_default;
 4703         // Replace (offset)(ptrlptr)e11 with e11
 4704         e = el_selecte1(el_selecte1(e));
 4705         e.Ety = ty;                    // retain original type
 4706         break;
 4707 
 4708     case OPbtst:
 4709         e = el_selecte1(e);
 4710         break;
 4711 
 4712     default: // operator
 4713     case_default:
 4714         // Attempt to replace (lngsht)(a op b) with
 4715         // ((lngsht)a op (lngsht)b).
 4716         // op is now an integer op, which is cheaper.
 4717         if (OTwid(e1.Eoper) && !OTassign(e1.Eoper))
 4718         {
 4719             tym_t ty1 = e1.EV.E1.Ety;
 4720             switch (e.Eoper)
 4721             {
 4722                 case OP16_8:
 4723                     // Make sure e1.EV.E1 is of the type we're converting from
 4724                     if (tysize(ty1) <= _tysize[TYint])
 4725                     {
 4726                         ty1 = (tyuns(ty1) ? TYuchar : TYschar) |
 4727                                     (ty1 & ~mTYbasic);
 4728                         e1.EV.E1 = el_una(e.Eoper,ty1,e1.EV.E1);
 4729                     }
 4730                     // Rvalue may be an int if it is a shift operator
 4731                     if (OTbinary(e1.Eoper))
 4732                     {   tym_t ty2 = e1.EV.E2.Ety;
 4733 
 4734                         if (tysize(ty2) <= _tysize[TYint])
 4735                         {
 4736                             ty2 = (tyuns(ty2) ? TYuchar : TYschar) |
 4737                                         (ty2 & ~mTYbasic);
 4738                             e1.EV.E2 = el_una(e.Eoper,ty2,e1.EV.E2);
 4739                         }
 4740                     }
 4741                     break;
 4742 
 4743                 case OPoffset:
 4744                     if (_tysize[TYint] == LONGSIZE)
 4745                     {
 4746                         // Make sure e1.EV.E1 is of the type we're converting from
 4747                         if (tysize(ty1) > LONGSIZE)
 4748                         {
 4749                             ty1 = (tyuns(ty1) ? TYuint : TYint) | (ty1 & ~mTYbasic);
 4750                             e1.EV.E1 = el_una(e.Eoper,ty1,e1.EV.E1);
 4751                         }
 4752                         // Rvalue may be an int if it is a shift operator
 4753                         if (OTbinary(e1.Eoper))
 4754                         {   tym_t ty2 = e1.EV.E2.Ety;
 4755 
 4756                             if (tysize(ty2) > LONGSIZE)
 4757                             {
 4758                                 ty2 = (tyuns(ty2) ? TYuint : TYint) |
 4759                                             (ty2 & ~mTYbasic);
 4760                                 e1.EV.E2 = el_una(e.Eoper,ty2,e1.EV.E2);
 4761                             }
 4762                         }
 4763                         break;
 4764                     }
 4765                     goto case OP32_16;
 4766 
 4767                 case OP32_16:
 4768                     // Make sure e1.EV.E1 is of the type we're converting from
 4769                     if (tysize(ty1) == LONGSIZE)
 4770                     {
 4771                         ty1 = (tyuns(ty1) ? TYushort : TYshort) | (ty1 & ~mTYbasic);
 4772                         e1.EV.E1 = el_una(e.Eoper,ty1,e1.EV.E1);
 4773                     }
 4774                     // Rvalue may be an int if it is a shift operator
 4775                     if (OTbinary(e1.Eoper))
 4776                     {   tym_t ty2 = e1.EV.E2.Ety;
 4777 
 4778                         if (tysize(ty2) == LONGSIZE)
 4779                         {
 4780                             ty2 = (tyuns(ty2) ? TYushort : TYshort) |
 4781                                         (ty2 & ~mTYbasic);
 4782                             e1.EV.E2 = el_una(e.Eoper,ty2,e1.EV.E2);
 4783                         }
 4784                     }
 4785                     break;
 4786 
 4787                 default:
 4788                     assert(0);
 4789             }
 4790             e1.Ety = ty;
 4791             e = el_selecte1(e);
 4792             again = 1;
 4793             return e;
 4794         }
 4795         break;
 4796     }
 4797     return e;
 4798 }
 4799 
 4800 
 4801 /************************
 4802  * Optimize conversions of long longs to ints.
 4803  * OP64_32, OP128_64
 4804  */
 4805 
 4806 private elem * el64_32(elem *e, goal_t goal)
 4807 {
 4808     tym_t ty = e.Ety;
 4809     elem *e1 = e.EV.E1;
 4810     switch (e1.Eoper)
 4811     {
 4812     case OPs32_64:
 4813     case OPu32_64:
 4814     case OPs64_128:
 4815     case OPu64_128:
 4816         if (tysize(ty) != tysize(e.EV.E1.EV.E1.Ety))
 4817             break;
 4818         e = el_selecte1(el_selecte1(e));
 4819         e.Ety = ty;
 4820         break;
 4821 
 4822     case OPpair:
 4823         if (tysize(ty) != tysize(e.EV.E1.EV.E1.Ety))
 4824             break;
 4825         if (el_sideeffect(e1.EV.E2))
 4826         {
 4827             // Rewrite (OP64_32(a pair b)) as ((t=a),(b,t))
 4828             elem *a = e1.EV.E1;
 4829             elem *b = e1.EV.E2;
 4830             elem *t = el_alloctmp(a.Ety);
 4831 
 4832             e.Eoper = OPcomma;
 4833             e.EV.E1 = el_bin(OPeq,a.Ety,t,a);
 4834             e.EV.E2 = e1;
 4835 
 4836             e1.Eoper = OPcomma;
 4837             e1.EV.E1 = b;
 4838             e1.EV.E2 = el_copytree(t);
 4839             e1.Ety = e.Ety;
 4840             break;
 4841         }
 4842         e = el_selecte1(el_selecte1(e));
 4843         e.Ety = ty;
 4844         break;
 4845 
 4846     case OPrpair:
 4847         if (tysize(ty) != tysize(e.EV.E1.EV.E2.Ety))
 4848             break;
 4849         if (el_sideeffect(e1.EV.E1))
 4850         {
 4851             // Rewrite (OP64_32(a rpair b)) as (a,b)
 4852             e = el_selecte1(e);
 4853             e.Eoper = OPcomma;
 4854             e.Ety = ty;
 4855             break;
 4856         }
 4857         e = el_selecte2(el_selecte1(e));
 4858         e.Ety = ty;
 4859         break;
 4860 
 4861     case OPvar:                 // simply paint type of variable
 4862     case OPind:
 4863         e = el_selecte1(e);
 4864         break;
 4865 
 4866     case OPshr:                 // OP64_32(x >> 32) => OPmsw(x)
 4867         if (e1.EV.E2.Eoper == OPconst &&
 4868             (e.Eoper == OP64_32 && el_tolong(e1.EV.E2) == 32 && !I64 ||
 4869              e.Eoper == OP128_64 && el_tolong(e1.EV.E2) == 64 && I64)
 4870            )
 4871         {
 4872             e.Eoper = OPmsw;
 4873             e.EV.E1 = el_selecte1(e.EV.E1);
 4874         }
 4875         break;
 4876 
 4877     case OPmul:
 4878         static if (TARGET_OSX) // https://issues.dlang.org/show_bug.cgi?id=21047
 4879             break;
 4880         else
 4881             goto case;
 4882 
 4883     case OPadd:
 4884     case OPmin:
 4885     case OPor:
 4886     case OPand:
 4887     case OPxor:
 4888         // OP64_32(a op b) => (OP64_32(a) op OP64_32(b))
 4889         e1.EV.E1 = el_una(e.Eoper, ty, e1.EV.E1);
 4890         e1.EV.E2 = el_una(e.Eoper, ty, e1.EV.E2);
 4891         e = el_selecte1(e);
 4892         break;
 4893 
 4894     default:
 4895         break;
 4896     }
 4897     return e;
 4898 }
 4899 
 4900 
 4901 /*******************************
 4902  * Convert complex to real.
 4903  */
 4904 
 4905 private elem *elc_r(elem *e, goal_t goal)
 4906 {
 4907     elem *e1 = e.EV.E1;
 4908 
 4909     if (e1.Eoper == OPvar || e1.Eoper == OPind)
 4910     {
 4911         e1.Ety = e.Ety;
 4912         e = el_selecte1(e);
 4913     }
 4914     return e;
 4915 }
 4916 
 4917 /*******************************
 4918  * Convert complex to imaginary.
 4919  */
 4920 
 4921 private elem *elc_i(elem *e, goal_t goal)
 4922 {
 4923     elem *e1 = e.EV.E1;
 4924 
 4925     if (e1.Eoper == OPvar)
 4926     {
 4927         e1.Ety = e.Ety;
 4928         e1.EV.Voffset += tysize(e.Ety);
 4929         e = el_selecte1(e);
 4930     }
 4931     else if (e1.Eoper == OPind)
 4932     {
 4933         e1.Ety = e.Ety;
 4934         e = el_selecte1(e);
 4935         e.EV.E1 = el_bin(OPadd, e.EV.E1.Ety, e.EV.E1, el_long(TYint, tysize(e.Ety)));
 4936         return optelem(e, GOALvalue);
 4937     }
 4938 
 4939     return e;
 4940 }
 4941 
 4942 /******************************
 4943  * Handle OPu8_16 and OPs8_16.
 4944  */
 4945 
 4946 private elem * elbyteint(elem *e, goal_t goal)
 4947 {
 4948     if (OTlogical(e.EV.E1.Eoper) || e.EV.E1.Eoper == OPbtst)
 4949     {
 4950         e.EV.E1.Ety = e.Ety;
 4951         e = el_selecte1(e);
 4952         return e;
 4953     }
 4954     return evalu8(e, goal);
 4955 }
 4956 
 4957 /******************************
 4958  * OPs32_64
 4959  * OPu32_64
 4960  */
 4961 private elem * el32_64(elem *e, goal_t goal)
 4962 {
 4963     if (REGSIZE == 8 && e.EV.E1.Eoper == OPbtst)
 4964     {
 4965         e.EV.E1.Ety = e.Ety;
 4966         e = el_selecte1(e);
 4967         return e;
 4968     }
 4969     return evalu8(e, goal);
 4970 }
 4971 
 4972 /****************************
 4973  * Handle OPu64_d,
 4974  *      OPd_ld OPu64_d,
 4975  *      OPd_f OPu64_d
 4976  */
 4977 
 4978 private elem *elu64_d(elem *e, goal_t goal)
 4979 {
 4980     tym_t ty;
 4981     elem** pu;
 4982     if (e.Eoper == OPu64_d)
 4983     {
 4984         pu = &e.EV.E1;
 4985         ty = TYdouble;
 4986     }
 4987     else if (e.Eoper == OPd_ld && e.EV.E1.Eoper == OPu64_d)
 4988     {
 4989         pu = &e.EV.E1.EV.E1;
 4990         *pu = optelem(*pu, GOALvalue);
 4991         ty = TYldouble;
 4992     }
 4993     else if (e.Eoper == OPd_f && e.EV.E1.Eoper == OPu64_d)
 4994     {
 4995         pu = &e.EV.E1.EV.E1;
 4996         *pu = optelem(*pu, GOALvalue);
 4997         ty = TYfloat;
 4998     }
 4999 
 5000     if (!pu || (*pu).Eoper == OPconst)
 5001         return evalu8(e, goal);
 5002 
 5003     elem* u = *pu;
 5004     if (config.fpxmmregs && I64 && (ty == TYfloat || ty == TYdouble))
 5005     {
 5006         /* Rewrite for SIMD as:
 5007          *    u >= 0 ? OPs64_d(u) : OPs64_d((u >> 1) | (u & 1)) * 2
 5008          */
 5009         u.Ety = TYllong;
 5010         elem *u1 = el_copytree(u);
 5011         if (!OTleaf(u.Eoper))
 5012             fixside(&u, &u1);
 5013         elem *u2 = el_copytree(u1);
 5014 
 5015         u = el_bin(OPge, TYint, u, el_long(TYllong, 0));
 5016 
 5017         u1 = el_una(OPs64_d, TYdouble, u1);
 5018         if (ty == TYfloat)
 5019             u1 = el_una(OPd_f, TYfloat, u1);
 5020 
 5021         elem* u3 = el_copytree(u2);
 5022         u2 = el_bin(OPshr, TYullong, u2, el_long(TYullong, 1));
 5023         u3 = el_bin(OPand, TYullong, u3, el_long(TYullong, 1));
 5024         u2 = el_bin(OPor, TYllong, u2, u3);
 5025 
 5026         u2 = el_una(OPs64_d, TYdouble, u2);
 5027         if (ty == TYfloat)
 5028             u2 = el_una(OPd_f, TYfloat, u2);
 5029 
 5030         u2 = el_bin(OPmul, ty, u2, el_long(ty, 2));
 5031 
 5032         elem* r = el_bin(OPcond, e.Ety, u, el_bin(OPcolon, e.Ety, u1, u2));
 5033         *pu = null;
 5034         el_free(e);
 5035         return optelem(r, GOALvalue);
 5036     }
 5037     if (config.inline8087)
 5038     {
 5039         /* Rewrite for x87 as:
 5040          *  u < 0 ? OPs64_d(u) : OPs64_d(u) + 0x1p+64
 5041          */
 5042         u.Ety = TYllong;
 5043         elem *u1 = el_copytree(u);
 5044         if (!OTleaf(u.Eoper))
 5045             fixside(&u, &u1);
 5046 
 5047         elem* eop1 = el_una(OPs64_d, TYdouble, u1);
 5048         eop1 = el_una(OPd_ld, TYldouble, eop1);
 5049 
 5050         elem* eoff = el_calloc();
 5051         eoff.Eoper = OPconst;
 5052         eoff.Ety = TYldouble;
 5053         eoff.EV.Vldouble = 0x1p+64;
 5054 
 5055         elem* u2 = el_copytree(u1);
 5056         u2 = el_una(OPs64_d, TYdouble, u2);
 5057         u2 = el_una(OPd_ld, TYldouble, u2);
 5058 
 5059         elem* eop2 = el_bin(OPadd, TYldouble, u2, eoff);
 5060 
 5061         elem* r = el_bin(OPcond, TYldouble,
 5062                         el_bin(OPge, OPbool, u, el_long(TYllong, 0)),
 5063                         el_bin(OPcolon, TYldouble, eop1, eop2));
 5064 
 5065         if (ty != TYldouble)
 5066             r = el_una(OPtoprec, e.Ety, r);
 5067 
 5068         *pu = null;
 5069         el_free(e);
 5070 
 5071         return optelem(r, GOALvalue);
 5072     }
 5073 
 5074     return evalu8(e, goal);
 5075 }
 5076 
 5077 
 5078 /************************
 5079  * Handle <<, OProl and OPror
 5080  */
 5081 
 5082 private elem *elshl(elem *e, goal_t goal)
 5083 {
 5084     tym_t ty = e.Ety;
 5085     elem *e1 = e.EV.E1;
 5086     elem *e2 = e.EV.E2;
 5087 
 5088     if (e1.Eoper == OPconst && !boolres(e1))             // if e1 is 0
 5089     {
 5090         e1.Ety = ty;
 5091         e = el_selecte1(e);             // (0 << e2) => 0
 5092     }
 5093     else if (OPTIMIZER &&
 5094         e2.Eoper == OPconst &&
 5095         (e1.Eoper == OPshr || e1.Eoper == OPashr) &&
 5096         e1.EV.E2.Eoper == OPconst &&
 5097         el_tolong(e2) == el_tolong(e1.EV.E2))
 5098     {   /* Rewrite:
 5099          *  (x >> c) << c)
 5100          * with:
 5101          *  x & ~((1 << c) - 1);
 5102          */
 5103         targ_ullong c = el_tolong(e.EV.E2);
 5104         e = el_selecte1(e);
 5105         e = el_selecte1(e);
 5106         e = el_bin(OPand, e.Ety, e, el_long(e.Ety, ~((1UL << c) - 1)));
 5107         return optelem(e, goal);
 5108     }
 5109     return e;
 5110 }
 5111 
 5112 /************************
 5113  * Handle >>
 5114  * OPshr, OPashr
 5115  */
 5116 
 5117 private elem * elshr(elem *e, goal_t goal)
 5118 {
 5119     tym_t ty = e.Ety;
 5120     elem *e1 = e.EV.E1;
 5121     elem *e2 = e.EV.E2;
 5122 
 5123     // (x >> 16) replaced with ((shtlng) x+2)
 5124     if (OPTIMIZER &&
 5125         e2.Eoper == OPconst && e2.EV.Vshort == SHORTSIZE * 8 &&
 5126         tysize(ty) == LONGSIZE)
 5127     {
 5128         if (e1.Eoper == OPvar)
 5129         {
 5130             Symbol *s = e1.EV.Vsym;
 5131 
 5132             if (s.Sclass != SCfastpar && s.Sclass != SCshadowreg)
 5133             {
 5134                 e1.EV.Voffset += SHORTSIZE; // address high word in long
 5135                 if (I32)
 5136                     // Cannot independently address high word of register
 5137                     s.Sflags &= ~GTregcand;
 5138                 goto L1;
 5139             }
 5140         }
 5141         else if (e1.Eoper == OPind)
 5142         {
 5143             /* Replace (*p >> 16) with (shtlng)(*(&*p + 2))     */
 5144             e.EV.E1 = el_una(OPind,TYshort,
 5145                         el_bin(OPadd,e1.EV.E1.Ety,
 5146                                 el_una(OPaddr,e1.EV.E1.Ety,e1),
 5147                                 el_long(TYint,SHORTSIZE)));
 5148         L1:
 5149             e.Eoper = tyuns(e1.Ety) ? OPu16_32 : OPs16_32;
 5150             el_free(e2);
 5151             e.EV.E2 = null;
 5152             e1.Ety = TYshort;
 5153             e = optelem(e,GOALvalue);
 5154         }
 5155     }
 5156 
 5157     // (x >> 32) replaced with ((lngllng) x+4)
 5158     if (e2.Eoper == OPconst && e2.EV.Vlong == LONGSIZE * 8 &&
 5159         tysize(ty) == LLONGSIZE)
 5160     {
 5161         if (e1.Eoper == OPvar)
 5162         {
 5163             e1.EV.Voffset += LONGSIZE;      // address high dword in longlong
 5164             if (I64)
 5165                 // Cannot independently address high word of register
 5166                 e1.EV.Vsym.Sflags &= ~GTregcand;
 5167             goto L2;
 5168         }
 5169         else if (e1.Eoper == OPind)
 5170         {
 5171             // Replace (*p >> 32) with (lngllng)(*(&*p + 4))
 5172             e.EV.E1 = el_una(OPind,TYlong,
 5173                         el_bin(OPadd,e1.EV.E1.Ety,
 5174                                 el_una(OPaddr,e1.EV.E1.Ety,e1),
 5175                                 el_long(TYint,LONGSIZE)));
 5176         L2:
 5177             e.Eoper = tyuns(e1.Ety) ? OPu32_64 : OPs32_64;
 5178             el_free(e2);
 5179             e.EV.E2 = null;
 5180             e1.Ety = TYlong;
 5181             e = optelem(e,GOALvalue);
 5182         }
 5183     }
 5184     return e;
 5185 }
 5186 
 5187 /***********************************
 5188  * Handle OPmsw.
 5189  */
 5190 
 5191 elem *elmsw(elem *e, goal_t goal)
 5192 {
 5193     tym_t ty = e.Ety;
 5194     elem *e1 = e.EV.E1;
 5195 
 5196     if (OPTIMIZER &&
 5197         tysize(e1.Ety) == LLONGSIZE &&
 5198         tysize(ty) == LONGSIZE)
 5199     {
 5200         // Replace (int)(msw (long)x) with (int)*(&x+4)
 5201         if (e1.Eoper == OPvar)
 5202         {
 5203             e1.EV.Voffset += LONGSIZE;      // address high dword in longlong
 5204             if (I64)
 5205                 // Cannot independently address high word of register
 5206                 e1.EV.Vsym.Sflags &= ~GTregcand;
 5207             e1.Ety = ty;
 5208             e = optelem(e1,GOALvalue);
 5209         }
 5210         // Replace (int)(msw (long)*x) with (int)*(&*x+4)
 5211         else if (e1.Eoper == OPind)
 5212         {
 5213             e1 = el_una(OPind,ty,
 5214                 el_bin