github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/src/cmd/9g/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 static int regzer(Addr *a); 37 static int subprop(Flow*); 38 static int copyprop(Flow*); 39 static int copy1(Addr*, Addr*, Flow*, int); 40 static int copyas(Addr*, Addr*); 41 static int copyau(Addr*, Addr*); 42 static int copysub(Addr*, Addr*, Addr*, int); 43 static int copysub1(Prog*, Addr*, Addr*, int); 44 static int copyau1(Prog *p, Addr *v); 45 46 static uint32 gactive; 47 48 void 49 peep(Prog *firstp) 50 { 51 Graph *g; 52 Flow *r, *r1; 53 Prog *p, *p1; 54 int t; 55 56 g = flowstart(firstp, sizeof(Flow)); 57 if(g == nil) 58 return; 59 gactive = 0; 60 61 loop1: 62 if(debug['P'] && debug['v']) 63 dumpit("loop1", g->start, 0); 64 65 t = 0; 66 for(r=g->start; r!=nil; r=r->link) { 67 p = r->prog; 68 // TODO(austin) Handle smaller moves. arm and amd64 69 // distinguish between moves that moves that *must* 70 // sign/zero extend and moves that don't care so they 71 // can eliminate moves that don't care without 72 // breaking moves that do care. This might let us 73 // simplify or remove the next peep loop, too. 74 if(p->as == AMOVD || p->as == AFMOVD) 75 if(regtyp(&p->to)) { 76 // Try to eliminate reg->reg moves 77 if(regtyp(&p->from)) 78 if(p->from.type == p->to.type) { 79 if(copyprop(r)) { 80 excise(r); 81 t++; 82 } else 83 if(subprop(r) && copyprop(r)) { 84 excise(r); 85 t++; 86 } 87 } 88 // Convert uses to $0 to uses of R0 and 89 // propagate R0 90 if(regzer(&p->from)) 91 if(p->to.type == D_REG) { 92 p->from.type = D_REG; 93 p->from.reg = REGZERO; 94 if(copyprop(r)) { 95 excise(r); 96 t++; 97 } else 98 if(subprop(r) && copyprop(r)) { 99 excise(r); 100 t++; 101 } 102 } 103 } 104 } 105 if(t) 106 goto loop1; 107 108 /* 109 * look for MOVB x,R; MOVB R,R (for small MOVs not handled above) 110 */ 111 for(r=g->start; r!=nil; r=r->link) { 112 p = r->prog; 113 switch(p->as) { 114 default: 115 continue; 116 case AMOVH: 117 case AMOVHZ: 118 case AMOVB: 119 case AMOVBZ: 120 case AMOVW: 121 case AMOVWZ: 122 if(p->to.type != D_REG) 123 continue; 124 break; 125 } 126 r1 = r->link; 127 if(r1 == nil) 128 continue; 129 p1 = r1->prog; 130 if(p1->as != p->as) 131 continue; 132 if(p1->from.type != D_REG || p1->from.reg != p->to.reg) 133 continue; 134 if(p1->to.type != D_REG || p1->to.reg != p->to.reg) 135 continue; 136 excise(r1); 137 } 138 139 if(debug['D'] > 1) 140 goto ret; /* allow following code improvement to be suppressed */ 141 142 /* 143 * look for OP x,y,R; CMP R, $0 -> OPCC x,y,R 144 * when OP can set condition codes correctly 145 */ 146 for(r=g->start; r!=nil; r=r->link) { 147 p = r->prog; 148 switch(p->as) { 149 case ACMP: 150 case ACMPW: /* always safe? */ 151 if(!regzer(&p->to)) 152 continue; 153 r1 = r->s1; 154 if(r1 == nil) 155 continue; 156 switch(r1->prog->as) { 157 default: 158 continue; 159 case ABCL: 160 case ABC: 161 /* the conditions can be complex and these are currently little used */ 162 continue; 163 case ABEQ: 164 case ABGE: 165 case ABGT: 166 case ABLE: 167 case ABLT: 168 case ABNE: 169 case ABVC: 170 case ABVS: 171 break; 172 } 173 r1 = r; 174 do 175 r1 = uniqp(r1); 176 while (r1 != nil && r1->prog->as == ANOP); 177 if(r1 == nil) 178 continue; 179 p1 = r1->prog; 180 if(p1->to.type != D_REG || p1->to.reg != p->from.reg) 181 continue; 182 switch(p1->as) { 183 case ASUB: 184 case AADD: 185 case AXOR: 186 case AOR: 187 /* irregular instructions */ 188 if(p1->from.type == D_CONST) 189 continue; 190 break; 191 } 192 switch(p1->as) { 193 default: 194 continue; 195 case AMOVW: 196 case AMOVD: 197 if(p1->from.type != D_REG) 198 continue; 199 continue; 200 case AANDCC: 201 case AANDNCC: 202 case AORCC: 203 case AORNCC: 204 case AXORCC: 205 case ASUBCC: 206 case ASUBECC: 207 case ASUBMECC: 208 case ASUBZECC: 209 case AADDCC: 210 case AADDCCC: 211 case AADDECC: 212 case AADDMECC: 213 case AADDZECC: 214 case ARLWMICC: 215 case ARLWNMCC: 216 /* don't deal with floating point instructions for now */ 217 /* 218 case AFABS: 219 case AFADD: 220 case AFADDS: 221 case AFCTIW: 222 case AFCTIWZ: 223 case AFDIV: 224 case AFDIVS: 225 case AFMADD: 226 case AFMADDS: 227 case AFMOVD: 228 case AFMSUB: 229 case AFMSUBS: 230 case AFMUL: 231 case AFMULS: 232 case AFNABS: 233 case AFNEG: 234 case AFNMADD: 235 case AFNMADDS: 236 case AFNMSUB: 237 case AFNMSUBS: 238 case AFRSP: 239 case AFSUB: 240 case AFSUBS: 241 case ACNTLZW: 242 case AMTFSB0: 243 case AMTFSB1: 244 */ 245 case AADD: 246 case AADDV: 247 case AADDC: 248 case AADDCV: 249 case AADDME: 250 case AADDMEV: 251 case AADDE: 252 case AADDEV: 253 case AADDZE: 254 case AADDZEV: 255 case AAND: 256 case AANDN: 257 case ADIVW: 258 case ADIVWV: 259 case ADIVWU: 260 case ADIVWUV: 261 case ADIVD: 262 case ADIVDV: 263 case ADIVDU: 264 case ADIVDUV: 265 case AEQV: 266 case AEXTSB: 267 case AEXTSH: 268 case AEXTSW: 269 case AMULHW: 270 case AMULHWU: 271 case AMULLW: 272 case AMULLWV: 273 case AMULHD: 274 case AMULHDU: 275 case AMULLD: 276 case AMULLDV: 277 case ANAND: 278 case ANEG: 279 case ANEGV: 280 case ANOR: 281 case AOR: 282 case AORN: 283 case AREM: 284 case AREMV: 285 case AREMU: 286 case AREMUV: 287 case AREMD: 288 case AREMDV: 289 case AREMDU: 290 case AREMDUV: 291 case ARLWMI: 292 case ARLWNM: 293 case ASLW: 294 case ASRAW: 295 case ASRW: 296 case ASLD: 297 case ASRAD: 298 case ASRD: 299 case ASUB: 300 case ASUBV: 301 case ASUBC: 302 case ASUBCV: 303 case ASUBME: 304 case ASUBMEV: 305 case ASUBE: 306 case ASUBEV: 307 case ASUBZE: 308 case ASUBZEV: 309 case AXOR: 310 t = variant2as(p1->as, as2variant(p1->as) | V_CC); 311 break; 312 } 313 if(debug['D']) 314 print("cmp %P; %P -> ", p1, p); 315 p1->as = t; 316 if(debug['D']) 317 print("%P\n", p1); 318 excise(r); 319 continue; 320 } 321 } 322 323 ret: 324 flowend(g); 325 } 326 327 void 328 excise(Flow *r) 329 { 330 Prog *p, *l; 331 332 p = r->prog; 333 if(debug['P'] && debug['v']) 334 print("%P ===delete===\n", p); 335 l = p->link; 336 *p = zprog; 337 p->as = ANOP; 338 p->link = l; 339 ostats.ndelmov++; 340 } 341 342 /* 343 * regzer returns 1 if a's value is 0 (a is R0 or $0) 344 */ 345 static int 346 regzer(Addr *a) 347 { 348 if(a->type == D_CONST) 349 if(a->sym == nil && a->reg == NREG) 350 if(a->offset == 0) 351 return 1; 352 if(a->type == D_REG) 353 if(a->reg == REGZERO) 354 return 1; 355 return 0; 356 } 357 358 int 359 regtyp(Adr *a) 360 { 361 switch(a->type) { 362 default: 363 return 0; 364 case D_REG: 365 if(a->reg == REGZERO) 366 return 0; 367 case D_FREG: 368 return 1; 369 } 370 } 371 372 /* 373 * the idea is to substitute 374 * one register for another 375 * from one MOV to another 376 * MOV a, R1 377 * ADD b, R1 / no use of R2 378 * MOV R1, R2 379 * would be converted to 380 * MOV a, R2 381 * ADD b, R2 382 * MOV R2, R1 383 * hopefully, then the former or latter MOV 384 * will be eliminated by copy propagation. 385 * 386 * r0 (the argument, not the register) is the MOV at the end of the 387 * above sequences. This returns 1 if it modified any instructions. 388 */ 389 static int 390 subprop(Flow *r0) 391 { 392 Prog *p; 393 Addr *v1, *v2; 394 Flow *r; 395 int t; 396 ProgInfo info; 397 398 p = r0->prog; 399 v1 = &p->from; 400 if(!regtyp(v1)) 401 return 0; 402 v2 = &p->to; 403 if(!regtyp(v2)) 404 return 0; 405 for(r=uniqp(r0); r!=nil; r=uniqp(r)) { 406 if(uniqs(r) == nil) 407 break; 408 p = r->prog; 409 if(p->as == AVARDEF || p->as == AVARKILL) 410 continue; 411 proginfo(&info, p); 412 if(info.flags & Call) 413 return 0; 414 415 if((info.flags & (RightRead|RightWrite)) == RightWrite) { 416 if(p->to.type == v1->type) 417 if(p->to.reg == v1->reg) 418 goto gotit; 419 } 420 421 if(copyau(&p->from, v2) || 422 copyau1(p, v2) || 423 copyau(&p->to, v2)) 424 break; 425 if(copysub(&p->from, v1, v2, 0) || 426 copysub1(p, v1, v2, 0) || 427 copysub(&p->to, v1, v2, 0)) 428 break; 429 } 430 return 0; 431 432 gotit: 433 copysub(&p->to, v1, v2, 1); 434 if(debug['P']) { 435 print("gotit: %D->%D\n%P", v1, v2, r->prog); 436 if(p->from.type == v2->type) 437 print(" excise"); 438 print("\n"); 439 } 440 for(r=uniqs(r); r!=r0; r=uniqs(r)) { 441 p = r->prog; 442 copysub(&p->from, v1, v2, 1); 443 copysub1(p, v1, v2, 1); 444 copysub(&p->to, v1, v2, 1); 445 if(debug['P']) 446 print("%P\n", r->prog); 447 } 448 t = v1->reg; 449 v1->reg = v2->reg; 450 v2->reg = t; 451 if(debug['P']) 452 print("%P last\n", r->prog); 453 return 1; 454 } 455 456 /* 457 * The idea is to remove redundant copies. 458 * v1->v2 F=0 459 * (use v2 s/v2/v1/)* 460 * set v1 F=1 461 * use v2 return fail (v1->v2 move must remain) 462 * ----------------- 463 * v1->v2 F=0 464 * (use v2 s/v2/v1/)* 465 * set v1 F=1 466 * set v2 return success (caller can remove v1->v2 move) 467 */ 468 static int 469 copyprop(Flow *r0) 470 { 471 Prog *p; 472 Addr *v1, *v2; 473 474 p = r0->prog; 475 v1 = &p->from; 476 v2 = &p->to; 477 if(copyas(v1, v2)) { 478 if(debug['P']) 479 print("eliminating self-move\n", r0->prog); 480 return 1; 481 } 482 gactive++; 483 if(debug['P']) 484 print("trying to eliminate %D->%D move from:\n%P\n", v1, v2, r0->prog); 485 return copy1(v1, v2, r0->s1, 0); 486 } 487 488 // copy1 replaces uses of v2 with v1 starting at r and returns 1 if 489 // all uses were rewritten. 490 static int 491 copy1(Addr *v1, Addr *v2, Flow *r, int f) 492 { 493 int t; 494 Prog *p; 495 496 if(r->active == gactive) { 497 if(debug['P']) 498 print("act set; return 1\n"); 499 return 1; 500 } 501 r->active = gactive; 502 if(debug['P']) 503 print("copy1 replace %D with %D f=%d\n", v2, v1, f); 504 for(; r != nil; r = r->s1) { 505 p = r->prog; 506 if(debug['P']) 507 print("%P", p); 508 if(!f && uniqp(r) == nil) { 509 // Multiple predecessors; conservatively 510 // assume v1 was set on other path 511 f = 1; 512 if(debug['P']) 513 print("; merge; f=%d", f); 514 } 515 t = copyu(p, v2, nil); 516 switch(t) { 517 case 2: /* rar, can't split */ 518 if(debug['P']) 519 print("; %D rar; return 0\n", v2); 520 return 0; 521 522 case 3: /* set */ 523 if(debug['P']) 524 print("; %D set; return 1\n", v2); 525 return 1; 526 527 case 1: /* used, substitute */ 528 case 4: /* use and set */ 529 if(f) { 530 if(!debug['P']) 531 return 0; 532 if(t == 4) 533 print("; %D used+set and f=%d; return 0\n", v2, f); 534 else 535 print("; %D used and f=%d; return 0\n", v2, f); 536 return 0; 537 } 538 if(copyu(p, v2, v1)) { 539 if(debug['P']) 540 print("; sub fail; return 0\n"); 541 return 0; 542 } 543 if(debug['P']) 544 print("; sub %D->%D\n => %P", v2, v1, p); 545 if(t == 4) { 546 if(debug['P']) 547 print("; %D used+set; return 1\n", v2); 548 return 1; 549 } 550 break; 551 } 552 if(!f) { 553 t = copyu(p, v1, nil); 554 if(!f && (t == 2 || t == 3 || t == 4)) { 555 f = 1; 556 if(debug['P']) 557 print("; %D set and !f; f=%d", v1, f); 558 } 559 } 560 if(debug['P']) 561 print("\n"); 562 if(r->s2) 563 if(!copy1(v1, v2, r->s2, f)) 564 return 0; 565 } 566 return 1; 567 } 568 569 // If s==nil, copyu returns the set/use of v in p; otherwise, it 570 // modifies p to replace reads of v with reads of s and returns 0 for 571 // success or non-zero for failure. 572 // 573 // If s==nil, copy returns one of the following values: 574 // 1 if v only used 575 // 2 if v is set and used in one address (read-alter-rewrite; 576 // can't substitute) 577 // 3 if v is only set 578 // 4 if v is set in one address and used in another (so addresses 579 // can be rewritten independently) 580 // 0 otherwise (not touched) 581 int 582 copyu(Prog *p, Addr *v, Addr *s) 583 { 584 if(p->from3.type != D_NONE) 585 // 9g never generates a from3 586 print("copyu: from3 (%D) not implemented\n", p->from3); 587 588 switch(p->as) { 589 590 default: 591 print("copyu: can't find %A\n", p->as); 592 return 2; 593 594 case ANOP: /* read p->from, write p->to */ 595 case AMOVH: 596 case AMOVHZ: 597 case AMOVB: 598 case AMOVBZ: 599 case AMOVW: 600 case AMOVWZ: 601 case AMOVD: 602 603 case ANEG: 604 case ANEGCC: 605 case AADDME: 606 case AADDMECC: 607 case AADDZE: 608 case AADDZECC: 609 case ASUBME: 610 case ASUBMECC: 611 case ASUBZE: 612 case ASUBZECC: 613 614 case AFCTIW: 615 case AFCTIWZ: 616 case AFCTID: 617 case AFCTIDZ: 618 case AFCFID: 619 case AFCFIDCC: 620 case AFMOVS: 621 case AFMOVD: 622 case AFRSP: 623 case AFNEG: 624 case AFNEGCC: 625 if(s != nil) { 626 if(copysub(&p->from, v, s, 1)) 627 return 1; 628 // Update only indirect uses of v in p->to 629 if(!copyas(&p->to, v)) 630 if(copysub(&p->to, v, s, 1)) 631 return 1; 632 return 0; 633 } 634 if(copyas(&p->to, v)) { 635 // Fix up implicit from 636 if(p->from.type == D_NONE) 637 p->from = p->to; 638 if(copyau(&p->from, v)) 639 return 4; 640 return 3; 641 } 642 if(copyau(&p->from, v)) 643 return 1; 644 if(copyau(&p->to, v)) 645 // p->to only indirectly uses v 646 return 1; 647 return 0; 648 649 case AMOVBU: /* rar p->from, write p->to or read p->from, rar p->to */ 650 case AMOVBZU: 651 case AMOVHU: 652 case AMOVHZU: 653 case AMOVWZU: 654 case AMOVDU: 655 if(p->from.type == D_OREG) { 656 if(copyas(&p->from, v)) 657 // No s!=nil check; need to fail 658 // anyway in that case 659 return 2; 660 if(s != nil) { 661 if(copysub(&p->to, v, s, 1)) 662 return 1; 663 return 0; 664 } 665 if(copyas(&p->to, v)) 666 return 3; 667 } else if (p->to.type == D_OREG) { 668 if(copyas(&p->to, v)) 669 return 2; 670 if(s != nil) { 671 if(copysub(&p->from, v, s, 1)) 672 return 1; 673 return 0; 674 } 675 if(copyau(&p->from, v)) 676 return 1; 677 } else { 678 print("copyu: bad %P\n", p); 679 } 680 return 0; 681 682 case ARLWMI: /* read p->from, read p->reg, rar p->to */ 683 case ARLWMICC: 684 if(copyas(&p->to, v)) 685 return 2; 686 /* fall through */ 687 688 case AADD: /* read p->from, read p->reg, write p->to */ 689 case AADDC: 690 case AADDE: 691 case ASUB: 692 case ASLW: 693 case ASRW: 694 case ASRAW: 695 case ASLD: 696 case ASRD: 697 case ASRAD: 698 case AOR: 699 case AORCC: 700 case AORN: 701 case AORNCC: 702 case AAND: 703 case AANDCC: 704 case AANDN: 705 case AANDNCC: 706 case ANAND: 707 case ANANDCC: 708 case ANOR: 709 case ANORCC: 710 case AXOR: 711 case AMULHW: 712 case AMULHWU: 713 case AMULLW: 714 case AMULLD: 715 case ADIVW: 716 case ADIVD: 717 case ADIVWU: 718 case ADIVDU: 719 case AREM: 720 case AREMU: 721 case AREMD: 722 case AREMDU: 723 case ARLWNM: 724 case ARLWNMCC: 725 726 case AFADDS: 727 case AFADD: 728 case AFSUBS: 729 case AFSUB: 730 case AFMULS: 731 case AFMUL: 732 case AFDIVS: 733 case AFDIV: 734 if(s != nil) { 735 if(copysub(&p->from, v, s, 1)) 736 return 1; 737 if(copysub1(p, v, s, 1)) 738 return 1; 739 // Update only indirect uses of v in p->to 740 if(!copyas(&p->to, v)) 741 if(copysub(&p->to, v, s, 1)) 742 return 1; 743 return 0; 744 } 745 if(copyas(&p->to, v)) { 746 if(p->reg == NREG) 747 // Fix up implicit reg (e.g., ADD 748 // R3,R4 -> ADD R3,R4,R4) so we can 749 // update reg and to separately. 750 p->reg = p->to.reg; 751 if(copyau(&p->from, v)) 752 return 4; 753 if(copyau1(p, v)) 754 return 4; 755 return 3; 756 } 757 if(copyau(&p->from, v)) 758 return 1; 759 if(copyau1(p, v)) 760 return 1; 761 if(copyau(&p->to, v)) 762 return 1; 763 return 0; 764 765 case ABEQ: 766 case ABGT: 767 case ABGE: 768 case ABLT: 769 case ABLE: 770 case ABNE: 771 case ABVC: 772 case ABVS: 773 return 0; 774 775 case ACHECKNIL: /* read p->from */ 776 case ACMP: /* read p->from, read p->to */ 777 case ACMPU: 778 case ACMPW: 779 case ACMPWU: 780 case AFCMPO: 781 case AFCMPU: 782 if(s != nil) { 783 if(copysub(&p->from, v, s, 1)) 784 return 1; 785 return copysub(&p->to, v, s, 1); 786 } 787 if(copyau(&p->from, v)) 788 return 1; 789 if(copyau(&p->to, v)) 790 return 1; 791 return 0; 792 793 case ABR: /* read p->to */ 794 // 9g never generates a branch to a GPR (this isn't 795 // even a normal instruction; liblink turns it in to a 796 // mov and a branch). 797 if(s != nil) { 798 if(copysub(&p->to, v, s, 1)) 799 return 1; 800 return 0; 801 } 802 if(copyau(&p->to, v)) 803 return 1; 804 return 0; 805 806 case ARETURN: /* funny */ 807 if(s != nil) 808 return 0; 809 // All registers die at this point, so claim 810 // everything is set (and not used). 811 return 3; 812 813 case ABL: /* funny */ 814 if(v->type == D_REG) { 815 if(v->reg <= REGEXT && v->reg > exregoffset) 816 return 2; 817 if(v->reg == REGARG) 818 return 2; 819 } 820 if(v->type == D_FREG) { 821 if(v->reg <= FREGEXT && v->reg > exfregoffset) 822 return 2; 823 } 824 if(p->from.type == D_REG && v->type == D_REG && p->from.reg == v->reg) 825 return 2; 826 827 if(s != nil) { 828 if(copysub(&p->to, v, s, 1)) 829 return 1; 830 return 0; 831 } 832 if(copyau(&p->to, v)) 833 return 4; 834 return 3; 835 836 case ADUFFZERO: 837 // R0 is zero, used by DUFFZERO, cannot be substituted. 838 // R3 is ptr to memory, used and set, cannot be substituted. 839 if(v->type == D_REG) { 840 if(v->reg == 0) 841 return 1; 842 if(v->reg == 3) 843 return 2; 844 } 845 return 0; 846 847 case ADUFFCOPY: 848 // R3, R4 are ptr to src, dst, used and set, cannot be substituted. 849 // R5 is scratch, set by DUFFCOPY, cannot be substituted. 850 if(v->type == D_REG) { 851 if(v->reg == 3 || v->reg == 4) 852 return 2; 853 if(v->reg == 5) 854 return 3; 855 } 856 return 0; 857 858 case ATEXT: /* funny */ 859 if(v->type == D_REG) 860 if(v->reg == REGARG) 861 return 3; 862 return 0; 863 864 case APCDATA: 865 case AFUNCDATA: 866 case AVARDEF: 867 case AVARKILL: 868 return 0; 869 } 870 } 871 872 int 873 a2type(Prog *p) 874 { 875 ProgInfo info; 876 proginfo(&info, p); 877 if(info.flags & (SizeB|SizeW|SizeL|SizeQ)) 878 return D_REG; 879 if(info.flags & (SizeF|SizeD)) 880 return D_FREG; 881 return D_NONE; 882 } 883 884 // copyas returns 1 if a and v address the same register. 885 // 886 // If a is the from operand, this means this operation reads the 887 // register in v. If a is the to operand, this means this operation 888 // writes the register in v. 889 static int 890 copyas(Addr *a, Addr *v) 891 { 892 if(regtyp(v)) 893 if(a->type == v->type) 894 if(a->reg == v->reg) 895 return 1; 896 return 0; 897 } 898 899 // copyau returns 1 if a either directly or indirectly addresses the 900 // same register as v. 901 // 902 // If a is the from operand, this means this operation reads the 903 // register in v. If a is the to operand, this means the operation 904 // either reads or writes the register in v (if !copyas(a, v), then 905 // the operation reads the register in v). 906 static int 907 copyau(Addr *a, Addr *v) 908 { 909 if(copyas(a, v)) 910 return 1; 911 if(v->type == D_REG) 912 if(a->type == D_OREG || (a->type == D_CONST && a->reg != NREG)) 913 if(v->reg == a->reg) 914 return 1; 915 return 0; 916 } 917 918 // copyau1 returns 1 if p->reg references the same register as v and v 919 // is a direct reference. 920 static int 921 copyau1(Prog *p, Addr *v) 922 { 923 if(regtyp(v)) 924 if(p->from.type == v->type || p->to.type == v->type) 925 if(p->reg == v->reg) { 926 // Whether p->reg is a GPR or an FPR is 927 // implied by the instruction (both are 928 // numbered from 0). But the type should 929 // match v->type. Sanity check this. 930 if(a2type(p) != v->type) 931 print("botch a2type %P\n", p); 932 return 1; 933 } 934 return 0; 935 } 936 937 // copysub replaces v with s in a if f!=0 or indicates it if could if f==0. 938 // Returns 1 on failure to substitute (it always succeeds on ppc64). 939 static int 940 copysub(Addr *a, Addr *v, Addr *s, int f) 941 { 942 if(f) 943 if(copyau(a, v)) 944 a->reg = s->reg; 945 return 0; 946 } 947 948 // copysub1 replaces v with s in p1->reg if f!=0 or indicates if it could if f==0. 949 // Returns 1 on failure to substitute (it always succeeds on ppc64). 950 static int 951 copysub1(Prog *p1, Addr *v, Addr *s, int f) 952 { 953 if(f) 954 if(copyau1(p1, v)) 955 p1->reg = s->reg; 956 return 0; 957 } 958 959 int 960 sameaddr(Addr *a, Addr *v) 961 { 962 if(a->type != v->type) 963 return 0; 964 if(regtyp(v) && a->reg == v->reg) 965 return 1; 966 if(v->type == D_AUTO || v->type == D_PARAM) 967 if(v->offset == a->offset) 968 return 1; 969 return 0; 970 } 971 972 int 973 smallindir(Addr *a, Addr *reg) 974 { 975 return reg->type == D_REG && a->type == D_OREG && 976 a->reg == reg->reg && 977 0 <= a->offset && a->offset < 4096; 978 } 979 980 int 981 stackaddr(Addr *a) 982 { 983 return a->type == D_REG && a->reg == REGSP; 984 }