1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (C) 1986-1998 by Symantec 6 * Copyright (C) 2000-2021 by The D Language Foundation, All Rights Reserved 7 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 8 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/gdag.d, backend/gdag.d) 10 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/backend/gdag.d 11 */ 12 13 module dmd.backend.gdag; 14 15 version (SCPP) 16 version = COMPILE; 17 version (MARS) 18 version = COMPILE; 19 20 version (COMPILE) 21 { 22 23 import core.stdc.stdio; 24 import core.stdc.time; 25 26 import dmd.backend.cc; 27 import dmd.backend.cdef; 28 import dmd.backend.code_x86; 29 import dmd.backend.oper; 30 import dmd.backend.global; 31 import dmd.backend.goh; 32 import dmd.backend.el; 33 import dmd.backend.ty; 34 import dmd.backend.type; 35 36 import dmd.backend.dlist; 37 import dmd.backend.dvec; 38 39 extern (C++): 40 41 nothrow: 42 43 enum Aetype { cse, arraybounds } 44 45 private __gshared Aetype aetype; 46 47 bool Eunambig(elem* e) { return OTassign(e.Eoper) && e.EV.E1.Eoper == OPvar; } 48 49 /************************************* 50 * Determine if floating point should be cse'd. 51 * Returns: 52 * true if should be cse'd 53 */ 54 55 private bool cse_float(elem *e) 56 { 57 // Don't CSE floating stuff if generating 58 // inline 8087 code, the code generator 59 // can't handle it yet 60 return !(tyfloating(e.Ety) && config.inline8087 && 61 e.Eoper != OPvar && e.Eoper != OPconst) || 62 (tyxmmreg(e.Ety) && config.fpxmmregs); 63 } 64 65 /************************************ 66 * Build DAGs (basically find all the common subexpressions). 67 * Must be done after all other optimizations, because most 68 * of them depend on the trees being trees, not DAGs. 69 * The general strategy is: 70 * Compute available expressions (AEs) 71 * For each block 72 * stick together nodes that match, keeping AEs up to date 73 * For each block 74 * unstick unprofitable common subexpressions 75 * (this is generally target-dependent) 76 */ 77 78 void builddags() 79 { 80 vec_t aevec; 81 82 debug if (debugc) printf("builddags()\n"); 83 assert(dfo); 84 flowae(); /* compute available expressions */ 85 if (go.exptop <= 1) /* if no AEs */ 86 return; 87 aetype = Aetype.cse; 88 89 debug 90 foreach (i, e; go.expnod[]) 91 { 92 //printf("go.expnod[%d] = %p\n",i,e); 93 if (e) 94 elem_debug(e); 95 } 96 97 static if (0) 98 { 99 printf("defkill "); vec_println(go.defkill,go.exptop); 100 printf("starkill "); vec_println(go.starkill,go.exptop); 101 printf("vptrkill "); vec_println(go.vptrkill,go.exptop); 102 } 103 104 static if (0) 105 { 106 /* This is the 'correct' algorithm for CSEs. We can't use it */ 107 /* till we fix the code generator. */ 108 foreach (i, b; dfo[]) 109 { 110 if (b.Belem) 111 { 112 static if (0) 113 { 114 printf("dfo[%d] = %p\n",i,b); 115 printf("b.Bin "); vec_println(b.Bin,go.exptop); 116 printf("b.Bout "); vec_println(b.Bout,go.exptop); 117 aewalk(&(b.Belem),b.Bin); 118 printf("b.Bin "); vec_println(b.Bin,go.exptop); 119 printf("b.Bout "); vec_println(b.Bout,go.exptop); 120 } 121 else 122 { 123 aewalk(&(b.Belem),b.Bin); 124 } 125 /* Bin and Bout would be equal at this point */ 126 /* except that we deleted some elems from */ 127 /* go.expnod[] and so it's a subset of Bout */ 128 /* assert(veceq(b.Bin,b.Bout)); */ 129 } 130 } 131 } 132 else 133 { 134 /* Do CSEs across extended basic blocks only. This is because */ 135 /* the code generator can only track register contents */ 136 /* properly across extended basic blocks. */ 137 aevec = vec_calloc(go.exptop); 138 foreach (i, b; dfo[]) 139 { 140 /* if not first block and (there are more than one */ 141 /* predecessor or the only predecessor is not the */ 142 /* previous block), then zero out the available */ 143 /* expressions. */ 144 if ((i != 0 && 145 (list_block(b.Bpred) != dfo[i - 1] || 146 list_next(b.Bpred) != null)) 147 || b.BC == BCasm 148 || b.BC == BC_finally 149 || b.BC == BC_lpad 150 || b.BC == BCcatch 151 || b.BC == BCjcatch 152 ) 153 vec_clear(aevec); 154 if (b.Belem) /* if there is an expression */ 155 aewalk(&(b.Belem),aevec); 156 } 157 vec_free(aevec); 158 } 159 160 // Need 2 passes to converge on solution 161 foreach (j; 0 .. 2) 162 foreach (b; dfo[]) 163 { 164 if (b.Belem) 165 { 166 //printf("b = 0x%x\n",b); 167 removecses(&(b.Belem)); 168 } 169 } 170 } 171 172 173 /**************************** 174 * Walk tree, rewriting *pn into a DAG as we go. 175 * Params: 176 * pn = pointer to expression tree to convert to DAG 177 * ae = vector of available expressions 178 */ 179 180 private void aewalk(elem **pn,vec_t ae) 181 { 182 elem* n = *pn; 183 assert(n && ae); 184 //printf("visiting %d: (",n.Eexp); WReqn(*pn); printf(")\n"); 185 //chkvecdim(go.exptop); 186 const op = n.Eoper; 187 if (n.Eexp) // if an AE 188 { // Try to find an equivalent AE, and point to it instead 189 assert(go.expnod[n.Eexp] == n); 190 if (aetype == Aetype.cse) 191 { 192 for (uint i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) 193 { elem *e = go.expnod[i]; 194 195 // Attempt to replace n with e 196 if (e == null) // if elem no longer exists 197 vec_clearbit(i,ae); // it's not available 198 else if (n != e && 199 el_match(n,e) && 200 e.Ecount < 0xFF-1 && // must fit in unsigned char 201 cse_float(n) 202 ) 203 { 204 *pn = e; // replace n with e 205 //printf("cse: %p (",n); WReqn(*pn); printf(")\n"); 206 e.Ecount++; 207 debug assert(e.Ecount != 0); 208 209 void aeclear(elem *n) 210 { 211 while (1) 212 { 213 const i = n.Eexp; 214 assert(i); 215 if (n.Ecount) 216 break; 217 218 go.expnod[i] = null; 219 vec_clearbit(i,ae); 220 if (OTunary(n.Eoper)) 221 { 222 n = n.EV.E1; 223 continue; 224 } 225 else if (OTbinary(n.Eoper)) 226 { 227 aeclear(n.EV.E1); 228 n = n.EV.E2; 229 continue; 230 } 231 break; 232 } 233 } 234 235 aeclear(n); 236 el_free(n); 237 return; 238 } 239 } 240 } 241 } 242 243 elem *t; 244 switch (op) 245 { 246 case OPcolon: 247 case OPcolon2: 248 { 249 // ae = ae & ael & aer 250 // AEs gened by ael and aer are mutually exclusive 251 vec_t aer = vec_clone(ae); 252 aewalk(&(n.EV.E1),ae); 253 aewalk(&(n.EV.E2),aer); 254 vec_andass(ae,aer); 255 vec_free(aer); 256 break; 257 } 258 259 case OPandand: 260 case OPoror: 261 { 262 aewalk(&(n.EV.E1),ae); 263 /* ae &= aer */ 264 vec_t aer = vec_clone(ae); 265 aewalk(&(n.EV.E2),aer); 266 if (el_returns(n.EV.E2)) 267 vec_andass(ae,aer); 268 vec_free(aer); 269 break; 270 } 271 272 case OPnegass: 273 t = n.EV.E1; 274 if (t.Eoper == OPind) 275 aewalk(&(t.EV.E1),ae); 276 break; 277 278 case OPctor: 279 case OPdtor: 280 case OPdctor: 281 break; 282 283 case OPasm: 284 case OPddtor: 285 vec_clear(ae); // kill everything 286 return; 287 288 default: 289 if (OTbinary(op)) 290 { 291 if (ERTOL(n)) 292 { 293 // Don't CSE constants that will turn into 294 // an INC or DEC anyway 295 if (n.EV.E2.Eoper == OPconst && 296 n.EV.E2.EV.Vint == 1 && 297 (op == OPaddass || op == OPminass || 298 op == OPpostinc || op == OPpostdec) 299 ) 300 { } 301 else 302 aewalk(&(n.EV.E2),ae); 303 } 304 if (OTassign(op)) 305 { 306 t = n.EV.E1; 307 if (t.Eoper == OPind) 308 aewalk(&(t.EV.E1),ae); 309 } 310 else 311 aewalk(&(n.EV.E1),ae); 312 if (!ERTOL(n)) 313 aewalk(&(n.EV.E2),ae); 314 } 315 else if (OTunary(op)) 316 { 317 assert(op != OPnegass); 318 aewalk(&(n.EV.E1),ae); 319 } 320 } 321 322 if (OTdef(op)) 323 { 324 assert(n.Eexp == 0); // should not be an AE 325 /* remove all AEs that could be affected by this def */ 326 if (Eunambig(n)) // if unambiguous definition 327 { 328 assert(t.Eoper == OPvar); 329 Symbol* s = t.EV.Vsym; 330 if (!(s.Sflags & SFLunambig)) 331 vec_subass(ae,go.starkill); 332 for (uint i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) // for each ae elem 333 { 334 elem *e = go.expnod[i]; 335 336 if (!e) continue; 337 if (OTunary(e.Eoper)) 338 { 339 if (vec_testbit(e.EV.E1.Eexp,ae)) 340 continue; 341 } 342 else if (OTbinary(e.Eoper)) 343 { 344 if (vec_testbit(e.EV.E1.Eexp,ae) && 345 vec_testbit(e.EV.E2.Eexp,ae)) 346 continue; 347 } 348 else if (e.Eoper == OPvar) 349 { 350 if (e.EV.Vsym != s) 351 continue; 352 } 353 else 354 continue; 355 vec_clearbit(i,ae); 356 } 357 } 358 else /* else ambiguous definition */ 359 { 360 vec_subass(ae,go.defkill); 361 if (OTcalldef(op)) 362 vec_subass(ae,go.vptrkill); 363 } 364 365 // GEN the lvalue of an assignment operator 366 if (OTassign(op) && !OTpost(op) && t.Eexp) 367 vec_setbit(t.Eexp,ae); 368 } 369 if (n.Eexp) // if an AE 370 { 371 if (op == OPvp_fp || op == OPcvp_fp) 372 /* Invalidate all other OPvp_fps */ 373 vec_subass(ae,go.vptrkill); 374 375 /*printf("available: ("); WReqn(n); printf(")\n"); 376 elem_print(n);*/ 377 vec_setbit(n.Eexp,ae); /* mark this elem as available */ 378 } 379 } 380 381 382 /************************** 383 * Remove a CSE. 384 * Input: 385 * pe pointer to pointer to CSE 386 * Output: 387 * *pe new elem to replace the old 388 * Returns: 389 * *pe 390 */ 391 private elem * delcse(elem **pe) 392 { 393 elem *e; 394 395 e = el_calloc(); 396 el_copy(e,*pe); 397 398 debug if (debugc) 399 { 400 printf("deleting unprofitable CSE %p (", *pe); 401 WReqn(e); 402 printf(")\n"); 403 } 404 405 assert(e.Ecount != 0); 406 if (!OTleaf(e.Eoper)) 407 { 408 if (e.EV.E1.Ecount == 0xFF-1) 409 { 410 elem *ereplace; 411 ereplace = el_calloc(); 412 el_copy(ereplace,e.EV.E1); 413 e.EV.E1 = ereplace; 414 ereplace.Ecount = 0; 415 } 416 else 417 { 418 e.EV.E1.Ecount++; 419 debug assert(e.EV.E1.Ecount != 0); 420 } 421 if (OTbinary(e.Eoper)) 422 { 423 if (e.EV.E2.Ecount == 0xFF-1) 424 { 425 elem *ereplace; 426 ereplace = el_calloc(); 427 el_copy(ereplace,e.EV.E2); 428 e.EV.E2 = ereplace; 429 ereplace.Ecount = 0; 430 } 431 else 432 { 433 e.EV.E2.Ecount++; 434 debug assert(e.EV.E2.Ecount != 0); 435 } 436 } 437 } 438 --(*pe).Ecount; 439 debug assert((*pe).Ecount != 0xFF); 440 (*pe).Nflags |= NFLdelcse; // not generating node 441 e.Ecount = 0; 442 *pe = e; 443 return *pe; 444 } 445 446 447 /****************************** 448 * 'Unstick' CSEs that would be unprofitable to do. These are usually 449 * things like addressing modes, and are usually target-dependent. 450 */ 451 452 private void removecses(elem **pe) 453 { 454 L1: 455 elem* e = *pe; 456 //printf(" removecses(%p) ", e); WReqn(e); printf("\n"); 457 assert(e); 458 elem_debug(e); 459 if (e.Nflags & NFLdelcse && e.Ecount) 460 { 461 delcse(pe); 462 goto L1; 463 } 464 const op = e.Eoper; 465 if (OTunary(op)) 466 { 467 if (op == OPind) 468 { 469 bool scaledIndex = I32 || I64; // if scaled index addressing mode support 470 elem *e1 = e.EV.E1; 471 if (e1.Eoper == OPadd && 472 e1.Ecount 473 ) 474 { 475 if (scaledIndex) 476 { 477 e1 = delcse(&e.EV.E1); 478 if (e1.EV.E1.Ecount) // == 1) 479 delcse(&e1.EV.E1); 480 if (e1.EV.E2.Ecount && e1.EV.E2.Eoper != OPind) 481 delcse(&e1.EV.E2); 482 } 483 /* *(v +. c) 484 * *(*pc +. c) 485 * The + and the const shouldn't be CSEs. 486 */ 487 else if (e1.EV.E2.Eoper == OPconst && 488 (e1.EV.E1.Eoper == OPvar || (e1.EV.E1.Eoper == OPind && e1.EV.E1.Ety & (mTYconst | mTYimmutable))) 489 ) 490 { 491 e1 = delcse(&e.EV.E1); 492 } 493 } 494 495 /* *(((e <<. 3) + e) + e) 496 */ 497 if (scaledIndex && e1.Eoper == OPadd && 498 e1.EV.E1.Eoper == OPadd && 499 e1.EV.E1.EV.E1.Ecount && 500 e1.EV.E1.EV.E1.Eoper == OPshl && 501 e1.EV.E1.EV.E1.EV.E2.Eoper == OPconst && 502 e1.EV.E1.EV.E1.EV.E2.EV.Vuns <= 3 503 ) 504 { 505 delcse(&e1.EV.E1.EV.E1); // the <<. operator 506 } 507 508 /* *(((e << 3) +. e) + e) 509 */ 510 if (scaledIndex && e1.Eoper == OPadd && 511 e1.EV.E1.Eoper == OPadd && 512 e1.EV.E1.Ecount && 513 e1.EV.E1.EV.E1.Eoper == OPshl && 514 e1.EV.E1.EV.E1.EV.E2.Eoper == OPconst && 515 e1.EV.E1.EV.E1.EV.E2.EV.Vuns <= 3 516 ) 517 { 518 delcse(&e1.EV.E1); // the +. operator 519 } 520 521 /* *((e <<. 3) + e) 522 */ 523 else if (scaledIndex && e1.Eoper == OPadd && 524 e1.EV.E1.Ecount && 525 e1.EV.E1.Eoper == OPshl && 526 e1.EV.E1.EV.E2.Eoper == OPconst && 527 e1.EV.E1.EV.E2.EV.Vuns <= 3 528 ) 529 { 530 delcse(&e1.EV.E1); // the <<. operator 531 } 532 533 // Remove *e1 where it's a double 534 if (e.Ecount && tyfloating(e.Ety)) 535 e = delcse(pe); 536 } 537 // This CSE is too easy to regenerate 538 else if (op == OPu16_32 && I16 && e.Ecount) 539 e = delcse(pe); 540 541 else if (op == OPd_ld && e.EV.E1.Ecount > 0) 542 delcse(&e.EV.E1); 543 544 // OPremquo is only worthwhile if its result is used more than once 545 else if (e.EV.E1.Eoper == OPremquo && 546 (op == OP64_32 || op == OP128_64 || op == OPmsw) && 547 e.EV.E1.Ecount == 0) 548 { // Convert back to OPdiv or OPmod 549 elem *e1 = e.EV.E1; 550 e.Eoper = (op == OPmsw) ? OPmod : OPdiv; 551 e.EV.E1 = e1.EV.E1; 552 e.EV.E2 = e1.EV.E2; 553 e1.EV.E1 = null; 554 e1.EV.E2 = null; 555 el_free(e1); 556 557 removecses(&(e.EV.E1)); 558 pe = &(e.EV.E2); 559 goto L1; 560 } 561 } 562 else if (OTbinary(op)) 563 { 564 if (e.Ecount > 0 && OTrel(op) && e.Ecount < 4 565 /* Don't CSE floating stuff if generating */ 566 /* inline 8087 code, the code generator */ 567 /* can't handle it yet */ 568 && !(tyfloating(e.EV.E1.Ety) && config.inline8087) 569 ) 570 e = delcse(pe); 571 if (ERTOL(e)) 572 { 573 removecses(&(e.EV.E2)); 574 pe = &(e.EV.E1); 575 } 576 else 577 { 578 removecses(&(e.EV.E1)); 579 pe = &(e.EV.E2); 580 } 581 goto L1; 582 } 583 else /* leaf node */ 584 { 585 return; 586 } 587 pe = &(e.EV.E1); 588 goto L1; 589 } 590 591 /***************************************** 592 * Do optimizations based on if we know an expression is 593 * 0 or !=0, even though we don't know anything else. 594 */ 595 596 void boolopt() 597 { 598 vec_t aevec; 599 vec_t aevecval; 600 601 debug if (debugc) printf("boolopt()\n"); 602 if (!dfo.length) 603 compdfo(); 604 flowae(); /* compute available expressions */ 605 if (go.exptop <= 1) /* if no AEs */ 606 return; 607 static if (0) 608 { 609 for (uint i = 0; i < go.exptop; i++) 610 printf("go.expnod[%d] = 0x%x\n",i,go.expnod[i]); 611 printf("defkill "); vec_println(go.defkill,go.exptop); 612 printf("starkill "); vec_println(go.starkill,go.exptop); 613 printf("vptrkill "); vec_println(go.vptrkill,go.exptop); 614 } 615 616 /* Do CSEs across extended basic blocks only. This is because */ 617 /* the code generator can only track register contents */ 618 /* properly across extended basic blocks. */ 619 aevec = vec_calloc(go.exptop); 620 aevecval = vec_calloc(go.exptop); 621 622 // Mark each expression that we know starts off with a non-zero value 623 for (uint i = 0; i < go.exptop; i++) 624 { 625 elem *e = go.expnod[i]; 626 if (e) 627 { 628 elem_debug(e); 629 if (e.Eoper == OPvar && e.EV.Vsym.Sflags & SFLtrue) 630 { 631 vec_setbit(i,aevec); 632 vec_setbit(i,aevecval); 633 } 634 } 635 } 636 637 foreach (i, b; dfo[]) 638 { 639 /* if not first block and (there are more than one */ 640 /* predecessor or the only predecessor is not the */ 641 /* previous block), then zero out the available */ 642 /* expressions. */ 643 if ((i != 0 && 644 (list_block(b.Bpred) != dfo[i - 1] || 645 list_next(b.Bpred) != null)) 646 || b.BC == BCasm 647 || b.BC == BC_finally 648 || b.BC == BC_lpad 649 || b.BC == BCcatch 650 || b.BC == BCjcatch 651 ) 652 vec_clear(aevec); 653 if (b.Belem) /* if there is an expression */ 654 abewalk(b.Belem,aevec,aevecval); 655 } 656 vec_free(aevec); 657 vec_free(aevecval); 658 } 659 660 /**************************** 661 * Walk tree, replacing bool expressions that we know 662 * ae = vector of available boolean expressions 663 * aeval = parallel vector of values corresponding to whether bool 664 * value is 1 or 0 665 * n = elem tree to look at 666 */ 667 668 private void abewalk(elem *n,vec_t ae,vec_t aeval) 669 { 670 elem *t; 671 672 assert(n && ae); 673 elem_debug(n); 674 /*printf("visiting: ("); WReqn(*pn); printf("), Eexp = %d\n",n.Eexp);*/ 675 /*chkvecdim(go.exptop);*/ 676 const op = n.Eoper; 677 switch (op) 678 { 679 case OPcond: 680 { 681 assert(n.EV.E2.Eoper == OPcolon || n.EV.E2.Eoper == OPcolon2); 682 abewalk(n.EV.E1,ae,aeval); 683 abeboolres(n.EV.E1,ae,aeval); 684 vec_t aer = vec_clone(ae); 685 vec_t aerval = vec_clone(aeval); 686 if (!el_returns(n.EV.E2.EV.E1)) 687 { 688 abeset(n.EV.E1,aer,aerval,true); 689 abewalk(n.EV.E2.EV.E1,aer,aerval); 690 abeset(n.EV.E1,ae,aeval,false); 691 abewalk(n.EV.E2.EV.E2,ae,aeval); 692 } 693 else if (!el_returns(n.EV.E2.EV.E2)) 694 { 695 abeset(n.EV.E1,ae,aeval,true); 696 abewalk(n.EV.E2.EV.E1,ae,aeval); 697 abeset(n.EV.E1,aer,aerval,false); 698 abewalk(n.EV.E2.EV.E2,aer,aerval); 699 } 700 else 701 { 702 /* ae = ae & ael & aer 703 * AEs gened by ael and aer are mutually exclusive 704 */ 705 abeset(n.EV.E1,aer,aerval,true); 706 abewalk(n.EV.E2.EV.E1,aer,aerval); 707 abeset(n.EV.E1,ae,aeval,false); 708 abewalk(n.EV.E2.EV.E2,ae,aeval); 709 710 vec_xorass(aerval,aeval); 711 vec_subass(aer,aerval); 712 vec_andass(ae,aer); 713 } 714 vec_free(aer); 715 vec_free(aerval); 716 break; 717 } 718 719 case OPcolon: 720 case OPcolon2: 721 assert(0); 722 723 case OPandand: 724 case OPoror: 725 { 726 //printf("test1 %p: ", n); WReqn(n); printf("\n"); 727 abewalk(n.EV.E1,ae,aeval); 728 abeboolres(n.EV.E1,ae,aeval); 729 vec_t aer = vec_clone(ae); 730 vec_t aerval = vec_clone(aeval); 731 if (!el_returns(n.EV.E2)) 732 { 733 abeset(n.EV.E1,aer,aerval,(op == OPandand)); 734 abewalk(n.EV.E2,aer,aerval); 735 abeset(n.EV.E1,ae,aeval,(op != OPandand)); 736 } 737 else 738 { 739 /* ae &= aer 740 */ 741 abeset(n.EV.E1,aer,aerval,(op == OPandand)); 742 abewalk(n.EV.E2,aer,aerval); 743 744 vec_xorass(aerval,aeval); 745 vec_subass(aer,aerval); 746 vec_andass(ae,aer); 747 } 748 749 vec_free(aer); 750 vec_free(aerval); 751 break; 752 } 753 754 case OPbool: 755 case OPnot: 756 abewalk(n.EV.E1,ae,aeval); 757 abeboolres(n.EV.E1,ae,aeval); 758 break; 759 760 case OPeqeq: 761 case OPne: 762 case OPlt: 763 case OPle: 764 case OPgt: 765 case OPge: 766 case OPunord: case OPlg: case OPleg: case OPule: 767 case OPul: case OPuge: case OPug: case OPue: 768 case OPngt: case OPnge: case OPnlt: case OPnle: 769 case OPord: case OPnlg: case OPnleg: case OPnule: 770 case OPnul: case OPnuge: case OPnug: case OPnue: 771 abewalk(n.EV.E1,ae,aeval); 772 abewalk(n.EV.E2,ae,aeval); 773 abeboolres(n,ae,aeval); 774 break; 775 776 case OPnegass: 777 t = n.EV.E1; 778 if (t.Eoper == OPind) 779 abewalk(t.EV.E1,ae,aeval); 780 break; 781 782 case OPasm: 783 vec_clear(ae); // kill everything 784 return; 785 786 default: 787 if (OTbinary(op)) 788 { if (ERTOL(n)) 789 abewalk(n.EV.E2,ae,aeval); 790 if (OTassign(op)) 791 { t = n.EV.E1; 792 if (t.Eoper == OPind) 793 abewalk(t.EV.E1,ae,aeval); 794 } 795 else 796 abewalk(n.EV.E1,ae,aeval); 797 if (!ERTOL(n)) 798 abewalk(n.EV.E2,ae,aeval); 799 } 800 else if (OTunary(op)) 801 abewalk(n.EV.E1,ae,aeval); 802 break; 803 } 804 805 if (OTdef(op)) 806 { 807 assert(n.Eexp == 0); // should not be an AE 808 /* remove all AEs that could be affected by this def */ 809 if (Eunambig(n)) /* if unambiguous definition */ 810 { 811 Symbol *s; 812 813 assert(t.Eoper == OPvar); 814 s = t.EV.Vsym; 815 if (!(s.Sflags & SFLunambig)) 816 vec_subass(ae,go.starkill); 817 for (uint i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) // for each ae elem 818 { 819 elem *e = go.expnod[i]; 820 821 if (!e) continue; 822 if (el_appears(e,s)) 823 vec_clearbit(i,ae); 824 } 825 } 826 else /* else ambiguous definition */ 827 { 828 vec_subass(ae,go.defkill); 829 if (OTcalldef(op)) 830 vec_subass(ae,go.vptrkill); 831 } 832 /* GEN the lvalue of an assignment operator */ 833 uint i1, i2; 834 if (op == OPeq && (i1 = t.Eexp) != 0 && (i2 = n.EV.E2.Eexp) != 0) 835 { 836 if (vec_testbit(i2,ae)) 837 { 838 vec_setbit(i1,ae); 839 if (vec_testbit(i2,aeval)) 840 vec_setbit(i1,aeval); 841 else 842 vec_clearbit(i1,aeval); 843 } 844 } 845 } 846 else if (n.Eexp) /* if an AE */ 847 { 848 if (op == OPvp_fp || op == OPcvp_fp) 849 /* Invalidate all other OPvp_fps */ 850 vec_subass(ae,go.vptrkill); 851 852 /*printf("available: ("); WReqn(n); printf(")\n"); 853 elem_print(n);*/ 854 // vec_setbit(n.Eexp,ae); /* mark this elem as available */ 855 } 856 } 857 858 /************************************ 859 * Elem e is to be evaluated for a boolean result. 860 * See if we already know its value. 861 */ 862 863 private void abeboolres(elem *n,vec_t ae,vec_t aeval) 864 { 865 //printf("abeboolres()[%d %p] ", n.Eexp, go.expnod[n.Eexp]); WReqn(n); printf("\n"); 866 elem_debug(n); 867 if (n.Eexp && go.expnod[n.Eexp]) 868 { /* Try to find an equivalent AE, and point to it instead */ 869 assert(go.expnod[n.Eexp] == n); 870 uint i; 871 for (i = 0; (i = cast(uint) vec_index(i, ae)) < go.exptop; ++i) // for each ae elem 872 { elem *e = go.expnod[i]; 873 874 // Attempt to replace n with the boolean result of e 875 //printf("Looking at go.expnod[%d] = %p\n",i,e); 876 assert(e); 877 elem_debug(e); 878 if (n != e && el_match(n,e)) 879 { 880 debug if (debugc) 881 { printf("Elem %p: ",n); 882 WReqn(n); 883 printf(" is replaced by %d\n",vec_testbit(i,aeval) != 0); 884 } 885 886 abefree(n,ae); 887 n.EV.Vlong = vec_testbit(i,aeval) != 0; 888 n.Eoper = OPconst; 889 n.Ety = TYint; 890 go.changes++; 891 break; 892 } 893 } 894 } 895 } 896 897 /**************************** 898 * Remove e from available expressions, and its children. 899 */ 900 901 private void abefree(elem *e,vec_t ae) 902 { 903 //printf("abefree [%d %p]: ", e.Eexp, e); WReqn(e); printf("\n"); 904 assert(e.Eexp); 905 vec_clearbit(e.Eexp,ae); 906 go.expnod[e.Eexp] = null; 907 if (!OTleaf(e.Eoper)) 908 { 909 if (OTbinary(e.Eoper)) 910 { 911 abefree(e.EV.E2,ae); 912 el_free(e.EV.E2); 913 e.EV.E2 = null; 914 } 915 abefree(e.EV.E1,ae); 916 el_free(e.EV.E1); 917 e.EV.E1 = null; 918 } 919 } 920 921 /************************************ 922 * Elem e is to be evaluated for a boolean result. 923 * Set its result according to flag. 924 */ 925 926 private void abeset(elem *e,vec_t ae,vec_t aeval,int flag) 927 { 928 while (1) 929 { 930 uint i = e.Eexp; 931 if (i && go.expnod[i]) 932 { 933 //printf("abeset for go.expnod[%d] = %p: ",i,e); WReqn(e); printf("\n"); 934 vec_setbit(i,ae); 935 if (flag) 936 vec_setbit(i,aeval); 937 else 938 vec_clearbit(i,aeval); 939 } 940 switch (e.Eoper) 941 { case OPnot: 942 flag ^= 1; 943 e = e.EV.E1; 944 continue; 945 946 case OPbool: 947 case OPeq: 948 e = e.EV.E1; 949 continue; 950 951 default: 952 break; 953 } 954 break; 955 } 956 } 957 958 }