github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/8g/peep.c (about) 1 // Derived from Inferno utils/6c/peep.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 #include <u.h> 32 #include <libc.h> 33 #include "gg.h" 34 #include "opt.h" 35 36 #define REGEXT 0 37 38 static void conprop(Reg *r); 39 static void elimshortmov(Reg *r); 40 41 // do we need the carry bit 42 static int 43 needc(Prog *p) 44 { 45 while(p != P) { 46 switch(p->as) { 47 case AADCL: 48 case ASBBL: 49 case ARCRB: 50 case ARCRW: 51 case ARCRL: 52 return 1; 53 case AADDB: 54 case AADDW: 55 case AADDL: 56 case ASUBB: 57 case ASUBW: 58 case ASUBL: 59 case AJMP: 60 case ARET: 61 case ACALL: 62 return 0; 63 default: 64 if(p->to.type == D_BRANCH) 65 return 0; 66 } 67 p = p->link; 68 } 69 return 0; 70 } 71 72 static Reg* 73 rnops(Reg *r) 74 { 75 Prog *p; 76 Reg *r1; 77 78 if(r != R) 79 for(;;) { 80 p = r->prog; 81 if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE) 82 break; 83 r1 = uniqs(r); 84 if(r1 == R) 85 break; 86 r = r1; 87 } 88 return r; 89 } 90 91 void 92 peep(void) 93 { 94 Reg *r, *r1, *r2; 95 Prog *p, *p1; 96 int t; 97 98 /* 99 * complete R structure 100 */ 101 t = 0; 102 for(r=firstr; r!=R; r=r1) { 103 r1 = r->link; 104 if(r1 == R) 105 break; 106 p = r->prog->link; 107 while(p != r1->prog) 108 switch(p->as) { 109 default: 110 r2 = rega(); 111 r->link = r2; 112 r2->link = r1; 113 114 r2->prog = p; 115 p->reg = r2; 116 117 r2->p1 = r; 118 r->s1 = r2; 119 r2->s1 = r1; 120 r1->p1 = r2; 121 122 r = r2; 123 t++; 124 125 case ADATA: 126 case AGLOBL: 127 case ANAME: 128 case ASIGNAME: 129 case ALOCALS: 130 case ATYPE: 131 p = p->link; 132 } 133 } 134 135 // byte, word arithmetic elimination. 136 elimshortmov(r); 137 138 // constant propagation 139 // find MOV $con,R followed by 140 // another MOV $con,R without 141 // setting R in the interim 142 for(r=firstr; r!=R; r=r->link) { 143 p = r->prog; 144 switch(p->as) { 145 case ALEAL: 146 if(regtyp(&p->to)) 147 if(p->from.sym != S) 148 conprop(r); 149 break; 150 151 case AMOVB: 152 case AMOVW: 153 case AMOVL: 154 case AMOVSS: 155 case AMOVSD: 156 if(regtyp(&p->to)) 157 if(p->from.type == D_CONST) 158 conprop(r); 159 break; 160 } 161 } 162 163 loop1: 164 if(debug['P'] && debug['v']) 165 dumpit("loop1", firstr); 166 167 t = 0; 168 for(r=firstr; r!=R; r=r->link) { 169 p = r->prog; 170 switch(p->as) { 171 case AMOVL: 172 case AMOVSS: 173 case AMOVSD: 174 if(regtyp(&p->to)) 175 if(regtyp(&p->from)) { 176 if(copyprop(r)) { 177 excise(r); 178 t++; 179 } else 180 if(subprop(r) && copyprop(r)) { 181 excise(r); 182 t++; 183 } 184 } 185 break; 186 187 case AMOVBLZX: 188 case AMOVWLZX: 189 case AMOVBLSX: 190 case AMOVWLSX: 191 if(regtyp(&p->to)) { 192 r1 = rnops(uniqs(r)); 193 if(r1 != R) { 194 p1 = r1->prog; 195 if(p->as == p1->as && p->to.type == p1->from.type){ 196 p1->as = AMOVL; 197 t++; 198 } 199 } 200 } 201 break; 202 203 case AADDL: 204 case AADDW: 205 if(p->from.type != D_CONST || needc(p->link)) 206 break; 207 if(p->from.offset == -1){ 208 if(p->as == AADDL) 209 p->as = ADECL; 210 else 211 p->as = ADECW; 212 p->from = zprog.from; 213 break; 214 } 215 if(p->from.offset == 1){ 216 if(p->as == AADDL) 217 p->as = AINCL; 218 else 219 p->as = AINCW; 220 p->from = zprog.from; 221 break; 222 } 223 break; 224 225 case ASUBL: 226 case ASUBW: 227 if(p->from.type != D_CONST || needc(p->link)) 228 break; 229 if(p->from.offset == -1) { 230 if(p->as == ASUBL) 231 p->as = AINCL; 232 else 233 p->as = AINCW; 234 p->from = zprog.from; 235 break; 236 } 237 if(p->from.offset == 1){ 238 if(p->as == ASUBL) 239 p->as = ADECL; 240 else 241 p->as = ADECW; 242 p->from = zprog.from; 243 break; 244 } 245 break; 246 } 247 } 248 if(t) 249 goto loop1; 250 251 // MOVSD removal. 252 // We never use packed registers, so a MOVSD between registers 253 // can be replaced by MOVAPD, which moves the pair of float64s 254 // instead of just the lower one. We only use the lower one, but 255 // the processor can do better if we do moves using both. 256 for(r=firstr; r!=R; r=r->link) { 257 p = r->prog; 258 if(p->as == AMOVSD) 259 if(regtyp(&p->from)) 260 if(regtyp(&p->to)) 261 p->as = AMOVAPD; 262 } 263 } 264 265 void 266 excise(Reg *r) 267 { 268 Prog *p; 269 270 p = r->prog; 271 if(debug['P'] && debug['v']) 272 print("%P ===delete===\n", p); 273 274 p->as = ANOP; 275 p->from = zprog.from; 276 p->to = zprog.to; 277 278 ostats.ndelmov++; 279 } 280 281 Reg* 282 uniqp(Reg *r) 283 { 284 Reg *r1; 285 286 r1 = r->p1; 287 if(r1 == R) { 288 r1 = r->p2; 289 if(r1 == R || r1->p2link != R) 290 return R; 291 } else 292 if(r->p2 != R) 293 return R; 294 return r1; 295 } 296 297 Reg* 298 uniqs(Reg *r) 299 { 300 Reg *r1; 301 302 r1 = r->s1; 303 if(r1 == R) { 304 r1 = r->s2; 305 if(r1 == R) 306 return R; 307 } else 308 if(r->s2 != R) 309 return R; 310 return r1; 311 } 312 313 int 314 regtyp(Adr *a) 315 { 316 int t; 317 318 t = a->type; 319 if(t >= D_AX && t <= D_DI) 320 return 1; 321 if(t >= D_X0 && t <= D_X7) 322 return 1; 323 return 0; 324 } 325 326 // movb elimination. 327 // movb is simulated by the linker 328 // when a register other than ax, bx, cx, dx 329 // is used, so rewrite to other instructions 330 // when possible. a movb into a register 331 // can smash the entire 64-bit register without 332 // causing any trouble. 333 static void 334 elimshortmov(Reg *r) 335 { 336 Prog *p; 337 338 for(r=firstr; r!=R; r=r->link) { 339 p = r->prog; 340 if(regtyp(&p->to)) { 341 switch(p->as) { 342 case AINCB: 343 case AINCW: 344 p->as = AINCL; 345 break; 346 case ADECB: 347 case ADECW: 348 p->as = ADECL; 349 break; 350 case ANEGB: 351 case ANEGW: 352 p->as = ANEGL; 353 break; 354 case ANOTB: 355 case ANOTW: 356 p->as = ANOTL; 357 break; 358 } 359 if(regtyp(&p->from) || p->from.type == D_CONST) { 360 // move or artihmetic into partial register. 361 // from another register or constant can be movl. 362 // we don't switch to 32-bit arithmetic if it can 363 // change how the carry bit is set (and the carry bit is needed). 364 switch(p->as) { 365 case AMOVB: 366 case AMOVW: 367 p->as = AMOVL; 368 break; 369 case AADDB: 370 case AADDW: 371 if(!needc(p->link)) 372 p->as = AADDL; 373 break; 374 case ASUBB: 375 case ASUBW: 376 if(!needc(p->link)) 377 p->as = ASUBL; 378 break; 379 case AMULB: 380 case AMULW: 381 p->as = AMULL; 382 break; 383 case AIMULB: 384 case AIMULW: 385 p->as = AIMULL; 386 break; 387 case AANDB: 388 case AANDW: 389 p->as = AANDL; 390 break; 391 case AORB: 392 case AORW: 393 p->as = AORL; 394 break; 395 case AXORB: 396 case AXORW: 397 p->as = AXORL; 398 break; 399 case ASHLB: 400 case ASHLW: 401 p->as = ASHLL; 402 break; 403 } 404 } else { 405 // explicit zero extension 406 switch(p->as) { 407 case AMOVB: 408 p->as = AMOVBLZX; 409 break; 410 case AMOVW: 411 p->as = AMOVWLZX; 412 break; 413 } 414 } 415 } 416 } 417 } 418 419 /* 420 * the idea is to substitute 421 * one register for another 422 * from one MOV to another 423 * MOV a, R0 424 * ADD b, R0 / no use of R1 425 * MOV R0, R1 426 * would be converted to 427 * MOV a, R1 428 * ADD b, R1 429 * MOV R1, R0 430 * hopefully, then the former or latter MOV 431 * will be eliminated by copy propagation. 432 */ 433 int 434 subprop(Reg *r0) 435 { 436 Prog *p; 437 Adr *v1, *v2; 438 Reg *r; 439 int t; 440 441 p = r0->prog; 442 v1 = &p->from; 443 if(!regtyp(v1)) 444 return 0; 445 v2 = &p->to; 446 if(!regtyp(v2)) 447 return 0; 448 for(r=uniqp(r0); r!=R; r=uniqp(r)) { 449 if(uniqs(r) == R) 450 break; 451 p = r->prog; 452 switch(p->as) { 453 case ACALL: 454 return 0; 455 456 case AIMULL: 457 case AIMULW: 458 if(p->to.type != D_NONE) 459 break; 460 461 case ARCLB: 462 case ARCLL: 463 case ARCLW: 464 case ARCRB: 465 case ARCRL: 466 case ARCRW: 467 case AROLB: 468 case AROLL: 469 case AROLW: 470 case ARORB: 471 case ARORL: 472 case ARORW: 473 case ASALB: 474 case ASALL: 475 case ASALW: 476 case ASARB: 477 case ASARL: 478 case ASARW: 479 case ASHLB: 480 case ASHLL: 481 case ASHLW: 482 case ASHRB: 483 case ASHRL: 484 case ASHRW: 485 if(p->from.type == D_CONST) 486 break; 487 488 case ADIVB: 489 case ADIVL: 490 case ADIVW: 491 case AIDIVB: 492 case AIDIVL: 493 case AIDIVW: 494 case AIMULB: 495 case AMULB: 496 case AMULL: 497 case AMULW: 498 499 case AREP: 500 case AREPN: 501 502 case ACWD: 503 case ACDQ: 504 505 case ASTOSB: 506 case ASTOSL: 507 case AMOVSB: 508 case AMOVSL: 509 510 case AFMOVF: 511 case AFMOVD: 512 case AFMOVFP: 513 case AFMOVDP: 514 return 0; 515 516 case AMOVL: 517 case AMOVSS: 518 case AMOVSD: 519 if(p->to.type == v1->type) 520 goto gotit; 521 break; 522 } 523 if(copyau(&p->from, v2) || 524 copyau(&p->to, v2)) 525 break; 526 if(copysub(&p->from, v1, v2, 0) || 527 copysub(&p->to, v1, v2, 0)) 528 break; 529 } 530 return 0; 531 532 gotit: 533 copysub(&p->to, v1, v2, 1); 534 if(debug['P']) { 535 print("gotit: %D->%D\n%P", v1, v2, r->prog); 536 if(p->from.type == v2->type) 537 print(" excise"); 538 print("\n"); 539 } 540 for(r=uniqs(r); r!=r0; r=uniqs(r)) { 541 p = r->prog; 542 copysub(&p->from, v1, v2, 1); 543 copysub(&p->to, v1, v2, 1); 544 if(debug['P']) 545 print("%P\n", r->prog); 546 } 547 t = v1->type; 548 v1->type = v2->type; 549 v2->type = t; 550 if(debug['P']) 551 print("%P last\n", r->prog); 552 return 1; 553 } 554 555 /* 556 * The idea is to remove redundant copies. 557 * v1->v2 F=0 558 * (use v2 s/v2/v1/)* 559 * set v1 F=1 560 * use v2 return fail 561 * ----------------- 562 * v1->v2 F=0 563 * (use v2 s/v2/v1/)* 564 * set v1 F=1 565 * set v2 return success 566 */ 567 int 568 copyprop(Reg *r0) 569 { 570 Prog *p; 571 Adr *v1, *v2; 572 Reg *r; 573 574 p = r0->prog; 575 v1 = &p->from; 576 v2 = &p->to; 577 if(copyas(v1, v2)) 578 return 1; 579 for(r=firstr; r!=R; r=r->link) 580 r->active = 0; 581 return copy1(v1, v2, r0->s1, 0); 582 } 583 584 int 585 copy1(Adr *v1, Adr *v2, Reg *r, int f) 586 { 587 int t; 588 Prog *p; 589 590 if(r->active) { 591 if(debug['P']) 592 print("act set; return 1\n"); 593 return 1; 594 } 595 r->active = 1; 596 if(debug['P']) 597 print("copy %D->%D f=%d\n", v1, v2, f); 598 for(; r != R; r = r->s1) { 599 p = r->prog; 600 if(debug['P']) 601 print("%P", p); 602 if(!f && uniqp(r) == R) { 603 f = 1; 604 if(debug['P']) 605 print("; merge; f=%d", f); 606 } 607 t = copyu(p, v2, A); 608 switch(t) { 609 case 2: /* rar, cant split */ 610 if(debug['P']) 611 print("; %D rar; return 0\n", v2); 612 return 0; 613 614 case 3: /* set */ 615 if(debug['P']) 616 print("; %D set; return 1\n", v2); 617 return 1; 618 619 case 1: /* used, substitute */ 620 case 4: /* use and set */ 621 if(f) { 622 if(!debug['P']) 623 return 0; 624 if(t == 4) 625 print("; %D used+set and f=%d; return 0\n", v2, f); 626 else 627 print("; %D used and f=%d; return 0\n", v2, f); 628 return 0; 629 } 630 if(copyu(p, v2, v1)) { 631 if(debug['P']) 632 print("; sub fail; return 0\n"); 633 return 0; 634 } 635 if(debug['P']) 636 print("; sub %D/%D", v2, v1); 637 if(t == 4) { 638 if(debug['P']) 639 print("; %D used+set; return 1\n", v2); 640 return 1; 641 } 642 break; 643 } 644 if(!f) { 645 t = copyu(p, v1, A); 646 if(!f && (t == 2 || t == 3 || t == 4)) { 647 f = 1; 648 if(debug['P']) 649 print("; %D set and !f; f=%d", v1, f); 650 } 651 } 652 if(debug['P']) 653 print("\n"); 654 if(r->s2) 655 if(!copy1(v1, v2, r->s2, f)) 656 return 0; 657 } 658 return 1; 659 } 660 661 /* 662 * return 663 * 1 if v only used (and substitute), 664 * 2 if read-alter-rewrite 665 * 3 if set 666 * 4 if set and used 667 * 0 otherwise (not touched) 668 */ 669 int 670 copyu(Prog *p, Adr *v, Adr *s) 671 { 672 673 switch(p->as) { 674 675 default: 676 if(debug['P']) 677 print("unknown op %A\n", p->as); 678 /* SBBL; ADCL; FLD1; SAHF */ 679 return 2; 680 681 682 case ANEGB: 683 case ANEGW: 684 case ANEGL: 685 case ANOTB: 686 case ANOTW: 687 case ANOTL: 688 if(copyas(&p->to, v)) 689 return 2; 690 break; 691 692 case ALEAL: /* lhs addr, rhs store */ 693 if(copyas(&p->from, v)) 694 return 2; 695 696 697 case ANOP: /* rhs store */ 698 case AMOVL: 699 case AMOVBLSX: 700 case AMOVBLZX: 701 case AMOVWLSX: 702 case AMOVWLZX: 703 704 case AMOVSS: 705 case AMOVSD: 706 case ACVTSD2SL: 707 case ACVTSD2SS: 708 case ACVTSL2SD: 709 case ACVTSL2SS: 710 case ACVTSS2SD: 711 case ACVTSS2SL: 712 case ACVTTSD2SL: 713 case ACVTTSS2SL: 714 if(copyas(&p->to, v)) { 715 if(s != A) 716 return copysub(&p->from, v, s, 1); 717 if(copyau(&p->from, v)) 718 return 4; 719 return 3; 720 } 721 goto caseread; 722 723 case ARCLB: 724 case ARCLL: 725 case ARCLW: 726 case ARCRB: 727 case ARCRL: 728 case ARCRW: 729 case AROLB: 730 case AROLL: 731 case AROLW: 732 case ARORB: 733 case ARORL: 734 case ARORW: 735 case ASALB: 736 case ASALL: 737 case ASALW: 738 case ASARB: 739 case ASARL: 740 case ASARW: 741 case ASHLB: 742 case ASHLL: 743 case ASHLW: 744 case ASHRB: 745 case ASHRL: 746 case ASHRW: 747 if(copyas(&p->to, v)) 748 return 2; 749 if(copyas(&p->from, v)) 750 if(p->from.type == D_CX) 751 return 2; 752 goto caseread; 753 754 case AADDB: /* rhs rar */ 755 case AADDL: 756 case AADDW: 757 case AANDB: 758 case AANDL: 759 case AANDW: 760 case ADECL: 761 case ADECW: 762 case AINCL: 763 case AINCW: 764 case ASUBB: 765 case ASUBL: 766 case ASUBW: 767 case AORB: 768 case AORL: 769 case AORW: 770 case AXORB: 771 case AXORL: 772 case AXORW: 773 case AMOVB: 774 case AMOVW: 775 776 case AADDSD: 777 case AADDSS: 778 case ACMPSD: 779 case ACMPSS: 780 case ADIVSD: 781 case ADIVSS: 782 case AMAXSD: 783 case AMAXSS: 784 case AMINSD: 785 case AMINSS: 786 case AMULSD: 787 case AMULSS: 788 case ARCPSS: 789 case ARSQRTSS: 790 case ASQRTSD: 791 case ASQRTSS: 792 case ASUBSD: 793 case ASUBSS: 794 case AXORPD: 795 if(copyas(&p->to, v)) 796 return 2; 797 goto caseread; 798 799 case ACMPL: /* read only */ 800 case ACMPW: 801 case ACMPB: 802 803 case ACOMISD: 804 case ACOMISS: 805 case AUCOMISD: 806 case AUCOMISS: 807 caseread: 808 if(s != A) { 809 if(copysub(&p->from, v, s, 1)) 810 return 1; 811 return copysub(&p->to, v, s, 1); 812 } 813 if(copyau(&p->from, v)) 814 return 1; 815 if(copyau(&p->to, v)) 816 return 1; 817 break; 818 819 case AJGE: /* no reference */ 820 case AJNE: 821 case AJLE: 822 case AJEQ: 823 case AJHI: 824 case AJLS: 825 case AJMI: 826 case AJPL: 827 case AJGT: 828 case AJLT: 829 case AJCC: 830 case AJCS: 831 832 case AADJSP: 833 case AWAIT: 834 case ACLD: 835 break; 836 837 case AIMULL: 838 case AIMULW: 839 if(p->to.type != D_NONE) { 840 if(copyas(&p->to, v)) 841 return 2; 842 goto caseread; 843 } 844 845 case ADIVB: 846 case ADIVL: 847 case ADIVW: 848 case AIDIVB: 849 case AIDIVL: 850 case AIDIVW: 851 case AIMULB: 852 case AMULB: 853 case AMULL: 854 case AMULW: 855 856 case ACWD: 857 case ACDQ: 858 if(v->type == D_AX || v->type == D_DX) 859 return 2; 860 goto caseread; 861 862 case AREP: 863 case AREPN: 864 if(v->type == D_CX) 865 return 2; 866 goto caseread; 867 868 case AMOVSB: 869 case AMOVSL: 870 if(v->type == D_DI || v->type == D_SI) 871 return 2; 872 goto caseread; 873 874 case ASTOSB: 875 case ASTOSL: 876 if(v->type == D_AX || v->type == D_DI) 877 return 2; 878 goto caseread; 879 880 case AJMP: /* funny */ 881 if(s != A) { 882 if(copysub(&p->to, v, s, 1)) 883 return 1; 884 return 0; 885 } 886 if(copyau(&p->to, v)) 887 return 1; 888 return 0; 889 890 case ARET: /* funny */ 891 if(s != A) 892 return 1; 893 return 3; 894 895 case ACALL: /* funny */ 896 if(REGEXT && v->type <= REGEXT && v->type > exregoffset) 897 return 2; 898 if(REGARG >= 0 && v->type == (uchar)REGARG) 899 return 2; 900 if(v->type == p->from.type) 901 return 2; 902 903 if(s != A) { 904 if(copysub(&p->to, v, s, 1)) 905 return 1; 906 return 0; 907 } 908 if(copyau(&p->to, v)) 909 return 4; 910 return 3; 911 912 case ATEXT: /* funny */ 913 if(REGARG >= 0 && v->type == (uchar)REGARG) 914 return 3; 915 return 0; 916 } 917 return 0; 918 } 919 920 /* 921 * direct reference, 922 * could be set/use depending on 923 * semantics 924 */ 925 int 926 copyas(Adr *a, Adr *v) 927 { 928 if(a->type != v->type) 929 return 0; 930 if(regtyp(v)) 931 return 1; 932 if(v->type == D_AUTO || v->type == D_PARAM) 933 if(v->offset == a->offset) 934 return 1; 935 return 0; 936 } 937 938 /* 939 * either direct or indirect 940 */ 941 int 942 copyau(Adr *a, Adr *v) 943 { 944 945 if(copyas(a, v)) 946 return 1; 947 if(regtyp(v)) { 948 if(a->type-D_INDIR == v->type) 949 return 1; 950 if(a->index == v->type) 951 return 1; 952 } 953 return 0; 954 } 955 956 /* 957 * substitute s for v in a 958 * return failure to substitute 959 */ 960 int 961 copysub(Adr *a, Adr *v, Adr *s, int f) 962 { 963 int t; 964 965 if(copyas(a, v)) { 966 t = s->type; 967 if(t >= D_AX && t <= D_DI || t >= D_X0 && t <= D_X7) { 968 if(f) 969 a->type = t; 970 } 971 return 0; 972 } 973 if(regtyp(v)) { 974 t = v->type; 975 if(a->type == t+D_INDIR) { 976 if((s->type == D_BP) && a->index != D_NONE) 977 return 1; /* can't use BP-base with index */ 978 if(f) 979 a->type = s->type+D_INDIR; 980 // return 0; 981 } 982 if(a->index == t) { 983 if(f) 984 a->index = s->type; 985 return 0; 986 } 987 return 0; 988 } 989 return 0; 990 } 991 992 static void 993 conprop(Reg *r0) 994 { 995 Reg *r; 996 Prog *p, *p0; 997 int t; 998 Adr *v0; 999 1000 p0 = r0->prog; 1001 v0 = &p0->to; 1002 r = r0; 1003 1004 loop: 1005 r = uniqs(r); 1006 if(r == R || r == r0) 1007 return; 1008 if(uniqp(r) == R) 1009 return; 1010 1011 p = r->prog; 1012 t = copyu(p, v0, A); 1013 switch(t) { 1014 case 0: // miss 1015 case 1: // use 1016 goto loop; 1017 1018 case 2: // rar 1019 case 4: // use and set 1020 break; 1021 1022 case 3: // set 1023 if(p->as == p0->as) 1024 if(p->from.type == p0->from.type) 1025 if(p->from.node == p0->from.node) 1026 if(p->from.offset == p0->from.offset) 1027 if(p->from.scale == p0->from.scale) 1028 if(p->from.u.vval == p0->from.u.vval) 1029 if(p->from.index == p0->from.index) { 1030 excise(r); 1031 goto loop; 1032 } 1033 break; 1034 } 1035 }