github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/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 "fmt" 11 "io" 12 "math" 13 "os" 14 "path/filepath" 15 ) 16 17 func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter) { 18 // repeat rewrites until we find no more rewrites 19 for { 20 change := false 21 for _, b := range f.Blocks { 22 if b.Control != nil && b.Control.Op == OpCopy { 23 for b.Control.Op == OpCopy { 24 b.SetControl(b.Control.Args[0]) 25 } 26 } 27 if rb(b) { 28 change = true 29 } 30 for _, v := range b.Values { 31 change = phielimValue(v) || change 32 33 // Eliminate copy inputs. 34 // If any copy input becomes unused, mark it 35 // as invalid and discard its argument. Repeat 36 // recursively on the discarded argument. 37 // This phase helps remove phantom "dead copy" uses 38 // of a value so that a x.Uses==1 rule condition 39 // fires reliably. 40 for i, a := range v.Args { 41 if a.Op != OpCopy { 42 continue 43 } 44 v.SetArg(i, copySource(a)) 45 change = true 46 for a.Uses == 0 { 47 b := a.Args[0] 48 a.reset(OpInvalid) 49 a = b 50 } 51 } 52 53 // apply rewrite function 54 if rv(v) { 55 change = true 56 } 57 } 58 } 59 if !change { 60 break 61 } 62 } 63 // remove clobbered values 64 for _, b := range f.Blocks { 65 j := 0 66 for i, v := range b.Values { 67 if v.Op == OpInvalid { 68 f.freeValue(v) 69 continue 70 } 71 if i != j { 72 b.Values[j] = v 73 } 74 j++ 75 } 76 if j != len(b.Values) { 77 tail := b.Values[j:] 78 for j := range tail { 79 tail[j] = nil 80 } 81 b.Values = b.Values[:j] 82 } 83 } 84 } 85 86 // Common functions called from rewriting rules 87 88 func is64BitFloat(t *types.Type) bool { 89 return t.Size() == 8 && t.IsFloat() 90 } 91 92 func is32BitFloat(t *types.Type) bool { 93 return t.Size() == 4 && t.IsFloat() 94 } 95 96 func is64BitInt(t *types.Type) bool { 97 return t.Size() == 8 && t.IsInteger() 98 } 99 100 func is32BitInt(t *types.Type) bool { 101 return t.Size() == 4 && t.IsInteger() 102 } 103 104 func is16BitInt(t *types.Type) bool { 105 return t.Size() == 2 && t.IsInteger() 106 } 107 108 func is8BitInt(t *types.Type) bool { 109 return t.Size() == 1 && t.IsInteger() 110 } 111 112 func isPtr(t *types.Type) bool { 113 return t.IsPtrShaped() 114 } 115 116 func isSigned(t *types.Type) bool { 117 return t.IsSigned() 118 } 119 120 func typeSize(t *types.Type) int64 { 121 return t.Size() 122 } 123 124 // mergeSym merges two symbolic offsets. There is no real merging of 125 // offsets, we just pick the non-nil one. 126 func mergeSym(x, y interface{}) interface{} { 127 if x == nil { 128 return y 129 } 130 if y == nil { 131 return x 132 } 133 panic(fmt.Sprintf("mergeSym with two non-nil syms %s %s", x, y)) 134 } 135 func canMergeSym(x, y interface{}) bool { 136 return x == nil || y == nil 137 } 138 139 // canMergeLoad reports whether the load can be merged into target without 140 // invalidating the schedule. 141 // It also checks that the other non-load argument x is something we 142 // are ok with clobbering (all our current load+op instructions clobber 143 // their input register). 144 func canMergeLoad(target, load, x *Value) bool { 145 if target.Block.ID != load.Block.ID { 146 // If the load is in a different block do not merge it. 147 return false 148 } 149 150 // We can't merge the load into the target if the load 151 // has more than one use. 152 if load.Uses != 1 { 153 return false 154 } 155 156 // The register containing x is going to get clobbered. 157 // Don't merge if we still need the value of x. 158 // We don't have liveness information here, but we can 159 // approximate x dying with: 160 // 1) target is x's only use. 161 // 2) target is not in a deeper loop than x. 162 if x.Uses != 1 { 163 return false 164 } 165 loopnest := x.Block.Func.loopnest() 166 loopnest.calculateDepths() 167 if loopnest.depth(target.Block.ID) > loopnest.depth(x.Block.ID) { 168 return false 169 } 170 171 mem := load.MemoryArg() 172 173 // We need the load's memory arg to still be alive at target. That 174 // can't be the case if one of target's args depends on a memory 175 // state that is a successor of load's memory arg. 176 // 177 // For example, it would be invalid to merge load into target in 178 // the following situation because newmem has killed oldmem 179 // before target is reached: 180 // load = read ... oldmem 181 // newmem = write ... oldmem 182 // arg0 = read ... newmem 183 // target = add arg0 load 184 // 185 // If the argument comes from a different block then we can exclude 186 // it immediately because it must dominate load (which is in the 187 // same block as target). 188 var args []*Value 189 for _, a := range target.Args { 190 if a != load && a.Block.ID == target.Block.ID { 191 args = append(args, a) 192 } 193 } 194 195 // memPreds contains memory states known to be predecessors of load's 196 // memory state. It is lazily initialized. 197 var memPreds map[*Value]bool 198 search: 199 for i := 0; len(args) > 0; i++ { 200 const limit = 100 201 if i >= limit { 202 // Give up if we have done a lot of iterations. 203 return false 204 } 205 v := args[len(args)-1] 206 args = args[:len(args)-1] 207 if target.Block.ID != v.Block.ID { 208 // Since target and load are in the same block 209 // we can stop searching when we leave the block. 210 continue search 211 } 212 if v.Op == OpPhi { 213 // A Phi implies we have reached the top of the block. 214 // The memory phi, if it exists, is always 215 // the first logical store in the block. 216 continue search 217 } 218 if v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() { 219 // We could handle this situation however it is likely 220 // to be very rare. 221 return false 222 } 223 if v.Type.IsMemory() { 224 if memPreds == nil { 225 // Initialise a map containing memory states 226 // known to be predecessors of load's memory 227 // state. 228 memPreds = make(map[*Value]bool) 229 m := mem 230 const limit = 50 231 for i := 0; i < limit; i++ { 232 if m.Op == OpPhi { 233 // The memory phi, if it exists, is always 234 // the first logical store in the block. 235 break 236 } 237 if m.Block.ID != target.Block.ID { 238 break 239 } 240 if !m.Type.IsMemory() { 241 break 242 } 243 memPreds[m] = true 244 if len(m.Args) == 0 { 245 break 246 } 247 m = m.MemoryArg() 248 } 249 } 250 251 // We can merge if v is a predecessor of mem. 252 // 253 // For example, we can merge load into target in the 254 // following scenario: 255 // x = read ... v 256 // mem = write ... v 257 // load = read ... mem 258 // target = add x load 259 if memPreds[v] { 260 continue search 261 } 262 return false 263 } 264 if len(v.Args) > 0 && v.Args[len(v.Args)-1] == mem { 265 // If v takes mem as an input then we know mem 266 // is valid at this point. 267 continue search 268 } 269 for _, a := range v.Args { 270 if target.Block.ID == a.Block.ID { 271 args = append(args, a) 272 } 273 } 274 } 275 276 return true 277 } 278 279 // isSameSym returns whether sym is the same as the given named symbol 280 func isSameSym(sym interface{}, name string) bool { 281 s, ok := sym.(fmt.Stringer) 282 return ok && s.String() == name 283 } 284 285 // nlz returns the number of leading zeros. 286 func nlz(x int64) int64 { 287 // log2(0) == 1, so nlz(0) == 64 288 return 63 - log2(x) 289 } 290 291 // ntz returns the number of trailing zeros. 292 func ntz(x int64) int64 { 293 return 64 - nlz(^x&(x-1)) 294 } 295 296 func oneBit(x int64) bool { 297 return nlz(x)+ntz(x) == 63 298 } 299 300 // nlo returns the number of leading ones. 301 func nlo(x int64) int64 { 302 return nlz(^x) 303 } 304 305 // nto returns the number of trailing ones. 306 func nto(x int64) int64 { 307 return ntz(^x) 308 } 309 310 // log2 returns logarithm in base 2 of uint64(n), with log2(0) = -1. 311 // Rounds down. 312 func log2(n int64) (l int64) { 313 l = -1 314 x := uint64(n) 315 for ; x >= 0x8000; x >>= 16 { 316 l += 16 317 } 318 if x >= 0x80 { 319 x >>= 8 320 l += 8 321 } 322 if x >= 0x8 { 323 x >>= 4 324 l += 4 325 } 326 if x >= 0x2 { 327 x >>= 2 328 l += 2 329 } 330 if x >= 0x1 { 331 l++ 332 } 333 return 334 } 335 336 // isPowerOfTwo reports whether n is a power of 2. 337 func isPowerOfTwo(n int64) bool { 338 return n > 0 && n&(n-1) == 0 339 } 340 341 // is32Bit reports whether n can be represented as a signed 32 bit integer. 342 func is32Bit(n int64) bool { 343 return n == int64(int32(n)) 344 } 345 346 // is16Bit reports whether n can be represented as a signed 16 bit integer. 347 func is16Bit(n int64) bool { 348 return n == int64(int16(n)) 349 } 350 351 // isU12Bit reports whether n can be represented as an unsigned 12 bit integer. 352 func isU12Bit(n int64) bool { 353 return 0 <= n && n < (1<<12) 354 } 355 356 // isU16Bit reports whether n can be represented as an unsigned 16 bit integer. 357 func isU16Bit(n int64) bool { 358 return n == int64(uint16(n)) 359 } 360 361 // isU32Bit reports whether n can be represented as an unsigned 32 bit integer. 362 func isU32Bit(n int64) bool { 363 return n == int64(uint32(n)) 364 } 365 366 // is20Bit reports whether n can be represented as a signed 20 bit integer. 367 func is20Bit(n int64) bool { 368 return -(1<<19) <= n && n < (1<<19) 369 } 370 371 // b2i translates a boolean value to 0 or 1 for assigning to auxInt. 372 func b2i(b bool) int64 { 373 if b { 374 return 1 375 } 376 return 0 377 } 378 379 // i2f is used in rules for converting from an AuxInt to a float. 380 func i2f(i int64) float64 { 381 return math.Float64frombits(uint64(i)) 382 } 383 384 // i2f32 is used in rules for converting from an AuxInt to a float32. 385 func i2f32(i int64) float32 { 386 return float32(math.Float64frombits(uint64(i))) 387 } 388 389 // f2i is used in the rules for storing a float in AuxInt. 390 func f2i(f float64) int64 { 391 return int64(math.Float64bits(f)) 392 } 393 394 // uaddOvf returns true if unsigned a+b would overflow. 395 func uaddOvf(a, b int64) bool { 396 return uint64(a)+uint64(b) < uint64(a) 397 } 398 399 // de-virtualize an InterCall 400 // 'sym' is the symbol for the itab 401 func devirt(v *Value, sym interface{}, offset int64) *obj.LSym { 402 f := v.Block.Func 403 n, ok := sym.(*obj.LSym) 404 if !ok { 405 return nil 406 } 407 lsym := f.fe.DerefItab(n, offset) 408 if f.pass.debug > 0 { 409 if lsym != nil { 410 f.Warnl(v.Pos, "de-virtualizing call") 411 } else { 412 f.Warnl(v.Pos, "couldn't de-virtualize call") 413 } 414 } 415 return lsym 416 } 417 418 // isSamePtr reports whether p1 and p2 point to the same address. 419 func isSamePtr(p1, p2 *Value) bool { 420 if p1 == p2 { 421 return true 422 } 423 if p1.Op != p2.Op { 424 return false 425 } 426 switch p1.Op { 427 case OpOffPtr: 428 return p1.AuxInt == p2.AuxInt && isSamePtr(p1.Args[0], p2.Args[0]) 429 case OpAddr: 430 // OpAddr's 0th arg is either OpSP or OpSB, which means that it is uniquely identified by its Op. 431 // Checking for value equality only works after [z]cse has run. 432 return p1.Aux == p2.Aux && p1.Args[0].Op == p2.Args[0].Op 433 case OpAddPtr: 434 return p1.Args[1] == p2.Args[1] && isSamePtr(p1.Args[0], p2.Args[0]) 435 } 436 return false 437 } 438 439 // moveSize returns the number of bytes an aligned MOV instruction moves 440 func moveSize(align int64, c *Config) int64 { 441 switch { 442 case align%8 == 0 && c.PtrSize == 8: 443 return 8 444 case align%4 == 0: 445 return 4 446 case align%2 == 0: 447 return 2 448 } 449 return 1 450 } 451 452 // mergePoint finds a block among a's blocks which dominates b and is itself 453 // dominated by all of a's blocks. Returns nil if it can't find one. 454 // Might return nil even if one does exist. 455 func mergePoint(b *Block, a ...*Value) *Block { 456 // Walk backward from b looking for one of the a's blocks. 457 458 // Max distance 459 d := 100 460 461 for d > 0 { 462 for _, x := range a { 463 if b == x.Block { 464 goto found 465 } 466 } 467 if len(b.Preds) > 1 { 468 // Don't know which way to go back. Abort. 469 return nil 470 } 471 b = b.Preds[0].b 472 d-- 473 } 474 return nil // too far away 475 found: 476 // At this point, r is the first value in a that we find by walking backwards. 477 // if we return anything, r will be it. 478 r := b 479 480 // Keep going, counting the other a's that we find. They must all dominate r. 481 na := 0 482 for d > 0 { 483 for _, x := range a { 484 if b == x.Block { 485 na++ 486 } 487 } 488 if na == len(a) { 489 // Found all of a in a backwards walk. We can return r. 490 return r 491 } 492 if len(b.Preds) > 1 { 493 return nil 494 } 495 b = b.Preds[0].b 496 d-- 497 498 } 499 return nil // too far away 500 } 501 502 // clobber invalidates v. Returns true. 503 // clobber is used by rewrite rules to: 504 // A) make sure v is really dead and never used again. 505 // B) decrement use counts of v's args. 506 func clobber(v *Value) bool { 507 v.reset(OpInvalid) 508 // Note: leave v.Block intact. The Block field is used after clobber. 509 return true 510 } 511 512 // noteRule is an easy way to track if a rule is matched when writing 513 // new ones. Make the rule of interest also conditional on 514 // noteRule("note to self: rule of interest matched") 515 // and that message will print when the rule matches. 516 func noteRule(s string) bool { 517 fmt.Println(s) 518 return true 519 } 520 521 // warnRule generates a compiler debug output with string s when 522 // cond is true and the rule is fired. 523 func warnRule(cond bool, v *Value, s string) bool { 524 if cond { 525 v.Block.Func.Warnl(v.Pos, s) 526 } 527 return true 528 } 529 530 // logRule logs the use of the rule s. This will only be enabled if 531 // rewrite rules were generated with the -log option, see gen/rulegen.go. 532 func logRule(s string) { 533 if ruleFile == nil { 534 // Open a log file to write log to. We open in append 535 // mode because all.bash runs the compiler lots of times, 536 // and we want the concatenation of all of those logs. 537 // This means, of course, that users need to rm the old log 538 // to get fresh data. 539 // TODO: all.bash runs compilers in parallel. Need to synchronize logging somehow? 540 w, err := os.OpenFile(filepath.Join(os.Getenv("GOROOT"), "src", "rulelog"), 541 os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) 542 if err != nil { 543 panic(err) 544 } 545 ruleFile = w 546 } 547 _, err := fmt.Fprintf(ruleFile, "rewrite %s\n", s) 548 if err != nil { 549 panic(err) 550 } 551 } 552 553 var ruleFile io.Writer 554 555 func min(x, y int64) int64 { 556 if x < y { 557 return x 558 } 559 return y 560 } 561 562 func isConstZero(v *Value) bool { 563 switch v.Op { 564 case OpConstNil: 565 return true 566 case OpConst64, OpConst32, OpConst16, OpConst8, OpConstBool, OpConst32F, OpConst64F: 567 return v.AuxInt == 0 568 } 569 return false 570 } 571 572 // reciprocalExact64 reports whether 1/c is exactly representable. 573 func reciprocalExact64(c float64) bool { 574 b := math.Float64bits(c) 575 man := b & (1<<52 - 1) 576 if man != 0 { 577 return false // not a power of 2, denormal, or NaN 578 } 579 exp := b >> 52 & (1<<11 - 1) 580 // exponent bias is 0x3ff. So taking the reciprocal of a number 581 // changes the exponent to 0x7fe-exp. 582 switch exp { 583 case 0: 584 return false // ±0 585 case 0x7ff: 586 return false // ±inf 587 case 0x7fe: 588 return false // exponent is not representable 589 default: 590 return true 591 } 592 } 593 594 // reciprocalExact32 reports whether 1/c is exactly representable. 595 func reciprocalExact32(c float32) bool { 596 b := math.Float32bits(c) 597 man := b & (1<<23 - 1) 598 if man != 0 { 599 return false // not a power of 2, denormal, or NaN 600 } 601 exp := b >> 23 & (1<<8 - 1) 602 // exponent bias is 0x7f. So taking the reciprocal of a number 603 // changes the exponent to 0xfe-exp. 604 switch exp { 605 case 0: 606 return false // ±0 607 case 0xff: 608 return false // ±inf 609 case 0xfe: 610 return false // exponent is not representable 611 default: 612 return true 613 } 614 } 615 616 // check if an immediate can be directly encoded into an ARM's instruction 617 func isARMImmRot(v uint32) bool { 618 for i := 0; i < 16; i++ { 619 if v&^0xff == 0 { 620 return true 621 } 622 v = v<<2 | v>>30 623 } 624 625 return false 626 } 627 628 // overlap reports whether the ranges given by the given offset and 629 // size pairs overlap. 630 func overlap(offset1, size1, offset2, size2 int64) bool { 631 if offset1 >= offset2 && offset2+size2 > offset1 { 632 return true 633 } 634 if offset2 >= offset1 && offset1+size1 > offset2 { 635 return true 636 } 637 return false 638 } 639 640 // check if value zeroes out upper 32-bit of 64-bit register. 641 // depth limits recursion depth. In AMD64.rules 3 is used as limit, 642 // because it catches same amount of cases as 4. 643 func zeroUpper32Bits(x *Value, depth int) bool { 644 switch x.Op { 645 case OpAMD64MOVLconst, OpAMD64MOVLload, OpAMD64MOVLQZX, OpAMD64MOVLloadidx1, 646 OpAMD64MOVWload, OpAMD64MOVWloadidx1, OpAMD64MOVBload, OpAMD64MOVBloadidx1, 647 OpAMD64MOVLloadidx4, OpAMD64ADDLmem, OpAMD64SUBLmem, OpAMD64ANDLmem, 648 OpAMD64ORLmem, OpAMD64XORLmem, OpAMD64CVTTSD2SL, 649 OpAMD64ADDL, OpAMD64ADDLconst, OpAMD64SUBL, OpAMD64SUBLconst, 650 OpAMD64ANDL, OpAMD64ANDLconst, OpAMD64ORL, OpAMD64ORLconst, 651 OpAMD64XORL, OpAMD64XORLconst, OpAMD64NEGL, OpAMD64NOTL: 652 return true 653 case OpArg, OpSelect0, OpSelect1: 654 return x.Type.Width == 4 655 case OpPhi: 656 // Phis can use each-other as an arguments, instead of tracking visited values, 657 // just limit recursion depth. 658 if depth <= 0 { 659 return false 660 } 661 for i := range x.Args { 662 if !zeroUpper32Bits(x.Args[i], depth-1) { 663 return false 664 } 665 } 666 return true 667 668 } 669 return false 670 } 671 672 // inlineablememmovesize reports whether the given arch performs OpMove of the given size 673 // faster than memmove and in a safe way when src and dst overlap. 674 // This is used as a check for replacing memmove with OpMove. 675 func isInlinableMemmoveSize(sz int64, c *Config) bool { 676 switch c.arch { 677 case "amd64", "amd64p32": 678 return sz <= 16 679 case "386", "ppc64", "s390x", "ppc64le": 680 return sz <= 8 681 case "arm", "mips", "mips64", "mipsle", "mips64le": 682 return sz <= 4 683 } 684 return false 685 }