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  }