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