github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/reg.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/gc/reg.go 2 3 // Derived from Inferno utils/6c/reg.c 4 // http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c 5 // 6 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 7 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 8 // Portions Copyright © 1997-1999 Vita Nuova Limited 9 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 10 // Portions Copyright © 2004,2006 Bruce Ellis 11 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 12 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 13 // Portions Copyright © 2009 The Go Authors. All rights reserved. 14 // 15 // Permission is hereby granted, free of charge, to any person obtaining a copy 16 // of this software and associated documentation files (the "Software"), to deal 17 // in the Software without restriction, including without limitation the rights 18 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 // copies of the Software, and to permit persons to whom the Software is 20 // furnished to do so, subject to the following conditions: 21 // 22 // The above copyright notice and this permission notice shall be included in 23 // all copies or substantial portions of the Software. 24 // 25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 31 // THE SOFTWARE. 32 33 package gc 34 35 import ( 36 "bytes" 37 "rsc.io/tmp/bootstrap/internal/obj" 38 "fmt" 39 "sort" 40 "strings" 41 ) 42 43 // A Var represents a single variable that may be stored in a register. 44 // That variable may itself correspond to a hardware register, 45 // to represent the use of registers in the unoptimized instruction stream. 46 type Var struct { 47 offset int64 48 node *Node 49 nextinnode *Var 50 width int 51 id int // index in vars 52 name int8 53 etype int8 54 addr int8 55 } 56 57 // Bits represents a set of Vars, stored as a bit set of var numbers 58 // (the index in vars, or equivalently v.id). 59 type Bits struct { 60 b [BITS]uint64 61 } 62 63 const ( 64 BITS = 3 65 NVAR = BITS * 64 66 ) 67 68 var ( 69 vars [NVAR]Var // variables under consideration 70 nvar int // number of vars 71 72 regbits uint64 // bits for hardware registers 73 74 zbits Bits // zero 75 externs Bits // global variables 76 params Bits // function parameters and results 77 ivar Bits // function parameters (inputs) 78 ovar Bits // function results (outputs) 79 consts Bits // constant values 80 addrs Bits // variables with address taken 81 ) 82 83 // A Reg is a wrapper around a single Prog (one instruction) that holds 84 // register optimization information while the optimizer runs. 85 // r->prog is the instruction. 86 type Reg struct { 87 set Bits // regopt variables written by this instruction. 88 use1 Bits // regopt variables read by prog->from. 89 use2 Bits // regopt variables read by prog->to. 90 91 // refahead/refbehind are the regopt variables whose current 92 // value may be used in the following/preceding instructions 93 // up to a CALL (or the value is clobbered). 94 refbehind Bits 95 refahead Bits 96 97 // calahead/calbehind are similar, but for variables in 98 // instructions that are reachable after hitting at least one 99 // CALL. 100 calbehind Bits 101 calahead Bits 102 103 regdiff Bits 104 act Bits 105 regu uint64 // register used bitmap 106 } 107 108 // A Rgn represents a single regopt variable over a region of code 109 // where a register could potentially be dedicated to that variable. 110 // The code encompassed by a Rgn is defined by the flow graph, 111 // starting at enter, flood-filling forward while varno is refahead 112 // and backward while varno is refbehind, and following branches. 113 // A single variable may be represented by multiple disjoint Rgns and 114 // each Rgn may choose a different register for that variable. 115 // Registers are allocated to regions greedily in order of descending 116 // cost. 117 type Rgn struct { 118 enter *Flow 119 cost int16 120 varno int16 121 regno int16 122 } 123 124 // The Plan 9 C compilers used a limit of 600 regions, 125 // but the yacc-generated parser in y.go has 3100 regions. 126 // We set MaxRgn large enough to handle that. 127 // There's not a huge cost to having too many regions: 128 // the main processing traces the live area for each variable, 129 // which is limited by the number of variables times the area, 130 // not the raw region count. If there are many regions, they 131 // are almost certainly small and easy to trace. 132 // The only operation that scales with region count is the 133 // sorting by cost, which uses sort.Sort and is therefore 134 // guaranteed n log n. 135 const MaxRgn = 6000 136 137 var ( 138 region []Rgn 139 nregion int 140 ) 141 142 type rcmp []Rgn 143 144 func (x rcmp) Len() int { 145 return len(x) 146 } 147 148 func (x rcmp) Swap(i, j int) { 149 x[i], x[j] = x[j], x[i] 150 } 151 152 func (x rcmp) Less(i, j int) bool { 153 p1 := &x[i] 154 p2 := &x[j] 155 if p1.cost != p2.cost { 156 return int(p2.cost)-int(p1.cost) < 0 157 } 158 if p1.varno != p2.varno { 159 return int(p2.varno)-int(p1.varno) < 0 160 } 161 if p1.enter != p2.enter { 162 return int(p2.enter.Id-p1.enter.Id) < 0 163 } 164 return false 165 } 166 167 func setaddrs(bit Bits) { 168 var i int 169 var n int 170 var v *Var 171 var node *Node 172 173 for bany(&bit) { 174 // convert each bit to a variable 175 i = bnum(bit) 176 177 node = vars[i].node 178 n = int(vars[i].name) 179 biclr(&bit, uint(i)) 180 181 // disable all pieces of that variable 182 for i = 0; i < nvar; i++ { 183 v = &vars[i] 184 if v.node == node && int(v.name) == n { 185 v.addr = 2 186 } 187 } 188 } 189 } 190 191 var regnodes [64]*Node 192 193 func walkvardef(n *Node, f *Flow, active int) { 194 var f1 *Flow 195 var bn int 196 var v *Var 197 198 for f1 = f; f1 != nil; f1 = f1.S1 { 199 if f1.Active == int32(active) { 200 break 201 } 202 f1.Active = int32(active) 203 if f1.Prog.As == obj.AVARKILL && f1.Prog.To.Node == n { 204 break 205 } 206 for v, _ = n.Opt.(*Var); v != nil; v = v.nextinnode { 207 bn = v.id 208 biset(&(f1.Data.(*Reg)).act, uint(bn)) 209 } 210 211 if f1.Prog.As == obj.ACALL { 212 break 213 } 214 } 215 216 for f2 := f; f2 != f1; f2 = f2.S1 { 217 if f2.S2 != nil { 218 walkvardef(n, f2.S2, active) 219 } 220 } 221 } 222 223 /* 224 * add mov b,rn 225 * just after r 226 */ 227 func addmove(r *Flow, bn int, rn int, f int) { 228 p1 := Ctxt.NewProg() 229 Clearp(p1) 230 p1.Pc = 9999 231 232 p := r.Prog 233 p1.Link = p.Link 234 p.Link = p1 235 p1.Lineno = p.Lineno 236 237 v := &vars[bn] 238 239 a := &p1.To 240 a.Offset = v.offset 241 a.Etype = uint8(v.etype) 242 a.Type = obj.TYPE_MEM 243 a.Name = v.name 244 a.Node = v.node 245 a.Sym = Linksym(v.node.Sym) 246 247 /* NOTE(rsc): 9g did 248 if(a->etype == TARRAY) 249 a->type = TYPE_ADDR; 250 else if(a->sym == nil) 251 a->type = TYPE_CONST; 252 */ 253 p1.As = int16(Thearch.Optoas(OAS, Types[uint8(v.etype)])) 254 255 // TODO(rsc): Remove special case here. 256 if (Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && v.etype == TBOOL { 257 p1.As = int16(Thearch.Optoas(OAS, Types[TUINT8])) 258 } 259 p1.From.Type = obj.TYPE_REG 260 p1.From.Reg = int16(rn) 261 p1.From.Name = obj.NAME_NONE 262 if f == 0 { 263 p1.From = *a 264 *a = obj.Addr{} 265 a.Type = obj.TYPE_REG 266 a.Reg = int16(rn) 267 } 268 269 if Debug['R'] != 0 && Debug['v'] != 0 { 270 fmt.Printf("%v ===add=== %v\n", p, p1) 271 } 272 Ostats.Nspill++ 273 } 274 275 func overlap_reg(o1 int64, w1 int, o2 int64, w2 int) bool { 276 t1 := o1 + int64(w1) 277 t2 := o2 + int64(w2) 278 279 if t1 <= o2 || t2 <= o1 { 280 return false 281 } 282 283 return true 284 } 285 286 func mkvar(f *Flow, a *obj.Addr) Bits { 287 /* 288 * mark registers used 289 */ 290 if a.Type == obj.TYPE_NONE { 291 return zbits 292 } 293 294 r := f.Data.(*Reg) 295 r.use1.b[0] |= Thearch.Doregbits(int(a.Index)) // TODO: Use RtoB 296 297 var n int 298 switch a.Type { 299 default: 300 regu := Thearch.Doregbits(int(a.Reg)) | Thearch.RtoB(int(a.Reg)) // TODO: Use RtoB 301 if regu == 0 { 302 return zbits 303 } 304 bit := zbits 305 bit.b[0] = regu 306 return bit 307 308 // TODO(rsc): Remove special case here. 309 case obj.TYPE_ADDR: 310 var bit Bits 311 if Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' { 312 goto memcase 313 } 314 a.Type = obj.TYPE_MEM 315 bit = mkvar(f, a) 316 setaddrs(bit) 317 a.Type = obj.TYPE_ADDR 318 Ostats.Naddr++ 319 return zbits 320 321 memcase: 322 fallthrough 323 324 case obj.TYPE_MEM: 325 if r != nil { 326 r.use1.b[0] |= Thearch.RtoB(int(a.Reg)) 327 } 328 329 /* NOTE: 5g did 330 if(r->f.prog->scond & (C_PBIT|C_WBIT)) 331 r->set.b[0] |= RtoB(a->reg); 332 */ 333 switch a.Name { 334 default: 335 // Note: This case handles NAME_EXTERN and NAME_STATIC. 336 // We treat these as requiring eager writes to memory, due to 337 // the possibility of a fault handler looking at them, so there is 338 // not much point in registerizing the loads. 339 // If we later choose the set of candidate variables from a 340 // larger list, these cases could be deprioritized instead of 341 // removed entirely. 342 return zbits 343 344 case obj.NAME_PARAM, 345 obj.NAME_AUTO: 346 n = int(a.Name) 347 } 348 } 349 350 node, _ := a.Node.(*Node) 351 if node == nil || node.Op != ONAME || node.Orig == nil { 352 return zbits 353 } 354 node = node.Orig 355 if node.Orig != node { 356 Fatal("%v: bad node", Ctxt.Dconv(a)) 357 } 358 if node.Sym == nil || node.Sym.Name[0] == '.' { 359 return zbits 360 } 361 et := int(a.Etype) 362 o := a.Offset 363 w := a.Width 364 if w < 0 { 365 Fatal("bad width %d for %v", w, Ctxt.Dconv(a)) 366 } 367 368 flag := 0 369 var v *Var 370 for i := 0; i < nvar; i++ { 371 v = &vars[i] 372 if v.node == node && int(v.name) == n { 373 if v.offset == o { 374 if int(v.etype) == et { 375 if int64(v.width) == w { 376 // TODO(rsc): Remove special case for arm here. 377 if flag == 0 || Thearch.Thechar != '5' { 378 return blsh(uint(i)) 379 } 380 } 381 } 382 } 383 384 // if they overlap, disable both 385 if overlap_reg(v.offset, v.width, o, int(w)) { 386 // print("disable overlap %s %d %d %d %d, %E != %E\n", s->name, v->offset, v->width, o, w, v->etype, et); 387 v.addr = 1 388 389 flag = 1 390 } 391 } 392 } 393 394 switch et { 395 case 0, TFUNC: 396 return zbits 397 } 398 399 if nvar >= NVAR { 400 if Debug['w'] > 1 && node != nil { 401 Fatal("variable not optimized: %v", Nconv(node, obj.FmtSharp)) 402 } 403 if Debug['v'] > 0 { 404 Warn("variable not optimized: %v", Nconv(node, obj.FmtSharp)) 405 } 406 407 // If we're not tracking a word in a variable, mark the rest as 408 // having its address taken, so that we keep the whole thing 409 // live at all calls. otherwise we might optimize away part of 410 // a variable but not all of it. 411 var v *Var 412 for i := 0; i < nvar; i++ { 413 v = &vars[i] 414 if v.node == node { 415 v.addr = 1 416 } 417 } 418 419 return zbits 420 } 421 422 i := nvar 423 nvar++ 424 v = &vars[i] 425 v.id = i 426 v.offset = o 427 v.name = int8(n) 428 v.etype = int8(et) 429 v.width = int(w) 430 v.addr = int8(flag) // funny punning 431 v.node = node 432 433 // node->opt is the head of a linked list 434 // of Vars within the given Node, so that 435 // we can start at a Var and find all the other 436 // Vars in the same Go variable. 437 v.nextinnode, _ = node.Opt.(*Var) 438 439 node.Opt = v 440 441 bit := blsh(uint(i)) 442 if n == obj.NAME_EXTERN || n == obj.NAME_STATIC { 443 for z := 0; z < BITS; z++ { 444 externs.b[z] |= bit.b[z] 445 } 446 } 447 if n == obj.NAME_PARAM { 448 for z := 0; z < BITS; z++ { 449 params.b[z] |= bit.b[z] 450 } 451 } 452 453 if node.Class == PPARAM { 454 for z := 0; z < BITS; z++ { 455 ivar.b[z] |= bit.b[z] 456 } 457 } 458 if node.Class == PPARAMOUT { 459 for z := 0; z < BITS; z++ { 460 ovar.b[z] |= bit.b[z] 461 } 462 } 463 464 // Treat values with their address taken as live at calls, 465 // because the garbage collector's liveness analysis in ../gc/plive.c does. 466 // These must be consistent or else we will elide stores and the garbage 467 // collector will see uninitialized data. 468 // The typical case where our own analysis is out of sync is when the 469 // node appears to have its address taken but that code doesn't actually 470 // get generated and therefore doesn't show up as an address being 471 // taken when we analyze the instruction stream. 472 // One instance of this case is when a closure uses the same name as 473 // an outer variable for one of its own variables declared with :=. 474 // The parser flags the outer variable as possibly shared, and therefore 475 // sets addrtaken, even though it ends up not being actually shared. 476 // If we were better about _ elision, _ = &x would suffice too. 477 // The broader := in a closure problem is mentioned in a comment in 478 // closure.c:/^typecheckclosure and dcl.c:/^oldname. 479 if node.Addrtaken { 480 v.addr = 1 481 } 482 483 // Disable registerization for globals, because: 484 // (1) we might panic at any time and we want the recovery code 485 // to see the latest values (issue 1304). 486 // (2) we don't know what pointers might point at them and we want 487 // loads via those pointers to see updated values and vice versa (issue 7995). 488 // 489 // Disable registerization for results if using defer, because the deferred func 490 // might recover and return, causing the current values to be used. 491 if node.Class == PEXTERN || (Hasdefer != 0 && node.Class == PPARAMOUT) { 492 v.addr = 1 493 } 494 495 if Debug['R'] != 0 { 496 fmt.Printf("bit=%2d et=%v w=%d+%d %v %v flag=%d\n", i, Econv(int(et), 0), o, w, Nconv(node, obj.FmtSharp), Ctxt.Dconv(a), v.addr) 497 } 498 Ostats.Nvar++ 499 500 return bit 501 } 502 503 var change int 504 505 func prop(f *Flow, ref Bits, cal Bits) { 506 var f1 *Flow 507 var r1 *Reg 508 var z int 509 var i int 510 var v *Var 511 var v1 *Var 512 513 for f1 = f; f1 != nil; f1 = f1.P1 { 514 r1 = f1.Data.(*Reg) 515 for z = 0; z < BITS; z++ { 516 ref.b[z] |= r1.refahead.b[z] 517 if ref.b[z] != r1.refahead.b[z] { 518 r1.refahead.b[z] = ref.b[z] 519 change = 1 520 } 521 522 cal.b[z] |= r1.calahead.b[z] 523 if cal.b[z] != r1.calahead.b[z] { 524 r1.calahead.b[z] = cal.b[z] 525 change = 1 526 } 527 } 528 529 switch f1.Prog.As { 530 case obj.ACALL: 531 if Noreturn(f1.Prog) { 532 break 533 } 534 535 // Mark all input variables (ivar) as used, because that's what the 536 // liveness bitmaps say. The liveness bitmaps say that so that a 537 // panic will not show stale values in the parameter dump. 538 // Mark variables with a recent VARDEF (r1->act) as used, 539 // so that the optimizer flushes initializations to memory, 540 // so that if a garbage collection happens during this CALL, 541 // the collector will see initialized memory. Again this is to 542 // match what the liveness bitmaps say. 543 for z = 0; z < BITS; z++ { 544 cal.b[z] |= ref.b[z] | externs.b[z] | ivar.b[z] | r1.act.b[z] 545 ref.b[z] = 0 546 } 547 548 // cal.b is the current approximation of what's live across the call. 549 // Every bit in cal.b is a single stack word. For each such word, 550 // find all the other tracked stack words in the same Go variable 551 // (struct/slice/string/interface) and mark them live too. 552 // This is necessary because the liveness analysis for the garbage 553 // collector works at variable granularity, not at word granularity. 554 // It is fundamental for slice/string/interface: the garbage collector 555 // needs the whole value, not just some of the words, in order to 556 // interpret the other bits correctly. Specifically, slice needs a consistent 557 // ptr and cap, string needs a consistent ptr and len, and interface 558 // needs a consistent type word and data word. 559 for z = 0; z < BITS; z++ { 560 if cal.b[z] == 0 { 561 continue 562 } 563 for i = 0; i < 64; i++ { 564 if z*64+i >= nvar || (cal.b[z]>>uint(i))&1 == 0 { 565 continue 566 } 567 v = &vars[z*64+i] 568 if v.node.Opt == nil { // v represents fixed register, not Go variable 569 continue 570 } 571 572 // v->node->opt is the head of a linked list of Vars 573 // corresponding to tracked words from the Go variable v->node. 574 // Walk the list and set all the bits. 575 // For a large struct this could end up being quadratic: 576 // after the first setting, the outer loop (for z, i) would see a 1 bit 577 // for all of the remaining words in the struct, and for each such 578 // word would go through and turn on all the bits again. 579 // To avoid the quadratic behavior, we only turn on the bits if 580 // v is the head of the list or if the head's bit is not yet turned on. 581 // This will set the bits at most twice, keeping the overall loop linear. 582 v1, _ = v.node.Opt.(*Var) 583 584 if v == v1 || !btest(&cal, uint(v1.id)) { 585 for ; v1 != nil; v1 = v1.nextinnode { 586 biset(&cal, uint(v1.id)) 587 } 588 } 589 } 590 } 591 592 case obj.ATEXT: 593 for z = 0; z < BITS; z++ { 594 cal.b[z] = 0 595 ref.b[z] = 0 596 } 597 598 case obj.ARET: 599 for z = 0; z < BITS; z++ { 600 cal.b[z] = externs.b[z] | ovar.b[z] 601 ref.b[z] = 0 602 } 603 } 604 605 for z = 0; z < BITS; z++ { 606 ref.b[z] = ref.b[z]&^r1.set.b[z] | r1.use1.b[z] | r1.use2.b[z] 607 cal.b[z] &^= (r1.set.b[z] | r1.use1.b[z] | r1.use2.b[z]) 608 r1.refbehind.b[z] = ref.b[z] 609 r1.calbehind.b[z] = cal.b[z] 610 } 611 612 if f1.Active != 0 { 613 break 614 } 615 f1.Active = 1 616 } 617 618 var r *Reg 619 var f2 *Flow 620 for ; f != f1; f = f.P1 { 621 r = f.Data.(*Reg) 622 for f2 = f.P2; f2 != nil; f2 = f2.P2link { 623 prop(f2, r.refbehind, r.calbehind) 624 } 625 } 626 } 627 628 func synch(f *Flow, dif Bits) { 629 var r1 *Reg 630 var z int 631 632 for f1 := f; f1 != nil; f1 = f1.S1 { 633 r1 = f1.Data.(*Reg) 634 for z = 0; z < BITS; z++ { 635 dif.b[z] = dif.b[z]&^(^r1.refbehind.b[z]&r1.refahead.b[z]) | r1.set.b[z] | r1.regdiff.b[z] 636 if dif.b[z] != r1.regdiff.b[z] { 637 r1.regdiff.b[z] = dif.b[z] 638 change = 1 639 } 640 } 641 642 if f1.Active != 0 { 643 break 644 } 645 f1.Active = 1 646 for z = 0; z < BITS; z++ { 647 dif.b[z] &^= (^r1.calbehind.b[z] & r1.calahead.b[z]) 648 } 649 if f1.S2 != nil { 650 synch(f1.S2, dif) 651 } 652 } 653 } 654 655 func allreg(b uint64, r *Rgn) uint64 { 656 v := &vars[r.varno] 657 r.regno = 0 658 switch v.etype { 659 default: 660 Fatal("unknown etype %d/%v", Bitno(b), Econv(int(v.etype), 0)) 661 662 case TINT8, 663 TUINT8, 664 TINT16, 665 TUINT16, 666 TINT32, 667 TUINT32, 668 TINT64, 669 TUINT64, 670 TINT, 671 TUINT, 672 TUINTPTR, 673 TBOOL, 674 TPTR32, 675 TPTR64: 676 i := Thearch.BtoR(^b) 677 if i != 0 && r.cost > 0 { 678 r.regno = int16(i) 679 return Thearch.RtoB(i) 680 } 681 682 case TFLOAT32, TFLOAT64: 683 i := Thearch.BtoF(^b) 684 if i != 0 && r.cost > 0 { 685 r.regno = int16(i) 686 return Thearch.FtoB(i) 687 } 688 } 689 690 return 0 691 } 692 693 func LOAD(r *Reg, z int) uint64 { 694 return ^r.refbehind.b[z] & r.refahead.b[z] 695 } 696 697 func STORE(r *Reg, z int) uint64 { 698 return ^r.calbehind.b[z] & r.calahead.b[z] 699 } 700 701 // Cost parameters 702 const ( 703 CLOAD = 5 // cost of load 704 CREF = 5 // cost of reference if not registerized 705 LOOP = 3 // loop execution count (applied in popt.go) 706 ) 707 708 func paint1(f *Flow, bn int) { 709 z := bn / 64 710 bb := uint64(1 << uint(bn%64)) 711 r := f.Data.(*Reg) 712 if r.act.b[z]&bb != 0 { 713 return 714 } 715 var f1 *Flow 716 var r1 *Reg 717 for { 718 if r.refbehind.b[z]&bb == 0 { 719 break 720 } 721 f1 = f.P1 722 if f1 == nil { 723 break 724 } 725 r1 = f1.Data.(*Reg) 726 if r1.refahead.b[z]&bb == 0 { 727 break 728 } 729 if r1.act.b[z]&bb != 0 { 730 break 731 } 732 f = f1 733 r = r1 734 } 735 736 if LOAD(r, z)&^(r.set.b[z]&^(r.use1.b[z]|r.use2.b[z]))&bb != 0 { 737 change -= CLOAD * int(f.Loop) 738 } 739 740 for { 741 r.act.b[z] |= bb 742 743 if f.Prog.As != obj.ANOP { // don't give credit for NOPs 744 if r.use1.b[z]&bb != 0 { 745 change += CREF * int(f.Loop) 746 } 747 if (r.use2.b[z]|r.set.b[z])&bb != 0 { 748 change += CREF * int(f.Loop) 749 } 750 } 751 752 if STORE(r, z)&r.regdiff.b[z]&bb != 0 { 753 change -= CLOAD * int(f.Loop) 754 } 755 756 if r.refbehind.b[z]&bb != 0 { 757 for f1 = f.P2; f1 != nil; f1 = f1.P2link { 758 if (f1.Data.(*Reg)).refahead.b[z]&bb != 0 { 759 paint1(f1, bn) 760 } 761 } 762 } 763 764 if r.refahead.b[z]&bb == 0 { 765 break 766 } 767 f1 = f.S2 768 if f1 != nil { 769 if (f1.Data.(*Reg)).refbehind.b[z]&bb != 0 { 770 paint1(f1, bn) 771 } 772 } 773 f = f.S1 774 if f == nil { 775 break 776 } 777 r = f.Data.(*Reg) 778 if r.act.b[z]&bb != 0 { 779 break 780 } 781 if r.refbehind.b[z]&bb == 0 { 782 break 783 } 784 } 785 } 786 787 func paint2(f *Flow, bn int, depth int) uint64 { 788 z := bn / 64 789 bb := uint64(1 << uint(bn%64)) 790 vreg := regbits 791 r := f.Data.(*Reg) 792 if r.act.b[z]&bb == 0 { 793 return vreg 794 } 795 var r1 *Reg 796 var f1 *Flow 797 for { 798 if r.refbehind.b[z]&bb == 0 { 799 break 800 } 801 f1 = f.P1 802 if f1 == nil { 803 break 804 } 805 r1 = f1.Data.(*Reg) 806 if r1.refahead.b[z]&bb == 0 { 807 break 808 } 809 if r1.act.b[z]&bb == 0 { 810 break 811 } 812 f = f1 813 r = r1 814 } 815 816 for { 817 if Debug['R'] != 0 && Debug['v'] != 0 { 818 fmt.Printf(" paint2 %d %v\n", depth, f.Prog) 819 } 820 821 r.act.b[z] &^= bb 822 823 vreg |= r.regu 824 825 if r.refbehind.b[z]&bb != 0 { 826 for f1 = f.P2; f1 != nil; f1 = f1.P2link { 827 if (f1.Data.(*Reg)).refahead.b[z]&bb != 0 { 828 vreg |= paint2(f1, bn, depth+1) 829 } 830 } 831 } 832 833 if r.refahead.b[z]&bb == 0 { 834 break 835 } 836 f1 = f.S2 837 if f1 != nil { 838 if (f1.Data.(*Reg)).refbehind.b[z]&bb != 0 { 839 vreg |= paint2(f1, bn, depth+1) 840 } 841 } 842 f = f.S1 843 if f == nil { 844 break 845 } 846 r = f.Data.(*Reg) 847 if r.act.b[z]&bb == 0 { 848 break 849 } 850 if r.refbehind.b[z]&bb == 0 { 851 break 852 } 853 } 854 855 return vreg 856 } 857 858 func paint3(f *Flow, bn int, rb uint64, rn int) { 859 z := bn / 64 860 bb := uint64(1 << uint(bn%64)) 861 r := f.Data.(*Reg) 862 if r.act.b[z]&bb != 0 { 863 return 864 } 865 var r1 *Reg 866 var f1 *Flow 867 for { 868 if r.refbehind.b[z]&bb == 0 { 869 break 870 } 871 f1 = f.P1 872 if f1 == nil { 873 break 874 } 875 r1 = f1.Data.(*Reg) 876 if r1.refahead.b[z]&bb == 0 { 877 break 878 } 879 if r1.act.b[z]&bb != 0 { 880 break 881 } 882 f = f1 883 r = r1 884 } 885 886 if LOAD(r, z)&^(r.set.b[z]&^(r.use1.b[z]|r.use2.b[z]))&bb != 0 { 887 addmove(f, bn, rn, 0) 888 } 889 var p *obj.Prog 890 for { 891 r.act.b[z] |= bb 892 p = f.Prog 893 894 if r.use1.b[z]&bb != 0 { 895 if Debug['R'] != 0 && Debug['v'] != 0 { 896 fmt.Printf("%v", p) 897 } 898 addreg(&p.From, rn) 899 if Debug['R'] != 0 && Debug['v'] != 0 { 900 fmt.Printf(" ===change== %v\n", p) 901 } 902 } 903 904 if (r.use2.b[z]|r.set.b[z])&bb != 0 { 905 if Debug['R'] != 0 && Debug['v'] != 0 { 906 fmt.Printf("%v", p) 907 } 908 addreg(&p.To, rn) 909 if Debug['R'] != 0 && Debug['v'] != 0 { 910 fmt.Printf(" ===change== %v\n", p) 911 } 912 } 913 914 if STORE(r, z)&r.regdiff.b[z]&bb != 0 { 915 addmove(f, bn, rn, 1) 916 } 917 r.regu |= rb 918 919 if r.refbehind.b[z]&bb != 0 { 920 for f1 = f.P2; f1 != nil; f1 = f1.P2link { 921 if (f1.Data.(*Reg)).refahead.b[z]&bb != 0 { 922 paint3(f1, bn, rb, rn) 923 } 924 } 925 } 926 927 if r.refahead.b[z]&bb == 0 { 928 break 929 } 930 f1 = f.S2 931 if f1 != nil { 932 if (f1.Data.(*Reg)).refbehind.b[z]&bb != 0 { 933 paint3(f1, bn, rb, rn) 934 } 935 } 936 f = f.S1 937 if f == nil { 938 break 939 } 940 r = f.Data.(*Reg) 941 if r.act.b[z]&bb != 0 { 942 break 943 } 944 if r.refbehind.b[z]&bb == 0 { 945 break 946 } 947 } 948 } 949 950 func addreg(a *obj.Addr, rn int) { 951 a.Sym = nil 952 a.Node = nil 953 a.Offset = 0 954 a.Type = obj.TYPE_REG 955 a.Reg = int16(rn) 956 a.Name = 0 957 958 Ostats.Ncvtreg++ 959 } 960 961 func dumpone(f *Flow, isreg int) { 962 fmt.Printf("%d:%v", f.Loop, f.Prog) 963 if isreg != 0 { 964 r := f.Data.(*Reg) 965 var bit Bits 966 for z := 0; z < BITS; z++ { 967 bit.b[z] = r.set.b[z] | r.use1.b[z] | r.use2.b[z] | r.refbehind.b[z] | r.refahead.b[z] | r.calbehind.b[z] | r.calahead.b[z] | r.regdiff.b[z] | r.act.b[z] | 0 968 } 969 if bany(&bit) { 970 fmt.Printf("\t") 971 if bany(&r.set) { 972 fmt.Printf(" s:%v", &r.set) 973 } 974 if bany(&r.use1) { 975 fmt.Printf(" u1:%v", &r.use1) 976 } 977 if bany(&r.use2) { 978 fmt.Printf(" u2:%v", &r.use2) 979 } 980 if bany(&r.refbehind) { 981 fmt.Printf(" rb:%v ", &r.refbehind) 982 } 983 if bany(&r.refahead) { 984 fmt.Printf(" ra:%v ", &r.refahead) 985 } 986 if bany(&r.calbehind) { 987 fmt.Printf(" cb:%v ", &r.calbehind) 988 } 989 if bany(&r.calahead) { 990 fmt.Printf(" ca:%v ", &r.calahead) 991 } 992 if bany(&r.regdiff) { 993 fmt.Printf(" d:%v ", &r.regdiff) 994 } 995 if bany(&r.act) { 996 fmt.Printf(" a:%v ", &r.act) 997 } 998 } 999 } 1000 1001 fmt.Printf("\n") 1002 } 1003 1004 func Dumpit(str string, r0 *Flow, isreg int) { 1005 var r1 *Flow 1006 1007 fmt.Printf("\n%s\n", str) 1008 for r := r0; r != nil; r = r.Link { 1009 dumpone(r, isreg) 1010 r1 = r.P2 1011 if r1 != nil { 1012 fmt.Printf("\tpred:") 1013 for ; r1 != nil; r1 = r1.P2link { 1014 fmt.Printf(" %.4d", uint(int(r1.Prog.Pc))) 1015 } 1016 if r.P1 != nil { 1017 fmt.Printf(" (and %.4d)", uint(int(r.P1.Prog.Pc))) 1018 } else { 1019 fmt.Printf(" (only)") 1020 } 1021 fmt.Printf("\n") 1022 } 1023 1024 // Print successors if it's not just the next one 1025 if r.S1 != r.Link || r.S2 != nil { 1026 fmt.Printf("\tsucc:") 1027 if r.S1 != nil { 1028 fmt.Printf(" %.4d", uint(int(r.S1.Prog.Pc))) 1029 } 1030 if r.S2 != nil { 1031 fmt.Printf(" %.4d", uint(int(r.S2.Prog.Pc))) 1032 } 1033 fmt.Printf("\n") 1034 } 1035 } 1036 } 1037 1038 func regopt(firstp *obj.Prog) { 1039 mergetemp(firstp) 1040 1041 /* 1042 * control flow is more complicated in generated go code 1043 * than in generated c code. define pseudo-variables for 1044 * registers, so we have complete register usage information. 1045 */ 1046 var nreg int 1047 regnames := Thearch.Regnames(&nreg) 1048 1049 nvar = nreg 1050 for i := 0; i < nreg; i++ { 1051 vars[i] = Var{} 1052 } 1053 for i := 0; i < nreg; i++ { 1054 if regnodes[i] == nil { 1055 regnodes[i] = newname(Lookup(regnames[i])) 1056 } 1057 vars[i].node = regnodes[i] 1058 } 1059 1060 regbits = Thearch.Excludedregs() 1061 externs = zbits 1062 params = zbits 1063 consts = zbits 1064 addrs = zbits 1065 ivar = zbits 1066 ovar = zbits 1067 1068 /* 1069 * pass 1 1070 * build aux data structure 1071 * allocate pcs 1072 * find use and set of variables 1073 */ 1074 g := Flowstart(firstp, func() interface{} { return new(Reg) }) 1075 if g == nil { 1076 for i := 0; i < nvar; i++ { 1077 vars[i].node.Opt = nil 1078 } 1079 return 1080 } 1081 1082 firstf := g.Start 1083 1084 for f := firstf; f != nil; f = f.Link { 1085 p := f.Prog 1086 if p.As == obj.AVARDEF || p.As == obj.AVARKILL { 1087 continue 1088 } 1089 1090 // Avoid making variables for direct-called functions. 1091 if p.As == obj.ACALL && p.To.Type == obj.TYPE_MEM && p.To.Name == obj.NAME_EXTERN { 1092 continue 1093 } 1094 1095 // from vs to doesn't matter for registers. 1096 r := f.Data.(*Reg) 1097 r.use1.b[0] |= p.Info.Reguse | p.Info.Regindex 1098 r.set.b[0] |= p.Info.Regset 1099 1100 bit := mkvar(f, &p.From) 1101 if bany(&bit) { 1102 if p.Info.Flags&LeftAddr != 0 { 1103 setaddrs(bit) 1104 } 1105 if p.Info.Flags&LeftRead != 0 { 1106 for z := 0; z < BITS; z++ { 1107 r.use1.b[z] |= bit.b[z] 1108 } 1109 } 1110 if p.Info.Flags&LeftWrite != 0 { 1111 for z := 0; z < BITS; z++ { 1112 r.set.b[z] |= bit.b[z] 1113 } 1114 } 1115 } 1116 1117 // Compute used register for reg 1118 if p.Info.Flags&RegRead != 0 { 1119 r.use1.b[0] |= Thearch.RtoB(int(p.Reg)) 1120 } 1121 1122 // Currently we never generate three register forms. 1123 // If we do, this will need to change. 1124 if p.From3.Type != obj.TYPE_NONE { 1125 Fatal("regopt not implemented for from3") 1126 } 1127 1128 bit = mkvar(f, &p.To) 1129 if bany(&bit) { 1130 if p.Info.Flags&RightAddr != 0 { 1131 setaddrs(bit) 1132 } 1133 if p.Info.Flags&RightRead != 0 { 1134 for z := 0; z < BITS; z++ { 1135 r.use2.b[z] |= bit.b[z] 1136 } 1137 } 1138 if p.Info.Flags&RightWrite != 0 { 1139 for z := 0; z < BITS; z++ { 1140 r.set.b[z] |= bit.b[z] 1141 } 1142 } 1143 } 1144 } 1145 1146 for i := 0; i < nvar; i++ { 1147 v := &vars[i] 1148 if v.addr != 0 { 1149 bit := blsh(uint(i)) 1150 for z := 0; z < BITS; z++ { 1151 addrs.b[z] |= bit.b[z] 1152 } 1153 } 1154 1155 if Debug['R'] != 0 && Debug['v'] != 0 { 1156 fmt.Printf("bit=%2d addr=%d et=%v w=%-2d s=%v + %d\n", i, v.addr, Econv(int(v.etype), 0), v.width, v.node, v.offset) 1157 } 1158 } 1159 1160 if Debug['R'] != 0 && Debug['v'] != 0 { 1161 Dumpit("pass1", firstf, 1) 1162 } 1163 1164 /* 1165 * pass 2 1166 * find looping structure 1167 */ 1168 flowrpo(g) 1169 1170 if Debug['R'] != 0 && Debug['v'] != 0 { 1171 Dumpit("pass2", firstf, 1) 1172 } 1173 1174 /* 1175 * pass 2.5 1176 * iterate propagating fat vardef covering forward 1177 * r->act records vars with a VARDEF since the last CALL. 1178 * (r->act will be reused in pass 5 for something else, 1179 * but we'll be done with it by then.) 1180 */ 1181 active := 0 1182 1183 for f := firstf; f != nil; f = f.Link { 1184 f.Active = 0 1185 r := f.Data.(*Reg) 1186 r.act = zbits 1187 } 1188 1189 for f := firstf; f != nil; f = f.Link { 1190 p := f.Prog 1191 if p.As == obj.AVARDEF && Isfat(((p.To.Node).(*Node)).Type) && ((p.To.Node).(*Node)).Opt != nil { 1192 active++ 1193 walkvardef(p.To.Node.(*Node), f, active) 1194 } 1195 } 1196 1197 /* 1198 * pass 3 1199 * iterate propagating usage 1200 * back until flow graph is complete 1201 */ 1202 var f1 *Flow 1203 var i int 1204 var f *Flow 1205 loop1: 1206 change = 0 1207 1208 for f = firstf; f != nil; f = f.Link { 1209 f.Active = 0 1210 } 1211 for f = firstf; f != nil; f = f.Link { 1212 if f.Prog.As == obj.ARET { 1213 prop(f, zbits, zbits) 1214 } 1215 } 1216 1217 /* pick up unreachable code */ 1218 loop11: 1219 i = 0 1220 1221 for f = firstf; f != nil; f = f1 { 1222 f1 = f.Link 1223 if f1 != nil && f1.Active != 0 && f.Active == 0 { 1224 prop(f, zbits, zbits) 1225 i = 1 1226 } 1227 } 1228 1229 if i != 0 { 1230 goto loop11 1231 } 1232 if change != 0 { 1233 goto loop1 1234 } 1235 1236 if Debug['R'] != 0 && Debug['v'] != 0 { 1237 Dumpit("pass3", firstf, 1) 1238 } 1239 1240 /* 1241 * pass 4 1242 * iterate propagating register/variable synchrony 1243 * forward until graph is complete 1244 */ 1245 loop2: 1246 change = 0 1247 1248 for f = firstf; f != nil; f = f.Link { 1249 f.Active = 0 1250 } 1251 synch(firstf, zbits) 1252 if change != 0 { 1253 goto loop2 1254 } 1255 1256 if Debug['R'] != 0 && Debug['v'] != 0 { 1257 Dumpit("pass4", firstf, 1) 1258 } 1259 1260 /* 1261 * pass 4.5 1262 * move register pseudo-variables into regu. 1263 */ 1264 mask := uint64((1 << uint(nreg)) - 1) 1265 for f := firstf; f != nil; f = f.Link { 1266 r := f.Data.(*Reg) 1267 r.regu = (r.refbehind.b[0] | r.set.b[0]) & mask 1268 r.set.b[0] &^= mask 1269 r.use1.b[0] &^= mask 1270 r.use2.b[0] &^= mask 1271 r.refbehind.b[0] &^= mask 1272 r.refahead.b[0] &^= mask 1273 r.calbehind.b[0] &^= mask 1274 r.calahead.b[0] &^= mask 1275 r.regdiff.b[0] &^= mask 1276 r.act.b[0] &^= mask 1277 } 1278 1279 if Debug['R'] != 0 && Debug['v'] != 0 { 1280 Dumpit("pass4.5", firstf, 1) 1281 } 1282 1283 /* 1284 * pass 5 1285 * isolate regions 1286 * calculate costs (paint1) 1287 */ 1288 var bit Bits 1289 if f := firstf; f != nil { 1290 r := f.Data.(*Reg) 1291 for z := 0; z < BITS; z++ { 1292 bit.b[z] = (r.refahead.b[z] | r.calahead.b[z]) &^ (externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]) 1293 } 1294 if bany(&bit) && f.Refset == 0 { 1295 // should never happen - all variables are preset 1296 if Debug['w'] != 0 { 1297 fmt.Printf("%v: used and not set: %v\n", f.Prog.Line(), &bit) 1298 } 1299 f.Refset = 1 1300 } 1301 } 1302 1303 for f := firstf; f != nil; f = f.Link { 1304 (f.Data.(*Reg)).act = zbits 1305 } 1306 nregion = 0 1307 region = region[:0] 1308 var rgp *Rgn 1309 for f := firstf; f != nil; f = f.Link { 1310 r := f.Data.(*Reg) 1311 for z := 0; z < BITS; z++ { 1312 bit.b[z] = r.set.b[z] &^ (r.refahead.b[z] | r.calahead.b[z] | addrs.b[z]) 1313 } 1314 if bany(&bit) && f.Refset == 0 { 1315 if Debug['w'] != 0 { 1316 fmt.Printf("%v: set and not used: %v\n", f.Prog.Line(), &bit) 1317 } 1318 f.Refset = 1 1319 Thearch.Excise(f) 1320 } 1321 1322 for z := 0; z < BITS; z++ { 1323 bit.b[z] = LOAD(r, z) &^ (r.act.b[z] | addrs.b[z]) 1324 } 1325 for bany(&bit) { 1326 i = bnum(bit) 1327 change = 0 1328 paint1(f, i) 1329 biclr(&bit, uint(i)) 1330 if change <= 0 { 1331 continue 1332 } 1333 if nregion >= MaxRgn { 1334 nregion++ 1335 continue 1336 } 1337 1338 region = append(region, Rgn{ 1339 enter: f, 1340 cost: int16(change), 1341 varno: int16(i), 1342 }) 1343 nregion++ 1344 } 1345 } 1346 1347 if false && Debug['v'] != 0 && strings.Contains(Curfn.Nname.Sym.Name, "Parse") { 1348 Warn("regions: %d\n", nregion) 1349 } 1350 if nregion >= MaxRgn { 1351 if Debug['v'] != 0 { 1352 Warn("too many regions: %d\n", nregion) 1353 } 1354 nregion = MaxRgn 1355 } 1356 1357 sort.Sort(rcmp(region[:nregion])) 1358 1359 if Debug['R'] != 0 && Debug['v'] != 0 { 1360 Dumpit("pass5", firstf, 1) 1361 } 1362 1363 /* 1364 * pass 6 1365 * determine used registers (paint2) 1366 * replace code (paint3) 1367 */ 1368 if Debug['R'] != 0 && Debug['v'] != 0 { 1369 fmt.Printf("\nregisterizing\n") 1370 } 1371 var usedreg uint64 1372 var vreg uint64 1373 for i := 0; i < nregion; i++ { 1374 rgp = ®ion[i] 1375 if Debug['R'] != 0 && Debug['v'] != 0 { 1376 fmt.Printf("region %d: cost %d varno %d enter %d\n", i, rgp.cost, rgp.varno, rgp.enter.Prog.Pc) 1377 } 1378 bit = blsh(uint(rgp.varno)) 1379 usedreg = paint2(rgp.enter, int(rgp.varno), 0) 1380 vreg = allreg(usedreg, rgp) 1381 if rgp.regno != 0 { 1382 if Debug['R'] != 0 && Debug['v'] != 0 { 1383 v := &vars[rgp.varno] 1384 fmt.Printf("registerize %v+%d (bit=%2d et=%v) in %v usedreg=%#x vreg=%#x\n", v.node, v.offset, rgp.varno, Econv(int(v.etype), 0), obj.Rconv(int(rgp.regno)), usedreg, vreg) 1385 } 1386 1387 paint3(rgp.enter, int(rgp.varno), vreg, int(rgp.regno)) 1388 } 1389 } 1390 1391 /* 1392 * free aux structures. peep allocates new ones. 1393 */ 1394 for i := 0; i < nvar; i++ { 1395 vars[i].node.Opt = nil 1396 } 1397 Flowend(g) 1398 firstf = nil 1399 1400 if Debug['R'] != 0 && Debug['v'] != 0 { 1401 // Rebuild flow graph, since we inserted instructions 1402 g := Flowstart(firstp, nil) 1403 firstf = g.Start 1404 Dumpit("pass6", firstf, 0) 1405 Flowend(g) 1406 firstf = nil 1407 } 1408 1409 /* 1410 * pass 7 1411 * peep-hole on basic block 1412 */ 1413 if Debug['R'] == 0 || Debug['P'] != 0 { 1414 Thearch.Peep(firstp) 1415 } 1416 1417 /* 1418 * eliminate nops 1419 */ 1420 for p := firstp; p != nil; p = p.Link { 1421 for p.Link != nil && p.Link.As == obj.ANOP { 1422 p.Link = p.Link.Link 1423 } 1424 if p.To.Type == obj.TYPE_BRANCH { 1425 for p.To.Val.(*obj.Prog) != nil && p.To.Val.(*obj.Prog).As == obj.ANOP { 1426 p.To.Val = p.To.Val.(*obj.Prog).Link 1427 } 1428 } 1429 } 1430 1431 if Debug['R'] != 0 { 1432 if Ostats.Ncvtreg != 0 || Ostats.Nspill != 0 || Ostats.Nreload != 0 || Ostats.Ndelmov != 0 || Ostats.Nvar != 0 || Ostats.Naddr != 0 || false { 1433 fmt.Printf("\nstats\n") 1434 } 1435 1436 if Ostats.Ncvtreg != 0 { 1437 fmt.Printf("\t%4d cvtreg\n", Ostats.Ncvtreg) 1438 } 1439 if Ostats.Nspill != 0 { 1440 fmt.Printf("\t%4d spill\n", Ostats.Nspill) 1441 } 1442 if Ostats.Nreload != 0 { 1443 fmt.Printf("\t%4d reload\n", Ostats.Nreload) 1444 } 1445 if Ostats.Ndelmov != 0 { 1446 fmt.Printf("\t%4d delmov\n", Ostats.Ndelmov) 1447 } 1448 if Ostats.Nvar != 0 { 1449 fmt.Printf("\t%4d var\n", Ostats.Nvar) 1450 } 1451 if Ostats.Naddr != 0 { 1452 fmt.Printf("\t%4d addr\n", Ostats.Naddr) 1453 } 1454 1455 Ostats = OptStats{} 1456 } 1457 } 1458 1459 // bany reports whether any bits in a are set. 1460 func bany(a *Bits) bool { 1461 for _, x := range &a.b { // & to avoid making a copy of a.b 1462 if x != 0 { 1463 return true 1464 } 1465 } 1466 return false 1467 } 1468 1469 // bnum reports the lowest index of a 1 bit in a. 1470 func bnum(a Bits) int { 1471 for i, x := range &a.b { // & to avoid making a copy of a.b 1472 if x != 0 { 1473 return 64*i + Bitno(x) 1474 } 1475 } 1476 1477 Fatal("bad in bnum") 1478 return 0 1479 } 1480 1481 // blsh returns a Bits with 1 at index n, 0 elsewhere (1<<n). 1482 func blsh(n uint) Bits { 1483 c := zbits 1484 c.b[n/64] = 1 << (n % 64) 1485 return c 1486 } 1487 1488 // btest reports whether bit n is 1. 1489 func btest(a *Bits, n uint) bool { 1490 return a.b[n/64]&(1<<(n%64)) != 0 1491 } 1492 1493 // biset sets bit n to 1. 1494 func biset(a *Bits, n uint) { 1495 a.b[n/64] |= 1 << (n % 64) 1496 } 1497 1498 // biclr sets bit n to 0. 1499 func biclr(a *Bits, n uint) { 1500 a.b[n/64] &^= (1 << (n % 64)) 1501 } 1502 1503 // Bitno reports the lowest index of a 1 bit in b. 1504 // It calls Fatal if there is no 1 bit. 1505 func Bitno(b uint64) int { 1506 if b == 0 { 1507 Fatal("bad in bitno") 1508 } 1509 n := 0 1510 if b&(1<<32-1) == 0 { 1511 n += 32 1512 b >>= 32 1513 } 1514 if b&(1<<16-1) == 0 { 1515 n += 16 1516 b >>= 16 1517 } 1518 if b&(1<<8-1) == 0 { 1519 n += 8 1520 b >>= 8 1521 } 1522 if b&(1<<4-1) == 0 { 1523 n += 4 1524 b >>= 4 1525 } 1526 if b&(1<<2-1) == 0 { 1527 n += 2 1528 b >>= 2 1529 } 1530 if b&1 == 0 { 1531 n++ 1532 } 1533 return n 1534 } 1535 1536 // String returns a space-separated list of the variables represented by bits. 1537 func (bits Bits) String() string { 1538 // Note: This method takes a value receiver, both for convenience 1539 // and to make it safe to modify the bits as we process them. 1540 // Even so, most prints above use &bits, because then the value 1541 // being stored in the interface{} is a pointer and does not require 1542 // an allocation and copy to create the interface{}. 1543 var buf bytes.Buffer 1544 sep := "" 1545 for bany(&bits) { 1546 i := bnum(bits) 1547 buf.WriteString(sep) 1548 sep = " " 1549 v := &vars[i] 1550 if v.node == nil || v.node.Sym == nil { 1551 fmt.Fprintf(&buf, "$%d", i) 1552 } else { 1553 fmt.Fprintf(&buf, "%s(%d)", v.node.Sym.Name, i) 1554 if v.offset != 0 { 1555 fmt.Fprintf(&buf, "%+d", int64(v.offset)) 1556 } 1557 } 1558 biclr(&bits, uint(i)) 1559 } 1560 return buf.String() 1561 }