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