github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/6c/peep.c (about) 1 // 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 "gc.h" 32 33 static int 34 needc(Prog *p) 35 { 36 while(p != P) { 37 switch(p->as) { 38 case AADCL: 39 case AADCQ: 40 case ASBBL: 41 case ASBBQ: 42 case ARCRL: 43 case ARCRQ: 44 return 1; 45 case AADDL: 46 case AADDQ: 47 case ASUBL: 48 case ASUBQ: 49 case AJMP: 50 case ARET: 51 case ACALL: 52 return 0; 53 default: 54 if(p->to.type == D_BRANCH) 55 return 0; 56 } 57 p = p->link; 58 } 59 return 0; 60 } 61 62 static Reg* 63 rnops(Reg *r) 64 { 65 Prog *p; 66 Reg *r1; 67 68 if(r != R) 69 for(;;){ 70 p = r->prog; 71 if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE) 72 break; 73 r1 = uniqs(r); 74 if(r1 == R) 75 break; 76 r = r1; 77 } 78 return r; 79 } 80 81 void 82 peep(void) 83 { 84 Reg *r, *r1, *r2; 85 Prog *p, *p1; 86 int t; 87 88 /* 89 * complete R structure 90 */ 91 t = 0; 92 for(r=firstr; r!=R; r=r1) { 93 r1 = r->link; 94 if(r1 == R) 95 break; 96 p = r->prog->link; 97 while(p != r1->prog) 98 switch(p->as) { 99 default: 100 r2 = rega(); 101 r->link = r2; 102 r2->link = r1; 103 104 r2->prog = p; 105 r2->p1 = r; 106 r->s1 = r2; 107 r2->s1 = r1; 108 r1->p1 = r2; 109 110 r = r2; 111 t++; 112 113 case ADATA: 114 case AGLOBL: 115 case ANAME: 116 case ASIGNAME: 117 p = p->link; 118 } 119 } 120 121 pc = 0; /* speculating it won't kill */ 122 123 loop1: 124 125 t = 0; 126 for(r=firstr; r!=R; r=r->link) { 127 p = r->prog; 128 switch(p->as) { 129 case AMOVL: 130 case AMOVQ: 131 case AMOVSS: 132 case AMOVSD: 133 if(regtyp(&p->to)) 134 if(regtyp(&p->from)) { 135 if(copyprop(r)) { 136 excise(r); 137 t++; 138 } else 139 if(subprop(r) && copyprop(r)) { 140 excise(r); 141 t++; 142 } 143 } 144 break; 145 146 case AMOVBLZX: 147 case AMOVWLZX: 148 case AMOVBLSX: 149 case AMOVWLSX: 150 if(regtyp(&p->to)) { 151 r1 = rnops(uniqs(r)); 152 if(r1 != R) { 153 p1 = r1->prog; 154 if(p->as == p1->as && p->to.type == p1->from.type){ 155 p1->as = AMOVL; 156 t++; 157 } 158 } 159 } 160 break; 161 162 case AMOVBQSX: 163 case AMOVBQZX: 164 case AMOVWQSX: 165 case AMOVWQZX: 166 case AMOVLQSX: 167 case AMOVLQZX: 168 if(regtyp(&p->to)) { 169 r1 = rnops(uniqs(r)); 170 if(r1 != R) { 171 p1 = r1->prog; 172 if(p->as == p1->as && p->to.type == p1->from.type){ 173 p1->as = AMOVQ; 174 t++; 175 } 176 } 177 } 178 break; 179 180 case AADDL: 181 case AADDQ: 182 case AADDW: 183 if(p->from.type != D_CONST || needc(p->link)) 184 break; 185 if(p->from.offset == -1){ 186 if(p->as == AADDQ) 187 p->as = ADECQ; 188 else if(p->as == AADDL) 189 p->as = ADECL; 190 else 191 p->as = ADECW; 192 p->from = zprog.from; 193 } 194 else if(p->from.offset == 1){ 195 if(p->as == AADDQ) 196 p->as = AINCQ; 197 else if(p->as == AADDL) 198 p->as = AINCL; 199 else 200 p->as = AINCW; 201 p->from = zprog.from; 202 } 203 break; 204 205 case ASUBL: 206 case ASUBQ: 207 case ASUBW: 208 if(p->from.type != D_CONST || needc(p->link)) 209 break; 210 if(p->from.offset == -1) { 211 if(p->as == ASUBQ) 212 p->as = AINCQ; 213 else if(p->as == ASUBL) 214 p->as = AINCL; 215 else 216 p->as = AINCW; 217 p->from = zprog.from; 218 } 219 else if(p->from.offset == 1){ 220 if(p->as == ASUBQ) 221 p->as = ADECQ; 222 else if(p->as == ASUBL) 223 p->as = ADECL; 224 else 225 p->as = ADECW; 226 p->from = zprog.from; 227 } 228 break; 229 } 230 } 231 if(t) 232 goto loop1; 233 } 234 235 void 236 excise(Reg *r) 237 { 238 Prog *p; 239 240 p = r->prog; 241 p->as = ANOP; 242 p->from = zprog.from; 243 p->to = zprog.to; 244 } 245 246 Reg* 247 uniqp(Reg *r) 248 { 249 Reg *r1; 250 251 r1 = r->p1; 252 if(r1 == R) { 253 r1 = r->p2; 254 if(r1 == R || r1->p2link != R) 255 return R; 256 } else 257 if(r->p2 != R) 258 return R; 259 return r1; 260 } 261 262 Reg* 263 uniqs(Reg *r) 264 { 265 Reg *r1; 266 267 r1 = r->s1; 268 if(r1 == R) { 269 r1 = r->s2; 270 if(r1 == R) 271 return R; 272 } else 273 if(r->s2 != R) 274 return R; 275 return r1; 276 } 277 278 int 279 regtyp(Addr *a) 280 { 281 int t; 282 283 t = a->type; 284 if(t >= D_AX && t <= D_R15) 285 return 1; 286 if(t >= D_X0 && t <= D_X0+15) 287 return 1; 288 return 0; 289 } 290 291 /* 292 * the idea is to substitute 293 * one register for another 294 * from one MOV to another 295 * MOV a, R0 296 * ADD b, R0 / no use of R1 297 * MOV R0, R1 298 * would be converted to 299 * MOV a, R1 300 * ADD b, R1 301 * MOV R1, R0 302 * hopefully, then the former or latter MOV 303 * will be eliminated by copy propagation. 304 */ 305 int 306 subprop(Reg *r0) 307 { 308 Prog *p; 309 Addr *v1, *v2; 310 Reg *r; 311 int t; 312 313 p = r0->prog; 314 v1 = &p->from; 315 if(!regtyp(v1)) 316 return 0; 317 v2 = &p->to; 318 if(!regtyp(v2)) 319 return 0; 320 for(r=uniqp(r0); r!=R; r=uniqp(r)) { 321 if(uniqs(r) == R) 322 break; 323 p = r->prog; 324 switch(p->as) { 325 case ACALL: 326 return 0; 327 328 case AIMULL: 329 case AIMULQ: 330 case AIMULW: 331 if(p->to.type != D_NONE) 332 break; 333 goto giveup; 334 335 case AROLB: 336 case AROLL: 337 case AROLQ: 338 case AROLW: 339 case ARORB: 340 case ARORL: 341 case ARORQ: 342 case ARORW: 343 case ASALB: 344 case ASALL: 345 case ASALQ: 346 case ASALW: 347 case ASARB: 348 case ASARL: 349 case ASARQ: 350 case ASARW: 351 case ASHLB: 352 case ASHLL: 353 case ASHLQ: 354 case ASHLW: 355 case ASHRB: 356 case ASHRL: 357 case ASHRQ: 358 case ASHRW: 359 if(p->from.type == D_CONST) 360 break; 361 goto giveup; 362 363 case ADIVB: 364 case ADIVL: 365 case ADIVQ: 366 case ADIVW: 367 case AIDIVB: 368 case AIDIVL: 369 case AIDIVQ: 370 case AIDIVW: 371 case AIMULB: 372 case AMULB: 373 case AMULL: 374 case AMULQ: 375 case AMULW: 376 377 case AREP: 378 case AREPN: 379 380 case ACWD: 381 case ACDQ: 382 case ACQO: 383 384 case ASTOSB: 385 case ASTOSL: 386 case ASTOSQ: 387 case AMOVSB: 388 case AMOVSL: 389 case AMOVSQ: 390 case AMOVQL: 391 giveup: 392 return 0; 393 394 case AMOVL: 395 case AMOVQ: 396 if(p->to.type == v1->type) 397 goto gotit; 398 break; 399 } 400 if(copyau(&p->from, v2) || 401 copyau(&p->to, v2)) 402 break; 403 if(copysub(&p->from, v1, v2, 0) || 404 copysub(&p->to, v1, v2, 0)) 405 break; 406 } 407 return 0; 408 409 gotit: 410 copysub(&p->to, v1, v2, 1); 411 if(debug['P']) { 412 print("gotit: %D->%D\n%P", v1, v2, r->prog); 413 if(p->from.type == v2->type) 414 print(" excise"); 415 print("\n"); 416 } 417 for(r=uniqs(r); r!=r0; r=uniqs(r)) { 418 p = r->prog; 419 copysub(&p->from, v1, v2, 1); 420 copysub(&p->to, v1, v2, 1); 421 if(debug['P']) 422 print("%P\n", r->prog); 423 } 424 t = v1->type; 425 v1->type = v2->type; 426 v2->type = t; 427 if(debug['P']) 428 print("%P last\n", r->prog); 429 return 1; 430 } 431 432 /* 433 * The idea is to remove redundant copies. 434 * v1->v2 F=0 435 * (use v2 s/v2/v1/)* 436 * set v1 F=1 437 * use v2 return fail 438 * ----------------- 439 * v1->v2 F=0 440 * (use v2 s/v2/v1/)* 441 * set v1 F=1 442 * set v2 return success 443 */ 444 int 445 copyprop(Reg *r0) 446 { 447 Prog *p; 448 Addr *v1, *v2; 449 Reg *r; 450 451 p = r0->prog; 452 v1 = &p->from; 453 v2 = &p->to; 454 if(copyas(v1, v2)) 455 return 1; 456 for(r=firstr; r!=R; r=r->link) 457 r->active = 0; 458 return copy1(v1, v2, r0->s1, 0); 459 } 460 461 int 462 copy1(Addr *v1, Addr *v2, Reg *r, int f) 463 { 464 int t; 465 Prog *p; 466 467 if(r->active) { 468 if(debug['P']) 469 print("act set; return 1\n"); 470 return 1; 471 } 472 r->active = 1; 473 if(debug['P']) 474 print("copy %D->%D f=%d\n", v1, v2, f); 475 for(; r != R; r = r->s1) { 476 p = r->prog; 477 if(debug['P']) 478 print("%P", p); 479 if(!f && uniqp(r) == R) { 480 f = 1; 481 if(debug['P']) 482 print("; merge; f=%d", f); 483 } 484 t = copyu(p, v2, A); 485 switch(t) { 486 case 2: /* rar, can't split */ 487 if(debug['P']) 488 print("; %D rar; return 0\n", v2); 489 return 0; 490 491 case 3: /* set */ 492 if(debug['P']) 493 print("; %D set; return 1\n", v2); 494 return 1; 495 496 case 1: /* used, substitute */ 497 case 4: /* use and set */ 498 if(f) { 499 if(!debug['P']) 500 return 0; 501 if(t == 4) 502 print("; %D used+set and f=%d; return 0\n", v2, f); 503 else 504 print("; %D used and f=%d; return 0\n", v2, f); 505 return 0; 506 } 507 if(copyu(p, v2, v1)) { 508 if(debug['P']) 509 print("; sub fail; return 0\n"); 510 return 0; 511 } 512 if(debug['P']) 513 print("; sub %D/%D", v2, v1); 514 if(t == 4) { 515 if(debug['P']) 516 print("; %D used+set; return 1\n", v2); 517 return 1; 518 } 519 break; 520 } 521 if(!f) { 522 t = copyu(p, v1, A); 523 if(!f && (t == 2 || t == 3 || t == 4)) { 524 f = 1; 525 if(debug['P']) 526 print("; %D set and !f; f=%d", v1, f); 527 } 528 } 529 if(debug['P']) 530 print("\n"); 531 if(r->s2) 532 if(!copy1(v1, v2, r->s2, f)) 533 return 0; 534 } 535 return 1; 536 } 537 538 /* 539 * return 540 * 1 if v only used (and substitute), 541 * 2 if read-alter-rewrite 542 * 3 if set 543 * 4 if set and used 544 * 0 otherwise (not touched) 545 */ 546 int 547 copyu(Prog *p, Addr *v, Addr *s) 548 { 549 550 switch(p->as) { 551 552 default: 553 if(debug['P']) 554 print("unknown op %A\n", p->as); 555 /* SBBL; ADCL; FLD1; SAHF */ 556 return 2; 557 558 559 case ANEGB: 560 case ANEGW: 561 case ANEGL: 562 case ANEGQ: 563 case ANOTB: 564 case ANOTW: 565 case ANOTL: 566 case ANOTQ: 567 if(copyas(&p->to, v)) 568 return 2; 569 break; 570 571 case ALEAL: /* lhs addr, rhs store */ 572 case ALEAQ: 573 if(copyas(&p->from, v)) 574 return 2; 575 576 577 case ANOP: /* rhs store */ 578 case AMOVL: 579 case AMOVQ: 580 case AMOVBLSX: 581 case AMOVBLZX: 582 case AMOVBQSX: 583 case AMOVBQZX: 584 case AMOVLQSX: 585 case AMOVLQZX: 586 case AMOVWLSX: 587 case AMOVWLZX: 588 case AMOVWQSX: 589 case AMOVWQZX: 590 case AMOVQL: 591 592 case AMOVSS: 593 case AMOVSD: 594 case ACVTSD2SL: 595 case ACVTSD2SQ: 596 case ACVTSD2SS: 597 case ACVTSL2SD: 598 case ACVTSL2SS: 599 case ACVTSQ2SD: 600 case ACVTSQ2SS: 601 case ACVTSS2SD: 602 case ACVTSS2SL: 603 case ACVTSS2SQ: 604 case ACVTTSD2SL: 605 case ACVTTSD2SQ: 606 case ACVTTSS2SL: 607 case ACVTTSS2SQ: 608 if(copyas(&p->to, v)) { 609 if(s != A) 610 return copysub(&p->from, v, s, 1); 611 if(copyau(&p->from, v)) 612 return 4; 613 return 3; 614 } 615 goto caseread; 616 617 case AROLB: 618 case AROLL: 619 case AROLQ: 620 case AROLW: 621 case ARORB: 622 case ARORL: 623 case ARORQ: 624 case ARORW: 625 case ASALB: 626 case ASALL: 627 case ASALQ: 628 case ASALW: 629 case ASARB: 630 case ASARL: 631 case ASARQ: 632 case ASARW: 633 case ASHLB: 634 case ASHLL: 635 case ASHLQ: 636 case ASHLW: 637 case ASHRB: 638 case ASHRL: 639 case ASHRQ: 640 case ASHRW: 641 if(copyas(&p->to, v)) 642 return 2; 643 if(copyas(&p->from, v)) 644 if(p->from.type == D_CX) 645 return 2; 646 goto caseread; 647 648 case AADDB: /* rhs rar */ 649 case AADDL: 650 case AADDQ: 651 case AADDW: 652 case AANDB: 653 case AANDL: 654 case AANDQ: 655 case AANDW: 656 case ADECL: 657 case ADECQ: 658 case ADECW: 659 case AINCL: 660 case AINCQ: 661 case AINCW: 662 case ASUBB: 663 case ASUBL: 664 case ASUBQ: 665 case ASUBW: 666 case AORB: 667 case AORL: 668 case AORQ: 669 case AORW: 670 case AXORB: 671 case AXORL: 672 case AXORQ: 673 case AXORW: 674 case AMOVB: 675 case AMOVW: 676 677 case AADDSD: 678 case AADDSS: 679 case ACMPSD: 680 case ACMPSS: 681 case ADIVSD: 682 case ADIVSS: 683 case AMAXSD: 684 case AMAXSS: 685 case AMINSD: 686 case AMINSS: 687 case AMULSD: 688 case AMULSS: 689 case ARCPSS: 690 case ARSQRTSS: 691 case ASQRTSD: 692 case ASQRTSS: 693 case ASUBSD: 694 case ASUBSS: 695 case AXORPD: 696 if(copyas(&p->to, v)) 697 return 2; 698 goto caseread; 699 700 case ACMPL: /* read only */ 701 case ACMPW: 702 case ACMPB: 703 case ACMPQ: 704 705 case APREFETCHT0: 706 case APREFETCHT1: 707 case APREFETCHT2: 708 case APREFETCHNTA: 709 710 case ACOMISD: 711 case ACOMISS: 712 case AUCOMISD: 713 case AUCOMISS: 714 caseread: 715 if(s != A) { 716 if(copysub(&p->from, v, s, 1)) 717 return 1; 718 return copysub(&p->to, v, s, 1); 719 } 720 if(copyau(&p->from, v)) 721 return 1; 722 if(copyau(&p->to, v)) 723 return 1; 724 break; 725 726 case AJGE: /* no reference */ 727 case AJNE: 728 case AJLE: 729 case AJEQ: 730 case AJHI: 731 case AJLS: 732 case AJMI: 733 case AJPL: 734 case AJGT: 735 case AJLT: 736 case AJCC: 737 case AJCS: 738 739 case AADJSP: 740 case AWAIT: 741 case ACLD: 742 break; 743 744 case AIMULL: 745 case AIMULQ: 746 case AIMULW: 747 if(p->to.type != D_NONE) { 748 if(copyas(&p->to, v)) 749 return 2; 750 goto caseread; 751 } 752 753 case ADIVB: 754 case ADIVL: 755 case ADIVQ: 756 case ADIVW: 757 case AIDIVB: 758 case AIDIVL: 759 case AIDIVQ: 760 case AIDIVW: 761 case AIMULB: 762 case AMULB: 763 case AMULL: 764 case AMULQ: 765 case AMULW: 766 767 case ACWD: 768 case ACDQ: 769 case ACQO: 770 if(v->type == D_AX || v->type == D_DX) 771 return 2; 772 goto caseread; 773 774 case AREP: 775 case AREPN: 776 if(v->type == D_CX) 777 return 2; 778 goto caseread; 779 780 case AMOVSB: 781 case AMOVSL: 782 case AMOVSQ: 783 if(v->type == D_DI || v->type == D_SI) 784 return 2; 785 goto caseread; 786 787 case ASTOSB: 788 case ASTOSL: 789 case ASTOSQ: 790 if(v->type == D_AX || v->type == D_DI) 791 return 2; 792 goto caseread; 793 794 case AJMP: /* funny */ 795 if(s != A) { 796 if(copysub(&p->to, v, s, 1)) 797 return 1; 798 return 0; 799 } 800 if(copyau(&p->to, v)) 801 return 1; 802 return 0; 803 804 case ARET: /* funny */ 805 if(v->type == REGRET || v->type == FREGRET) 806 return 2; 807 if(s != A) 808 return 1; 809 return 3; 810 811 case ACALL: /* funny */ 812 if(REGARG >= 0 && v->type == (uchar)REGARG) 813 return 2; 814 815 if(s != A) { 816 if(copysub(&p->to, v, s, 1)) 817 return 1; 818 return 0; 819 } 820 if(copyau(&p->to, v)) 821 return 4; 822 return 3; 823 824 case ATEXT: /* funny */ 825 if(REGARG >= 0 && v->type == (uchar)REGARG) 826 return 3; 827 return 0; 828 } 829 return 0; 830 } 831 832 /* 833 * direct reference, 834 * could be set/use depending on 835 * semantics 836 */ 837 int 838 copyas(Addr *a, Addr *v) 839 { 840 if(a->type != v->type) 841 return 0; 842 if(regtyp(v)) 843 return 1; 844 if(v->type == D_AUTO || v->type == D_PARAM) 845 if(v->offset == a->offset) 846 return 1; 847 return 0; 848 } 849 850 /* 851 * either direct or indirect 852 */ 853 int 854 copyau(Addr *a, Addr *v) 855 { 856 857 if(copyas(a, v)) 858 return 1; 859 if(regtyp(v)) { 860 if(a->type-D_INDIR == v->type) 861 return 1; 862 if(a->index == v->type) 863 return 1; 864 } 865 return 0; 866 } 867 868 /* 869 * substitute s for v in a 870 * return failure to substitute 871 */ 872 int 873 copysub(Addr *a, Addr *v, Addr *s, int f) 874 { 875 int t; 876 877 if(copyas(a, v)) { 878 t = s->type; 879 if(t >= D_AX && t <= D_R15 || t >= D_X0 && t <= D_X0+15) { 880 if(f) 881 a->type = t; 882 } 883 return 0; 884 } 885 if(regtyp(v)) { 886 t = v->type; 887 if(a->type == t+D_INDIR) { 888 if((s->type == D_BP || s->type == D_R13) && a->index != D_NONE) 889 return 1; /* can't use BP-base with index */ 890 if(f) 891 a->type = s->type+D_INDIR; 892 // return 0; 893 } 894 if(a->index == t) { 895 if(f) 896 a->index = s->type; 897 return 0; 898 } 899 return 0; 900 } 901 return 0; 902 }