github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/cmd/compile/internal/ssa/rewrite.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssa 6 7 import ( 8 "cmd/compile/internal/types" 9 "cmd/internal/obj" 10 "cmd/internal/objabi" 11 "cmd/internal/src" 12 "encoding/binary" 13 "fmt" 14 "io" 15 "math" 16 "math/bits" 17 "os" 18 "path/filepath" 19 ) 20 21 func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter) { 22 // repeat rewrites until we find no more rewrites 23 pendingLines := f.cachedLineStarts // Holds statement boundaries that need to be moved to a new value/block 24 pendingLines.clear() 25 for { 26 change := false 27 for _, b := range f.Blocks { 28 if b.Control != nil && b.Control.Op == OpCopy { 29 for b.Control.Op == OpCopy { 30 b.SetControl(b.Control.Args[0]) 31 } 32 } 33 if rb(b) { 34 change = true 35 } 36 for j, v := range b.Values { 37 change = phielimValue(v) || change 38 39 // Eliminate copy inputs. 40 // If any copy input becomes unused, mark it 41 // as invalid and discard its argument. Repeat 42 // recursively on the discarded argument. 43 // This phase helps remove phantom "dead copy" uses 44 // of a value so that a x.Uses==1 rule condition 45 // fires reliably. 46 for i, a := range v.Args { 47 if a.Op != OpCopy { 48 continue 49 } 50 aa := copySource(a) 51 v.SetArg(i, aa) 52 // If a, a copy, has a line boundary indicator, attempt to find a new value 53 // to hold it. The first candidate is the value that will replace a (aa), 54 // if it shares the same block and line and is eligible. 55 // The second option is v, which has a as an input. Because aa is earlier in 56 // the data flow, it is the better choice. 57 if a.Pos.IsStmt() == src.PosIsStmt { 58 if aa.Block == a.Block && aa.Pos.Line() == a.Pos.Line() && aa.Pos.IsStmt() != src.PosNotStmt { 59 aa.Pos = aa.Pos.WithIsStmt() 60 } else if v.Block == a.Block && v.Pos.Line() == a.Pos.Line() && v.Pos.IsStmt() != src.PosNotStmt { 61 v.Pos = v.Pos.WithIsStmt() 62 } else { 63 // Record the lost line and look for a new home after all rewrites are complete. 64 // TODO: it's possible (in FOR loops, in particular) for statement boundaries for the same 65 // line to appear in more than one block, but only one block is stored, so if both end 66 // up here, then one will be lost. 67 pendingLines.set(a.Pos.Line(), int32(a.Block.ID)) 68 } 69 a.Pos = a.Pos.WithNotStmt() 70 } 71 change = true 72 for a.Uses == 0 { 73 b := a.Args[0] 74 a.reset(OpInvalid) 75 a = b 76 } 77 } 78 79 // apply rewrite function 80 if rv(v) { 81 change = true 82 // If value changed to a poor choice for a statement boundary, move the boundary 83 if v.Pos.IsStmt() == src.PosIsStmt { 84 if k := nextGoodStatementIndex(v, j, b); k != j { 85 v.Pos = v.Pos.WithNotStmt() 86 b.Values[k].Pos = b.Values[k].Pos.WithIsStmt() 87 } 88 } 89 } 90 } 91 } 92 if !change { 93 break 94 } 95 } 96 // remove clobbered values 97 for _, b := range f.Blocks { 98 j := 0 99 for i, v := range b.Values { 100 vl := v.Pos.Line() 101 if v.Op == OpInvalid { 102 if v.Pos.IsStmt() == src.PosIsStmt { 103 pendingLines.set(vl, int32(b.ID)) 104 } 105 f.freeValue(v) 106 continue 107 } 108 if v.Pos.IsStmt() != src.PosNotStmt && pendingLines.get(vl) == int32(b.ID) { 109 pendingLines.remove(vl) 110 v.Pos = v.Pos.WithIsStmt() 111 } 112 if i != j { 113 b.Values[j] = v 114 } 115 j++ 116 } 117 if pendingLines.get(b.Pos.Line()) == int32(b.ID) { 118 b.Pos = b.Pos.WithIsStmt() 119 pendingLines.remove(b.Pos.Line()) 120 } 121 if j != len(b.Values) { 122 tail := b.Values[j:] 123 for j := range tail { 124 tail[j] = nil 125 } 126 b.Values = b.Values[:j] 127 } 128 } 129 } 130 131 // Common functions called from rewriting rules 132 133 func is64BitFloat(t *types.Type) bool { 134 return t.Size() == 8 && t.IsFloat() 135 } 136 137 func is32BitFloat(t *types.Type) bool { 138 return t.Size() == 4 && t.IsFloat() 139 } 140 141 func is64BitInt(t *types.Type) bool { 142 return t.Size() == 8 && t.IsInteger() 143 } 144 145 func is32BitInt(t *types.Type) bool { 146 return t.Size() == 4 && t.IsInteger() 147 } 148 149 func is16BitInt(t *types.Type) bool { 150 return t.Size() == 2 && t.IsInteger() 151 } 152 153 func is8BitInt(t *types.Type) bool { 154 return t.Size() == 1 && t.IsInteger() 155 } 156 157 func isPtr(t *types.Type) bool { 158 return t.IsPtrShaped() 159 } 160 161 func isSigned(t *types.Type) bool { 162 return t.IsSigned() 163 } 164 165 // mergeSym merges two symbolic offsets. There is no real merging of 166 // offsets, we just pick the non-nil one. 167 func mergeSym(x, y interface{}) interface{} { 168 if x == nil { 169 return y 170 } 171 if y == nil { 172 return x 173 } 174 panic(fmt.Sprintf("mergeSym with two non-nil syms %s %s", x, y)) 175 } 176 func canMergeSym(x, y interface{}) bool { 177 return x == nil || y == nil 178 } 179 180 // canMergeLoad reports whether the load can be merged into target without 181 // invalidating the schedule. 182 // It also checks that the other non-load argument x is something we 183 // are ok with clobbering (all our current load+op instructions clobber 184 // their input register). 185 func canMergeLoad(target, load, x *Value) bool { 186 if target.Block.ID != load.Block.ID { 187 // If the load is in a different block do not merge it. 188 return false 189 } 190 191 // We can't merge the load into the target if the load 192 // has more than one use. 193 if load.Uses != 1 { 194 return false 195 } 196 197 // The register containing x is going to get clobbered. 198 // Don't merge if we still need the value of x. 199 // We don't have liveness information here, but we can 200 // approximate x dying with: 201 // 1) target is x's only use. 202 // 2) target is not in a deeper loop than x. 203 if x.Uses != 1 { 204 return false 205 } 206 loopnest := x.Block.Func.loopnest() 207 loopnest.calculateDepths() 208 if loopnest.depth(target.Block.ID) > loopnest.depth(x.Block.ID) { 209 return false 210 } 211 212 mem := load.MemoryArg() 213 214 // We need the load's memory arg to still be alive at target. That 215 // can't be the case if one of target's args depends on a memory 216 // state that is a successor of load's memory arg. 217 // 218 // For example, it would be invalid to merge load into target in 219 // the following situation because newmem has killed oldmem 220 // before target is reached: 221 // load = read ... oldmem 222 // newmem = write ... oldmem 223 // arg0 = read ... newmem 224 // target = add arg0 load 225 // 226 // If the argument comes from a different block then we can exclude 227 // it immediately because it must dominate load (which is in the 228 // same block as target). 229 var args []*Value 230 for _, a := range target.Args { 231 if a != load && a.Block.ID == target.Block.ID { 232 args = append(args, a) 233 } 234 } 235 236 // memPreds contains memory states known to be predecessors of load's 237 // memory state. It is lazily initialized. 238 var memPreds map[*Value]bool 239 for i := 0; len(args) > 0; i++ { 240 const limit = 100 241 if i >= limit { 242 // Give up if we have done a lot of iterations. 243 return false 244 } 245 v := args[len(args)-1] 246 args = args[:len(args)-1] 247 if target.Block.ID != v.Block.ID { 248 // Since target and load are in the same block 249 // we can stop searching when we leave the block. 250 continue 251 } 252 if v.Op == OpPhi { 253 // A Phi implies we have reached the top of the block. 254 // The memory phi, if it exists, is always 255 // the first logical store in the block. 256 continue 257 } 258 if v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() { 259 // We could handle this situation however it is likely 260 // to be very rare. 261 return false 262 } 263 if v.Type.IsMemory() { 264 if memPreds == nil { 265 // Initialise a map containing memory states 266 // known to be predecessors of load's memory 267 // state. 268 memPreds = make(map[*Value]bool) 269 m := mem 270 const limit = 50 271 for i := 0; i < limit; i++ { 272 if m.Op == OpPhi { 273 // The memory phi, if it exists, is always 274 // the first logical store in the block. 275 break 276 } 277 if m.Block.ID != target.Block.ID { 278 break 279 } 280 if !m.Type.IsMemory() { 281 break 282 } 283 memPreds[m] = true 284 if len(m.Args) == 0 { 285 break 286 } 287 m = m.MemoryArg() 288 } 289 } 290 291 // We can merge if v is a predecessor of mem. 292 // 293 // For example, we can merge load into target in the 294 // following scenario: 295 // x = read ... v 296 // mem = write ... v 297 // load = read ... mem 298 // target = add x load 299 if memPreds[v] { 300 continue 301 } 302 return false 303 } 304 if len(v.Args) > 0 && v.Args[len(v.Args)-1] == mem { 305 // If v takes mem as an input then we know mem 306 // is valid at this point. 307 continue 308 } 309 for _, a := range v.Args { 310 if target.Block.ID == a.Block.ID { 311 args = append(args, a) 312 } 313 } 314 } 315 316 return true 317 } 318 319 // isSameSym returns whether sym is the same as the given named symbol 320 func isSameSym(sym interface{}, name string) bool { 321 s, ok := sym.(fmt.Stringer) 322 return ok && s.String() == name 323 } 324 325 // nlz returns the number of leading zeros. 326 func nlz(x int64) int64 { 327 return int64(bits.LeadingZeros64(uint64(x))) 328 } 329 330 // ntz returns the number of trailing zeros. 331 func ntz(x int64) int64 { 332 return int64(bits.TrailingZeros64(uint64(x))) 333 } 334 335 func oneBit(x int64) bool { 336 return bits.OnesCount64(uint64(x)) == 1 337 } 338 339 // nlo returns the number of leading ones. 340 func nlo(x int64) int64 { 341 return nlz(^x) 342 } 343 344 // nto returns the number of trailing ones. 345 func nto(x int64) int64 { 346 return ntz(^x) 347 } 348 349 // log2 returns logarithm in base 2 of uint64(n), with log2(0) = -1. 350 // Rounds down. 351 func log2(n int64) int64 { 352 return int64(bits.Len64(uint64(n))) - 1 353 } 354 355 // log2uint32 returns logarithm in base 2 of uint32(n), with log2(0) = -1. 356 // Rounds down. 357 func log2uint32(n int64) int64 { 358 return int64(bits.Len32(uint32(n))) - 1 359 } 360 361 // isPowerOfTwo reports whether n is a power of 2. 362 func isPowerOfTwo(n int64) bool { 363 return n > 0 && n&(n-1) == 0 364 } 365 366 // isUint64PowerOfTwo reports whether uint64(n) is a power of 2. 367 func isUint64PowerOfTwo(in int64) bool { 368 n := uint64(in) 369 return n > 0 && n&(n-1) == 0 370 } 371 372 // isUint32PowerOfTwo reports whether uint32(n) is a power of 2. 373 func isUint32PowerOfTwo(in int64) bool { 374 n := uint64(uint32(in)) 375 return n > 0 && n&(n-1) == 0 376 } 377 378 // is32Bit reports whether n can be represented as a signed 32 bit integer. 379 func is32Bit(n int64) bool { 380 return n == int64(int32(n)) 381 } 382 383 // is16Bit reports whether n can be represented as a signed 16 bit integer. 384 func is16Bit(n int64) bool { 385 return n == int64(int16(n)) 386 } 387 388 // isU12Bit reports whether n can be represented as an unsigned 12 bit integer. 389 func isU12Bit(n int64) bool { 390 return 0 <= n && n < (1<<12) 391 } 392 393 // isU16Bit reports whether n can be represented as an unsigned 16 bit integer. 394 func isU16Bit(n int64) bool { 395 return n == int64(uint16(n)) 396 } 397 398 // isU32Bit reports whether n can be represented as an unsigned 32 bit integer. 399 func isU32Bit(n int64) bool { 400 return n == int64(uint32(n)) 401 } 402 403 // is20Bit reports whether n can be represented as a signed 20 bit integer. 404 func is20Bit(n int64) bool { 405 return -(1<<19) <= n && n < (1<<19) 406 } 407 408 // b2i translates a boolean value to 0 or 1 for assigning to auxInt. 409 func b2i(b bool) int64 { 410 if b { 411 return 1 412 } 413 return 0 414 } 415 416 // shiftIsBounded reports whether (left/right) shift Value v is known to be bounded. 417 // A shift is bounded if it is shifting by less than the width of the shifted value. 418 func shiftIsBounded(v *Value) bool { 419 return v.AuxInt != 0 420 } 421 422 // truncate64Fto32F converts a float64 value to a float32 preserving the bit pattern 423 // of the mantissa. It will panic if the truncation results in lost information. 424 func truncate64Fto32F(f float64) float32 { 425 if !isExactFloat32(f) { 426 panic("truncate64Fto32F: truncation is not exact") 427 } 428 if !math.IsNaN(f) { 429 return float32(f) 430 } 431 // NaN bit patterns aren't necessarily preserved across conversion 432 // instructions so we need to do the conversion manually. 433 b := math.Float64bits(f) 434 m := b & ((1 << 52) - 1) // mantissa (a.k.a. significand) 435 // | sign | exponent | mantissa | 436 r := uint32(((b >> 32) & (1 << 31)) | 0x7f800000 | (m >> (52 - 23))) 437 return math.Float32frombits(r) 438 } 439 440 // extend32Fto64F converts a float32 value to a float64 value preserving the bit 441 // pattern of the mantissa. 442 func extend32Fto64F(f float32) float64 { 443 if !math.IsNaN(float64(f)) { 444 return float64(f) 445 } 446 // NaN bit patterns aren't necessarily preserved across conversion 447 // instructions so we need to do the conversion manually. 448 b := uint64(math.Float32bits(f)) 449 // | sign | exponent | mantissa | 450 r := ((b << 32) & (1 << 63)) | (0x7ff << 52) | ((b & 0x7fffff) << (52 - 23)) 451 return math.Float64frombits(r) 452 } 453 454 // NeedsFixUp reports whether the division needs fix-up code. 455 func NeedsFixUp(v *Value) bool { 456 return v.AuxInt == 0 457 } 458 459 // i2f is used in rules for converting from an AuxInt to a float. 460 func i2f(i int64) float64 { 461 return math.Float64frombits(uint64(i)) 462 } 463 464 // auxFrom64F encodes a float64 value so it can be stored in an AuxInt. 465 func auxFrom64F(f float64) int64 { 466 return int64(math.Float64bits(f)) 467 } 468 469 // auxFrom32F encodes a float32 value so it can be stored in an AuxInt. 470 func auxFrom32F(f float32) int64 { 471 return int64(math.Float64bits(extend32Fto64F(f))) 472 } 473 474 // auxTo32F decodes a float32 from the AuxInt value provided. 475 func auxTo32F(i int64) float32 { 476 return truncate64Fto32F(math.Float64frombits(uint64(i))) 477 } 478 479 // auxTo64F decodes a float64 from the AuxInt value provided. 480 func auxTo64F(i int64) float64 { 481 return math.Float64frombits(uint64(i)) 482 } 483 484 // uaddOvf returns true if unsigned a+b would overflow. 485 func uaddOvf(a, b int64) bool { 486 return uint64(a)+uint64(b) < uint64(a) 487 } 488 489 // de-virtualize an InterCall 490 // 'sym' is the symbol for the itab 491 func devirt(v *Value, sym interface{}, offset int64) *obj.LSym { 492 f := v.Block.Func 493 n, ok := sym.(*obj.LSym) 494 if !ok { 495 return nil 496 } 497 lsym := f.fe.DerefItab(n, offset) 498 if f.pass.debug > 0 { 499 if lsym != nil { 500 f.Warnl(v.Pos, "de-virtualizing call") 501 } else { 502 f.Warnl(v.Pos, "couldn't de-virtualize call") 503 } 504 } 505 return lsym 506 } 507 508 // isSamePtr reports whether p1 and p2 point to the same address. 509 func isSamePtr(p1, p2 *Value) bool { 510 if p1 == p2 { 511 return true 512 } 513 if p1.Op != p2.Op { 514 return false 515 } 516 switch p1.Op { 517 case OpOffPtr: 518 return p1.AuxInt == p2.AuxInt && isSamePtr(p1.Args[0], p2.Args[0]) 519 case OpAddr, OpLocalAddr: 520 // OpAddr's 0th arg is either OpSP or OpSB, which means that it is uniquely identified by its Op. 521 // Checking for value equality only works after [z]cse has run. 522 return p1.Aux == p2.Aux && p1.Args[0].Op == p2.Args[0].Op 523 case OpAddPtr: 524 return p1.Args[1] == p2.Args[1] && isSamePtr(p1.Args[0], p2.Args[0]) 525 } 526 return false 527 } 528 529 // disjoint reports whether the memory region specified by [p1:p1+n1) 530 // does not overlap with [p2:p2+n2). 531 // A return value of false does not imply the regions overlap. 532 func disjoint(p1 *Value, n1 int64, p2 *Value, n2 int64) bool { 533 if n1 == 0 || n2 == 0 { 534 return true 535 } 536 if p1 == p2 { 537 return false 538 } 539 baseAndOffset := func(ptr *Value) (base *Value, offset int64) { 540 base, offset = ptr, 0 541 if base.Op == OpOffPtr { 542 offset += base.AuxInt 543 base = base.Args[0] 544 } 545 return base, offset 546 } 547 p1, off1 := baseAndOffset(p1) 548 p2, off2 := baseAndOffset(p2) 549 if isSamePtr(p1, p2) { 550 return !overlap(off1, n1, off2, n2) 551 } 552 // p1 and p2 are not the same, so if they are both OpAddrs then 553 // they point to different variables. 554 // If one pointer is on the stack and the other is an argument 555 // then they can't overlap. 556 switch p1.Op { 557 case OpAddr, OpLocalAddr: 558 if p2.Op == OpAddr || p2.Op == OpLocalAddr || p2.Op == OpSP { 559 return true 560 } 561 return p2.Op == OpArg && p1.Args[0].Op == OpSP 562 case OpArg: 563 if p2.Op == OpSP || p2.Op == OpLocalAddr { 564 return true 565 } 566 case OpSP: 567 return p2.Op == OpAddr || p2.Op == OpLocalAddr || p2.Op == OpArg || p2.Op == OpSP 568 } 569 return false 570 } 571 572 // moveSize returns the number of bytes an aligned MOV instruction moves 573 func moveSize(align int64, c *Config) int64 { 574 switch { 575 case align%8 == 0 && c.PtrSize == 8: 576 return 8 577 case align%4 == 0: 578 return 4 579 case align%2 == 0: 580 return 2 581 } 582 return 1 583 } 584 585 // mergePoint finds a block among a's blocks which dominates b and is itself 586 // dominated by all of a's blocks. Returns nil if it can't find one. 587 // Might return nil even if one does exist. 588 func mergePoint(b *Block, a ...*Value) *Block { 589 // Walk backward from b looking for one of the a's blocks. 590 591 // Max distance 592 d := 100 593 594 for d > 0 { 595 for _, x := range a { 596 if b == x.Block { 597 goto found 598 } 599 } 600 if len(b.Preds) > 1 { 601 // Don't know which way to go back. Abort. 602 return nil 603 } 604 b = b.Preds[0].b 605 d-- 606 } 607 return nil // too far away 608 found: 609 // At this point, r is the first value in a that we find by walking backwards. 610 // if we return anything, r will be it. 611 r := b 612 613 // Keep going, counting the other a's that we find. They must all dominate r. 614 na := 0 615 for d > 0 { 616 for _, x := range a { 617 if b == x.Block { 618 na++ 619 } 620 } 621 if na == len(a) { 622 // Found all of a in a backwards walk. We can return r. 623 return r 624 } 625 if len(b.Preds) > 1 { 626 return nil 627 } 628 b = b.Preds[0].b 629 d-- 630 631 } 632 return nil // too far away 633 } 634 635 // clobber invalidates v. Returns true. 636 // clobber is used by rewrite rules to: 637 // A) make sure v is really dead and never used again. 638 // B) decrement use counts of v's args. 639 func clobber(v *Value) bool { 640 v.reset(OpInvalid) 641 // Note: leave v.Block intact. The Block field is used after clobber. 642 return true 643 } 644 645 // clobberIfDead resets v when use count is 1. Returns true. 646 // clobberIfDead is used by rewrite rules to decrement 647 // use counts of v's args when v is dead and never used. 648 func clobberIfDead(v *Value) bool { 649 if v.Uses == 1 { 650 v.reset(OpInvalid) 651 } 652 // Note: leave v.Block intact. The Block field is used after clobberIfDead. 653 return true 654 } 655 656 // noteRule is an easy way to track if a rule is matched when writing 657 // new ones. Make the rule of interest also conditional on 658 // noteRule("note to self: rule of interest matched") 659 // and that message will print when the rule matches. 660 func noteRule(s string) bool { 661 fmt.Println(s) 662 return true 663 } 664 665 // warnRule generates compiler debug output with string s when 666 // v is not in autogenerated code, cond is true and the rule has fired. 667 func warnRule(cond bool, v *Value, s string) bool { 668 if pos := v.Pos; pos.Line() > 1 && cond { 669 v.Block.Func.Warnl(pos, s) 670 } 671 return true 672 } 673 674 // for a pseudo-op like (LessThan x), extract x 675 func flagArg(v *Value) *Value { 676 if len(v.Args) != 1 || !v.Args[0].Type.IsFlags() { 677 return nil 678 } 679 return v.Args[0] 680 } 681 682 // arm64Negate finds the complement to an ARM64 condition code, 683 // for example Equal -> NotEqual or LessThan -> GreaterEqual 684 // 685 // TODO: add floating-point conditions 686 func arm64Negate(op Op) Op { 687 switch op { 688 case OpARM64LessThan: 689 return OpARM64GreaterEqual 690 case OpARM64LessThanU: 691 return OpARM64GreaterEqualU 692 case OpARM64GreaterThan: 693 return OpARM64LessEqual 694 case OpARM64GreaterThanU: 695 return OpARM64LessEqualU 696 case OpARM64LessEqual: 697 return OpARM64GreaterThan 698 case OpARM64LessEqualU: 699 return OpARM64GreaterThanU 700 case OpARM64GreaterEqual: 701 return OpARM64LessThan 702 case OpARM64GreaterEqualU: 703 return OpARM64LessThanU 704 case OpARM64Equal: 705 return OpARM64NotEqual 706 case OpARM64NotEqual: 707 return OpARM64Equal 708 default: 709 panic("unreachable") 710 } 711 } 712 713 // arm64Invert evaluates (InvertFlags op), which 714 // is the same as altering the condition codes such 715 // that the same result would be produced if the arguments 716 // to the flag-generating instruction were reversed, e.g. 717 // (InvertFlags (CMP x y)) -> (CMP y x) 718 // 719 // TODO: add floating-point conditions 720 func arm64Invert(op Op) Op { 721 switch op { 722 case OpARM64LessThan: 723 return OpARM64GreaterThan 724 case OpARM64LessThanU: 725 return OpARM64GreaterThanU 726 case OpARM64GreaterThan: 727 return OpARM64LessThan 728 case OpARM64GreaterThanU: 729 return OpARM64LessThanU 730 case OpARM64LessEqual: 731 return OpARM64GreaterEqual 732 case OpARM64LessEqualU: 733 return OpARM64GreaterEqualU 734 case OpARM64GreaterEqual: 735 return OpARM64LessEqual 736 case OpARM64GreaterEqualU: 737 return OpARM64LessEqualU 738 case OpARM64Equal, OpARM64NotEqual: 739 return op 740 default: 741 panic("unreachable") 742 } 743 } 744 745 // evaluate an ARM64 op against a flags value 746 // that is potentially constant; return 1 for true, 747 // -1 for false, and 0 for not constant. 748 func ccARM64Eval(cc interface{}, flags *Value) int { 749 op := cc.(Op) 750 fop := flags.Op 751 switch fop { 752 case OpARM64InvertFlags: 753 return -ccARM64Eval(op, flags.Args[0]) 754 case OpARM64FlagEQ: 755 switch op { 756 case OpARM64Equal, OpARM64GreaterEqual, OpARM64LessEqual, 757 OpARM64GreaterEqualU, OpARM64LessEqualU: 758 return 1 759 default: 760 return -1 761 } 762 case OpARM64FlagLT_ULT: 763 switch op { 764 case OpARM64LessThan, OpARM64LessThanU, 765 OpARM64LessEqual, OpARM64LessEqualU: 766 return 1 767 default: 768 return -1 769 } 770 case OpARM64FlagLT_UGT: 771 switch op { 772 case OpARM64LessThan, OpARM64GreaterThanU, 773 OpARM64LessEqual, OpARM64GreaterEqualU: 774 return 1 775 default: 776 return -1 777 } 778 case OpARM64FlagGT_ULT: 779 switch op { 780 case OpARM64GreaterThan, OpARM64LessThanU, 781 OpARM64GreaterEqual, OpARM64LessEqualU: 782 return 1 783 default: 784 return -1 785 } 786 case OpARM64FlagGT_UGT: 787 switch op { 788 case OpARM64GreaterThan, OpARM64GreaterThanU, 789 OpARM64GreaterEqual, OpARM64GreaterEqualU: 790 return 1 791 default: 792 return -1 793 } 794 default: 795 return 0 796 } 797 } 798 799 // logRule logs the use of the rule s. This will only be enabled if 800 // rewrite rules were generated with the -log option, see gen/rulegen.go. 801 func logRule(s string) { 802 if ruleFile == nil { 803 // Open a log file to write log to. We open in append 804 // mode because all.bash runs the compiler lots of times, 805 // and we want the concatenation of all of those logs. 806 // This means, of course, that users need to rm the old log 807 // to get fresh data. 808 // TODO: all.bash runs compilers in parallel. Need to synchronize logging somehow? 809 w, err := os.OpenFile(filepath.Join(os.Getenv("GOROOT"), "src", "rulelog"), 810 os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) 811 if err != nil { 812 panic(err) 813 } 814 ruleFile = w 815 } 816 _, err := fmt.Fprintf(ruleFile, "rewrite %s\n", s) 817 if err != nil { 818 panic(err) 819 } 820 } 821 822 var ruleFile io.Writer 823 824 func min(x, y int64) int64 { 825 if x < y { 826 return x 827 } 828 return y 829 } 830 831 func isConstZero(v *Value) bool { 832 switch v.Op { 833 case OpConstNil: 834 return true 835 case OpConst64, OpConst32, OpConst16, OpConst8, OpConstBool, OpConst32F, OpConst64F: 836 return v.AuxInt == 0 837 } 838 return false 839 } 840 841 // reciprocalExact64 reports whether 1/c is exactly representable. 842 func reciprocalExact64(c float64) bool { 843 b := math.Float64bits(c) 844 man := b & (1<<52 - 1) 845 if man != 0 { 846 return false // not a power of 2, denormal, or NaN 847 } 848 exp := b >> 52 & (1<<11 - 1) 849 // exponent bias is 0x3ff. So taking the reciprocal of a number 850 // changes the exponent to 0x7fe-exp. 851 switch exp { 852 case 0: 853 return false // ±0 854 case 0x7ff: 855 return false // ±inf 856 case 0x7fe: 857 return false // exponent is not representable 858 default: 859 return true 860 } 861 } 862 863 // reciprocalExact32 reports whether 1/c is exactly representable. 864 func reciprocalExact32(c float32) bool { 865 b := math.Float32bits(c) 866 man := b & (1<<23 - 1) 867 if man != 0 { 868 return false // not a power of 2, denormal, or NaN 869 } 870 exp := b >> 23 & (1<<8 - 1) 871 // exponent bias is 0x7f. So taking the reciprocal of a number 872 // changes the exponent to 0xfe-exp. 873 switch exp { 874 case 0: 875 return false // ±0 876 case 0xff: 877 return false // ±inf 878 case 0xfe: 879 return false // exponent is not representable 880 default: 881 return true 882 } 883 } 884 885 // check if an immediate can be directly encoded into an ARM's instruction 886 func isARMImmRot(v uint32) bool { 887 for i := 0; i < 16; i++ { 888 if v&^0xff == 0 { 889 return true 890 } 891 v = v<<2 | v>>30 892 } 893 894 return false 895 } 896 897 // overlap reports whether the ranges given by the given offset and 898 // size pairs overlap. 899 func overlap(offset1, size1, offset2, size2 int64) bool { 900 if offset1 >= offset2 && offset2+size2 > offset1 { 901 return true 902 } 903 if offset2 >= offset1 && offset1+size1 > offset2 { 904 return true 905 } 906 return false 907 } 908 909 func areAdjacentOffsets(off1, off2, size int64) bool { 910 return off1+size == off2 || off1 == off2+size 911 } 912 913 // check if value zeroes out upper 32-bit of 64-bit register. 914 // depth limits recursion depth. In AMD64.rules 3 is used as limit, 915 // because it catches same amount of cases as 4. 916 func zeroUpper32Bits(x *Value, depth int) bool { 917 switch x.Op { 918 case OpAMD64MOVLconst, OpAMD64MOVLload, OpAMD64MOVLQZX, OpAMD64MOVLloadidx1, 919 OpAMD64MOVWload, OpAMD64MOVWloadidx1, OpAMD64MOVBload, OpAMD64MOVBloadidx1, 920 OpAMD64MOVLloadidx4, OpAMD64ADDLload, OpAMD64SUBLload, OpAMD64ANDLload, 921 OpAMD64ORLload, OpAMD64XORLload, OpAMD64CVTTSD2SL, 922 OpAMD64ADDL, OpAMD64ADDLconst, OpAMD64SUBL, OpAMD64SUBLconst, 923 OpAMD64ANDL, OpAMD64ANDLconst, OpAMD64ORL, OpAMD64ORLconst, 924 OpAMD64XORL, OpAMD64XORLconst, OpAMD64NEGL, OpAMD64NOTL: 925 return true 926 case OpArg: 927 return x.Type.Width == 4 928 case OpPhi, OpSelect0, OpSelect1: 929 // Phis can use each-other as an arguments, instead of tracking visited values, 930 // just limit recursion depth. 931 if depth <= 0 { 932 return false 933 } 934 for i := range x.Args { 935 if !zeroUpper32Bits(x.Args[i], depth-1) { 936 return false 937 } 938 } 939 return true 940 941 } 942 return false 943 } 944 945 // zeroUpper48Bits is similar to zeroUpper32Bits, but for upper 48 bits 946 func zeroUpper48Bits(x *Value, depth int) bool { 947 switch x.Op { 948 case OpAMD64MOVWQZX, OpAMD64MOVWload, OpAMD64MOVWloadidx1, OpAMD64MOVWloadidx2: 949 return true 950 case OpArg: 951 return x.Type.Width == 2 952 case OpPhi, OpSelect0, OpSelect1: 953 // Phis can use each-other as an arguments, instead of tracking visited values, 954 // just limit recursion depth. 955 if depth <= 0 { 956 return false 957 } 958 for i := range x.Args { 959 if !zeroUpper48Bits(x.Args[i], depth-1) { 960 return false 961 } 962 } 963 return true 964 965 } 966 return false 967 } 968 969 // zeroUpper56Bits is similar to zeroUpper32Bits, but for upper 56 bits 970 func zeroUpper56Bits(x *Value, depth int) bool { 971 switch x.Op { 972 case OpAMD64MOVBQZX, OpAMD64MOVBload, OpAMD64MOVBloadidx1: 973 return true 974 case OpArg: 975 return x.Type.Width == 1 976 case OpPhi, OpSelect0, OpSelect1: 977 // Phis can use each-other as an arguments, instead of tracking visited values, 978 // just limit recursion depth. 979 if depth <= 0 { 980 return false 981 } 982 for i := range x.Args { 983 if !zeroUpper56Bits(x.Args[i], depth-1) { 984 return false 985 } 986 } 987 return true 988 989 } 990 return false 991 } 992 993 // isInlinableMemmove reports whether the given arch performs a Move of the given size 994 // faster than memmove. It will only return true if replacing the memmove with a Move is 995 // safe, either because Move is small or because the arguments are disjoint. 996 // This is used as a check for replacing memmove with Move ops. 997 func isInlinableMemmove(dst, src *Value, sz int64, c *Config) bool { 998 // It is always safe to convert memmove into Move when its arguments are disjoint. 999 // Move ops may or may not be faster for large sizes depending on how the platform 1000 // lowers them, so we only perform this optimization on platforms that we know to 1001 // have fast Move ops. 1002 switch c.arch { 1003 case "amd64", "amd64p32": 1004 return sz <= 16 || (sz < 1024 && disjoint(dst, sz, src, sz)) 1005 case "386", "ppc64", "ppc64le", "arm64": 1006 return sz <= 8 1007 case "s390x": 1008 return sz <= 8 || disjoint(dst, sz, src, sz) 1009 case "arm", "mips", "mips64", "mipsle", "mips64le": 1010 return sz <= 4 1011 } 1012 return false 1013 } 1014 1015 // encodes the lsb and width for arm64 bitfield ops into the expected auxInt format. 1016 func arm64BFAuxInt(lsb, width int64) int64 { 1017 if lsb < 0 || lsb > 63 { 1018 panic("ARM64 bit field lsb constant out of range") 1019 } 1020 if width < 1 || width > 64 { 1021 panic("ARM64 bit field width constant out of range") 1022 } 1023 return width | lsb<<8 1024 } 1025 1026 // returns the lsb part of the auxInt field of arm64 bitfield ops. 1027 func getARM64BFlsb(bfc int64) int64 { 1028 return int64(uint64(bfc) >> 8) 1029 } 1030 1031 // returns the width part of the auxInt field of arm64 bitfield ops. 1032 func getARM64BFwidth(bfc int64) int64 { 1033 return bfc & 0xff 1034 } 1035 1036 // checks if mask >> rshift applied at lsb is a valid arm64 bitfield op mask. 1037 func isARM64BFMask(lsb, mask, rshift int64) bool { 1038 shiftedMask := int64(uint64(mask) >> uint64(rshift)) 1039 return shiftedMask != 0 && isPowerOfTwo(shiftedMask+1) && nto(shiftedMask)+lsb < 64 1040 } 1041 1042 // returns the bitfield width of mask >> rshift for arm64 bitfield ops 1043 func arm64BFWidth(mask, rshift int64) int64 { 1044 shiftedMask := int64(uint64(mask) >> uint64(rshift)) 1045 if shiftedMask == 0 { 1046 panic("ARM64 BF mask is zero") 1047 } 1048 return nto(shiftedMask) 1049 } 1050 1051 // sizeof returns the size of t in bytes. 1052 // It will panic if t is not a *types.Type. 1053 func sizeof(t interface{}) int64 { 1054 return t.(*types.Type).Size() 1055 } 1056 1057 // alignof returns the alignment of t in bytes. 1058 // It will panic if t is not a *types.Type. 1059 func alignof(t interface{}) int64 { 1060 return t.(*types.Type).Alignment() 1061 } 1062 1063 // registerizable reports whether t is a primitive type that fits in 1064 // a register. It assumes float64 values will always fit into registers 1065 // even if that isn't strictly true. 1066 // It will panic if t is not a *types.Type. 1067 func registerizable(b *Block, t interface{}) bool { 1068 typ := t.(*types.Type) 1069 if typ.IsPtrShaped() || typ.IsFloat() { 1070 return true 1071 } 1072 if typ.IsInteger() { 1073 return typ.Size() <= b.Func.Config.RegSize 1074 } 1075 return false 1076 } 1077 1078 // needRaceCleanup reports whether this call to racefuncenter/exit isn't needed. 1079 func needRaceCleanup(sym interface{}, v *Value) bool { 1080 f := v.Block.Func 1081 if !f.Config.Race { 1082 return false 1083 } 1084 if !isSameSym(sym, "runtime.racefuncenter") && !isSameSym(sym, "runtime.racefuncexit") { 1085 return false 1086 } 1087 for _, b := range f.Blocks { 1088 for _, v := range b.Values { 1089 if v.Op == OpStaticCall { 1090 switch v.Aux.(fmt.Stringer).String() { 1091 case "runtime.racefuncenter", "runtime.racefuncexit", "runtime.panicindex", 1092 "runtime.panicslice", "runtime.panicdivide", "runtime.panicwrap": 1093 // Check for racefuncenter will encounter racefuncexit and vice versa. 1094 // Allow calls to panic* 1095 default: 1096 // If we encountered any call, we need to keep racefunc*, 1097 // for accurate stacktraces. 1098 return false 1099 } 1100 } 1101 } 1102 } 1103 return true 1104 } 1105 1106 // symIsRO reports whether sym is a read-only global. 1107 func symIsRO(sym interface{}) bool { 1108 lsym := sym.(*obj.LSym) 1109 return lsym.Type == objabi.SRODATA && len(lsym.R) == 0 1110 } 1111 1112 // read8 reads one byte from the read-only global sym at offset off. 1113 func read8(sym interface{}, off int64) uint8 { 1114 lsym := sym.(*obj.LSym) 1115 return lsym.P[off] 1116 } 1117 1118 // read16 reads two bytes from the read-only global sym at offset off. 1119 func read16(sym interface{}, off int64, bigEndian bool) uint16 { 1120 lsym := sym.(*obj.LSym) 1121 if bigEndian { 1122 return binary.BigEndian.Uint16(lsym.P[off:]) 1123 } else { 1124 return binary.LittleEndian.Uint16(lsym.P[off:]) 1125 } 1126 } 1127 1128 // read32 reads four bytes from the read-only global sym at offset off. 1129 func read32(sym interface{}, off int64, bigEndian bool) uint32 { 1130 lsym := sym.(*obj.LSym) 1131 if bigEndian { 1132 return binary.BigEndian.Uint32(lsym.P[off:]) 1133 } else { 1134 return binary.LittleEndian.Uint32(lsym.P[off:]) 1135 } 1136 } 1137 1138 // read64 reads eight bytes from the read-only global sym at offset off. 1139 func read64(sym interface{}, off int64, bigEndian bool) uint64 { 1140 lsym := sym.(*obj.LSym) 1141 if bigEndian { 1142 return binary.BigEndian.Uint64(lsym.P[off:]) 1143 } else { 1144 return binary.LittleEndian.Uint64(lsym.P[off:]) 1145 } 1146 }