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