github.com/yukk001/go1.10.8@v0.0.0-20190813125351-6df2d3982e20/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  // 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  }