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