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