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