github.com/ccccaoqing/test@v0.0.0-20220510085219-3985d23445c0/src/cmd/8c/peep.c (about) 1 // Inferno utils/8c/peep.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8c/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 ASBBL: 40 case ARCRL: 41 return 1; 42 case AADDL: 43 case ASUBL: 44 case AJMP: 45 case ARET: 46 case ACALL: 47 return 0; 48 default: 49 if(p->to.type == D_BRANCH) 50 return 0; 51 } 52 p = p->link; 53 } 54 return 0; 55 } 56 57 void 58 peep(void) 59 { 60 Reg *r, *r1, *r2; 61 Prog *p, *p1; 62 int t; 63 64 /* 65 * complete R structure 66 */ 67 t = 0; 68 for(r=firstr; r!=R; r=r1) { 69 r1 = r->link; 70 if(r1 == R) 71 break; 72 p = r->prog->link; 73 while(p != r1->prog) 74 switch(p->as) { 75 default: 76 r2 = rega(); 77 r->link = r2; 78 r2->link = r1; 79 80 r2->prog = p; 81 r2->p1 = r; 82 r->s1 = r2; 83 r2->s1 = r1; 84 r1->p1 = r2; 85 86 r = r2; 87 t++; 88 89 case ADATA: 90 case AGLOBL: 91 case ANAME: 92 case ASIGNAME: 93 p = p->link; 94 } 95 } 96 97 pc = 0; /* speculating it won't kill */ 98 99 loop1: 100 101 t = 0; 102 for(r=firstr; r!=R; r=r->link) { 103 p = r->prog; 104 switch(p->as) { 105 case AMOVL: 106 if(regtyp(&p->to)) 107 if(regtyp(&p->from)) { 108 if(copyprop(r)) { 109 excise(r); 110 t++; 111 } 112 if(subprop(r) && copyprop(r)) { 113 excise(r); 114 t++; 115 } 116 } 117 break; 118 119 case AMOVBLSX: 120 case AMOVBLZX: 121 case AMOVWLSX: 122 case AMOVWLZX: 123 if(regtyp(&p->to)) { 124 r1 = uniqs(r); 125 if(r1 != R) { 126 p1 = r1->prog; 127 if(p->as == p1->as && p->to.type == p1->from.type) 128 p1->as = AMOVL; 129 } 130 } 131 break; 132 case AADDL: 133 case AADDW: 134 if(p->from.type != D_CONST || needc(p->link)) 135 break; 136 if(p->from.offset == -1){ 137 if(p->as == AADDL) 138 p->as = ADECL; 139 else 140 p->as = ADECW; 141 p->from = zprog.from; 142 } 143 else if(p->from.offset == 1){ 144 if(p->as == AADDL) 145 p->as = AINCL; 146 else 147 p->as = AINCW; 148 p->from = zprog.from; 149 } 150 break; 151 case ASUBL: 152 case ASUBW: 153 if(p->from.type != D_CONST || needc(p->link)) 154 break; 155 if(p->from.offset == -1) { 156 if(p->as == ASUBL) 157 p->as = AINCL; 158 else 159 p->as = AINCW; 160 p->from = zprog.from; 161 } 162 else if(p->from.offset == 1){ 163 if(p->as == ASUBL) 164 p->as = ADECL; 165 else 166 p->as = ADECW; 167 p->from = zprog.from; 168 } 169 break; 170 } 171 } 172 if(t) 173 goto loop1; 174 } 175 176 void 177 excise(Reg *r) 178 { 179 Prog *p; 180 181 p = r->prog; 182 p->as = ANOP; 183 p->from = zprog.from; 184 p->to = zprog.to; 185 } 186 187 Reg* 188 uniqp(Reg *r) 189 { 190 Reg *r1; 191 192 r1 = r->p1; 193 if(r1 == R) { 194 r1 = r->p2; 195 if(r1 == R || r1->p2link != R) 196 return R; 197 } else 198 if(r->p2 != R) 199 return R; 200 return r1; 201 } 202 203 Reg* 204 uniqs(Reg *r) 205 { 206 Reg *r1; 207 208 r1 = r->s1; 209 if(r1 == R) { 210 r1 = r->s2; 211 if(r1 == R) 212 return R; 213 } else 214 if(r->s2 != R) 215 return R; 216 return r1; 217 } 218 219 int 220 regtyp(Addr *a) 221 { 222 int t; 223 224 t = a->type; 225 if(t >= D_AX && t <= D_DI) 226 return 1; 227 return 0; 228 } 229 230 /* 231 * the idea is to substitute 232 * one register for another 233 * from one MOV to another 234 * MOV a, R0 235 * ADD b, R0 / no use of R1 236 * MOV R0, R1 237 * would be converted to 238 * MOV a, R1 239 * ADD b, R1 240 * MOV R1, R0 241 * hopefully, then the former or latter MOV 242 * will be eliminated by copy propagation. 243 */ 244 int 245 subprop(Reg *r0) 246 { 247 Prog *p; 248 Addr *v1, *v2; 249 Reg *r; 250 int t; 251 252 p = r0->prog; 253 v1 = &p->from; 254 if(!regtyp(v1)) 255 return 0; 256 v2 = &p->to; 257 if(!regtyp(v2)) 258 return 0; 259 for(r=uniqp(r0); r!=R; r=uniqp(r)) { 260 if(uniqs(r) == R) 261 break; 262 p = r->prog; 263 switch(p->as) { 264 case ACALL: 265 return 0; 266 267 case AIMULL: 268 case AIMULW: 269 if(p->to.type != D_NONE) 270 break; 271 272 case ADIVB: 273 case ADIVL: 274 case ADIVW: 275 case AIDIVB: 276 case AIDIVL: 277 case AIDIVW: 278 case AIMULB: 279 case AMULB: 280 case AMULL: 281 case AMULW: 282 283 case AROLB: 284 case AROLL: 285 case AROLW: 286 case ARORB: 287 case ARORL: 288 case ARORW: 289 case ASALB: 290 case ASALL: 291 case ASALW: 292 case ASARB: 293 case ASARL: 294 case ASARW: 295 case ASHLB: 296 case ASHLL: 297 case ASHLW: 298 case ASHRB: 299 case ASHRL: 300 case ASHRW: 301 302 case AREP: 303 case AREPN: 304 305 case ACWD: 306 case ACDQ: 307 308 case ASTOSB: 309 case ASTOSL: 310 case AMOVSB: 311 case AMOVSL: 312 case AFSTSW: 313 return 0; 314 315 case AMOVL: 316 if(p->to.type == v1->type) 317 goto gotit; 318 break; 319 } 320 if(copyau(&p->from, v2) || 321 copyau(&p->to, v2)) 322 break; 323 if(copysub(&p->from, v1, v2, 0) || 324 copysub(&p->to, v1, v2, 0)) 325 break; 326 } 327 return 0; 328 329 gotit: 330 copysub(&p->to, v1, v2, 1); 331 if(debug['P']) { 332 print("gotit: %D->%D\n%P", v1, v2, r->prog); 333 if(p->from.type == v2->type) 334 print(" excise"); 335 print("\n"); 336 } 337 for(r=uniqs(r); r!=r0; r=uniqs(r)) { 338 p = r->prog; 339 copysub(&p->from, v1, v2, 1); 340 copysub(&p->to, v1, v2, 1); 341 if(debug['P']) 342 print("%P\n", r->prog); 343 } 344 t = v1->type; 345 v1->type = v2->type; 346 v2->type = t; 347 if(debug['P']) 348 print("%P last\n", r->prog); 349 return 1; 350 } 351 352 /* 353 * The idea is to remove redundant copies. 354 * v1->v2 F=0 355 * (use v2 s/v2/v1/)* 356 * set v1 F=1 357 * use v2 return fail 358 * ----------------- 359 * v1->v2 F=0 360 * (use v2 s/v2/v1/)* 361 * set v1 F=1 362 * set v2 return success 363 */ 364 int 365 copyprop(Reg *r0) 366 { 367 Prog *p; 368 Addr *v1, *v2; 369 Reg *r; 370 371 p = r0->prog; 372 v1 = &p->from; 373 v2 = &p->to; 374 if(copyas(v1, v2)) 375 return 1; 376 for(r=firstr; r!=R; r=r->link) 377 r->active = 0; 378 return copy1(v1, v2, r0->s1, 0); 379 } 380 381 int 382 copy1(Addr *v1, Addr *v2, Reg *r, int f) 383 { 384 int t; 385 Prog *p; 386 387 if(r->active) { 388 if(debug['P']) 389 print("act set; return 1\n"); 390 return 1; 391 } 392 r->active = 1; 393 if(debug['P']) 394 print("copy %D->%D f=%d\n", v1, v2, f); 395 for(; r != R; r = r->s1) { 396 p = r->prog; 397 if(debug['P']) 398 print("%P", p); 399 if(!f && uniqp(r) == R) { 400 f = 1; 401 if(debug['P']) 402 print("; merge; f=%d", f); 403 } 404 t = copyu(p, v2, A); 405 switch(t) { 406 case 2: /* rar, can't split */ 407 if(debug['P']) 408 print("; %D rar; return 0\n", v2); 409 return 0; 410 411 case 3: /* set */ 412 if(debug['P']) 413 print("; %D set; return 1\n", v2); 414 return 1; 415 416 case 1: /* used, substitute */ 417 case 4: /* use and set */ 418 if(f) { 419 if(!debug['P']) 420 return 0; 421 if(t == 4) 422 print("; %D used+set and f=%d; return 0\n", v2, f); 423 else 424 print("; %D used and f=%d; return 0\n", v2, f); 425 return 0; 426 } 427 if(copyu(p, v2, v1)) { 428 if(debug['P']) 429 print("; sub fail; return 0\n"); 430 return 0; 431 } 432 if(debug['P']) 433 print("; sub %D/%D", v2, v1); 434 if(t == 4) { 435 if(debug['P']) 436 print("; %D used+set; return 1\n", v2); 437 return 1; 438 } 439 break; 440 } 441 if(!f) { 442 t = copyu(p, v1, A); 443 if(!f && (t == 2 || t == 3 || t == 4)) { 444 f = 1; 445 if(debug['P']) 446 print("; %D set and !f; f=%d", v1, f); 447 } 448 } 449 if(debug['P']) 450 print("\n"); 451 if(r->s2) 452 if(!copy1(v1, v2, r->s2, f)) 453 return 0; 454 } 455 return 1; 456 } 457 458 /* 459 * return 460 * 1 if v only used (and substitute), 461 * 2 if read-alter-rewrite 462 * 3 if set 463 * 4 if set and used 464 * 0 otherwise (not touched) 465 */ 466 int 467 copyu(Prog *p, Addr *v, Addr *s) 468 { 469 470 switch(p->as) { 471 472 default: 473 if(debug['P']) 474 print("unknown op %A\n", p->as); 475 return 2; 476 477 case ANEGB: 478 case ANEGW: 479 case ANEGL: 480 case ANOTB: 481 case ANOTW: 482 case ANOTL: 483 if(copyas(&p->to, v)) 484 return 2; 485 break; 486 487 case ALEAL: /* lhs addr, rhs store */ 488 if(copyas(&p->from, v)) 489 return 2; 490 491 492 case ANOP: /* rhs store */ 493 case AMOVL: 494 case AMOVBLSX: 495 case AMOVBLZX: 496 case AMOVWLSX: 497 case AMOVWLZX: 498 if(copyas(&p->to, v)) { 499 if(s != A) 500 return copysub(&p->from, v, s, 1); 501 if(copyau(&p->from, v)) 502 return 4; 503 return 3; 504 } 505 goto caseread; 506 507 case AROLB: 508 case AROLL: 509 case AROLW: 510 case ARORB: 511 case ARORL: 512 case ARORW: 513 case ASALB: 514 case ASALL: 515 case ASALW: 516 case ASARB: 517 case ASARL: 518 case ASARW: 519 case ASHLB: 520 case ASHLL: 521 case ASHLW: 522 case ASHRB: 523 case ASHRL: 524 case ASHRW: 525 if(copyas(&p->to, v)) 526 return 2; 527 if(copyas(&p->from, v)) 528 if(p->from.type == D_CX) 529 return 2; 530 goto caseread; 531 532 case AADDB: /* rhs rar */ 533 case AADDL: 534 case AADDW: 535 case AANDB: 536 case AANDL: 537 case AANDW: 538 case ADECL: 539 case ADECW: 540 case AINCL: 541 case AINCW: 542 case ASUBB: 543 case ASUBL: 544 case ASUBW: 545 case AORB: 546 case AORL: 547 case AORW: 548 case AXORB: 549 case AXORL: 550 case AXORW: 551 case AMOVB: 552 case AMOVW: 553 554 case AFMOVB: 555 case AFMOVBP: 556 case AFMOVD: 557 case AFMOVDP: 558 case AFMOVF: 559 case AFMOVFP: 560 case AFMOVL: 561 case AFMOVLP: 562 case AFMOVV: 563 case AFMOVVP: 564 case AFMOVW: 565 case AFMOVWP: 566 case AFMOVX: 567 case AFMOVXP: 568 case AFADDDP: 569 case AFADDW: 570 case AFADDL: 571 case AFADDF: 572 case AFADDD: 573 case AFMULDP: 574 case AFMULW: 575 case AFMULL: 576 case AFMULF: 577 case AFMULD: 578 case AFSUBDP: 579 case AFSUBW: 580 case AFSUBL: 581 case AFSUBF: 582 case AFSUBD: 583 case AFSUBRDP: 584 case AFSUBRW: 585 case AFSUBRL: 586 case AFSUBRF: 587 case AFSUBRD: 588 case AFDIVDP: 589 case AFDIVW: 590 case AFDIVL: 591 case AFDIVF: 592 case AFDIVD: 593 case AFDIVRDP: 594 case AFDIVRW: 595 case AFDIVRL: 596 case AFDIVRF: 597 case AFDIVRD: 598 if(copyas(&p->to, v)) 599 return 2; 600 goto caseread; 601 602 case ACMPL: /* read only */ 603 case ACMPW: 604 case ACMPB: 605 606 case APREFETCHT0: 607 case APREFETCHT1: 608 case APREFETCHT2: 609 case APREFETCHNTA: 610 611 612 case AFCOMB: 613 case AFCOMBP: 614 case AFCOMD: 615 case AFCOMDP: 616 case AFCOMDPP: 617 case AFCOMF: 618 case AFCOMFP: 619 case AFCOML: 620 case AFCOMLP: 621 case AFCOMW: 622 case AFCOMWP: 623 case AFUCOM: 624 case AFUCOMP: 625 case AFUCOMPP: 626 caseread: 627 if(s != A) { 628 if(copysub(&p->from, v, s, 1)) 629 return 1; 630 return copysub(&p->to, v, s, 1); 631 } 632 if(copyau(&p->from, v)) 633 return 1; 634 if(copyau(&p->to, v)) 635 return 1; 636 break; 637 638 case AJGE: /* no reference */ 639 case AJNE: 640 case AJLE: 641 case AJEQ: 642 case AJHI: 643 case AJLS: 644 case AJMI: 645 case AJPL: 646 case AJGT: 647 case AJLT: 648 case AJCC: 649 case AJCS: 650 651 case AADJSP: 652 case AFLDZ: 653 case AWAIT: 654 break; 655 656 case AIMULL: 657 case AIMULW: 658 if(p->to.type != D_NONE) { 659 if(copyas(&p->to, v)) 660 return 2; 661 goto caseread; 662 } 663 664 case ADIVB: 665 case ADIVL: 666 case ADIVW: 667 case AIDIVB: 668 case AIDIVL: 669 case AIDIVW: 670 case AIMULB: 671 case AMULB: 672 case AMULL: 673 case AMULW: 674 675 case ACWD: 676 case ACDQ: 677 if(v->type == D_AX || v->type == D_DX) 678 return 2; 679 goto caseread; 680 681 case AREP: 682 case AREPN: 683 if(v->type == D_CX) 684 return 2; 685 goto caseread; 686 687 case AMOVSB: 688 case AMOVSL: 689 if(v->type == D_DI || v->type == D_SI) 690 return 2; 691 goto caseread; 692 693 case ASTOSB: 694 case ASTOSL: 695 if(v->type == D_AX || v->type == D_DI) 696 return 2; 697 goto caseread; 698 699 case AFSTSW: 700 if(v->type == D_AX) 701 return 2; 702 goto caseread; 703 704 case AJMP: /* funny */ 705 if(s != A) { 706 if(copysub(&p->to, v, s, 1)) 707 return 1; 708 return 0; 709 } 710 if(copyau(&p->to, v)) 711 return 1; 712 return 0; 713 714 case ARET: /* funny */ 715 if(v->type == REGRET) 716 return 2; 717 if(s != A) 718 return 1; 719 return 3; 720 721 case ACALL: /* funny */ 722 if(REGARG >= 0 && v->type == (uchar)REGARG) 723 return 2; 724 725 if(s != A) { 726 if(copysub(&p->to, v, s, 1)) 727 return 1; 728 return 0; 729 } 730 if(copyau(&p->to, v)) 731 return 4; 732 return 3; 733 } 734 return 0; 735 } 736 737 /* 738 * direct reference, 739 * could be set/use depending on 740 * semantics 741 */ 742 int 743 copyas(Addr *a, Addr *v) 744 { 745 if(a->type != v->type) 746 return 0; 747 if(regtyp(v)) 748 return 1; 749 if(v->type == D_AUTO || v->type == D_PARAM) 750 if(v->offset == a->offset) 751 return 1; 752 return 0; 753 } 754 755 /* 756 * either direct or indirect 757 */ 758 int 759 copyau(Addr *a, Addr *v) 760 { 761 762 if(copyas(a, v)) 763 return 1; 764 if(regtyp(v)) { 765 if(a->type-D_INDIR == v->type) 766 return 1; 767 if(a->index == v->type) 768 return 1; 769 } 770 return 0; 771 } 772 773 /* 774 * substitute s for v in a 775 * return failure to substitute 776 */ 777 int 778 copysub(Addr *a, Addr *v, Addr *s, int f) 779 { 780 int t; 781 782 if(copyas(a, v)) { 783 t = s->type; 784 if(t >= D_AX && t <= D_DI) { 785 if(f) 786 a->type = t; 787 } 788 return 0; 789 } 790 if(regtyp(v)) { 791 t = v->type; 792 if(a->type == t+D_INDIR) { 793 if(s->type == D_BP && a->index != D_NONE) 794 return 1; /* can't use BP-base with index */ 795 if(f) 796 a->type = s->type+D_INDIR; 797 // return 0; 798 } 799 if(a->index == t) { 800 if(f) 801 a->index = s->type; 802 return 0; 803 } 804 return 0; 805 } 806 return 0; 807 }