github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/cmd/compile/internal/ssa/prove.go (about)

     1  // Copyright 2016 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  	"fmt"
     9  	"math"
    10  )
    11  
    12  type branch int
    13  
    14  const (
    15  	unknown branch = iota
    16  	positive
    17  	negative
    18  )
    19  
    20  // relation represents the set of possible relations between
    21  // pairs of variables (v, w). Without a priori knowledge the
    22  // mask is lt | eq | gt meaning v can be less than, equal to or
    23  // greater than w. When the execution path branches on the condition
    24  // `v op w` the set of relations is updated to exclude any
    25  // relation not possible due to `v op w` being true (or false).
    26  //
    27  // E.g.
    28  //
    29  // r := relation(...)
    30  //
    31  // if v < w {
    32  //   newR := r & lt
    33  // }
    34  // if v >= w {
    35  //   newR := r & (eq|gt)
    36  // }
    37  // if v != w {
    38  //   newR := r & (lt|gt)
    39  // }
    40  type relation uint
    41  
    42  const (
    43  	lt relation = 1 << iota
    44  	eq
    45  	gt
    46  )
    47  
    48  var relationStrings = [...]string{
    49  	0: "none", lt: "<", eq: "==", lt | eq: "<=",
    50  	gt: ">", gt | lt: "!=", gt | eq: ">=", gt | eq | lt: "any",
    51  }
    52  
    53  func (r relation) String() string {
    54  	if r < relation(len(relationStrings)) {
    55  		return relationStrings[r]
    56  	}
    57  	return fmt.Sprintf("relation(%d)", uint(r))
    58  }
    59  
    60  // domain represents the domain of a variable pair in which a set
    61  // of relations is known. For example, relations learned for unsigned
    62  // pairs cannot be transferred to signed pairs because the same bit
    63  // representation can mean something else.
    64  type domain uint
    65  
    66  const (
    67  	signed domain = 1 << iota
    68  	unsigned
    69  	pointer
    70  	boolean
    71  )
    72  
    73  var domainStrings = [...]string{
    74  	"signed", "unsigned", "pointer", "boolean",
    75  }
    76  
    77  func (d domain) String() string {
    78  	s := ""
    79  	for i, ds := range domainStrings {
    80  		if d&(1<<uint(i)) != 0 {
    81  			if len(s) != 0 {
    82  				s += "|"
    83  			}
    84  			s += ds
    85  			d &^= 1 << uint(i)
    86  		}
    87  	}
    88  	if d != 0 {
    89  		if len(s) != 0 {
    90  			s += "|"
    91  		}
    92  		s += fmt.Sprintf("0x%x", uint(d))
    93  	}
    94  	return s
    95  }
    96  
    97  type pair struct {
    98  	v, w *Value // a pair of values, ordered by ID.
    99  	// v can be nil, to mean the zero value.
   100  	// for booleans the zero value (v == nil) is false.
   101  	d domain
   102  }
   103  
   104  // fact is a pair plus a relation for that pair.
   105  type fact struct {
   106  	p pair
   107  	r relation
   108  }
   109  
   110  // a limit records known upper and lower bounds for a value.
   111  type limit struct {
   112  	min, max   int64  // min <= value <= max, signed
   113  	umin, umax uint64 // umin <= value <= umax, unsigned
   114  }
   115  
   116  func (l limit) String() string {
   117  	return fmt.Sprintf("sm,SM,um,UM=%d,%d,%d,%d", l.min, l.max, l.umin, l.umax)
   118  }
   119  
   120  func (l limit) intersect(l2 limit) limit {
   121  	if l.min < l2.min {
   122  		l.min = l2.min
   123  	}
   124  	if l.umin < l2.umin {
   125  		l.umin = l2.umin
   126  	}
   127  	if l.max > l2.max {
   128  		l.max = l2.max
   129  	}
   130  	if l.umax > l2.umax {
   131  		l.umax = l2.umax
   132  	}
   133  	return l
   134  }
   135  
   136  var noLimit = limit{math.MinInt64, math.MaxInt64, 0, math.MaxUint64}
   137  
   138  // a limitFact is a limit known for a particular value.
   139  type limitFact struct {
   140  	vid   ID
   141  	limit limit
   142  }
   143  
   144  // factsTable keeps track of relations between pairs of values.
   145  //
   146  // The fact table logic is sound, but incomplete. Outside of a few
   147  // special cases, it performs no deduction or arithmetic. While there
   148  // are known decision procedures for this, the ad hoc approach taken
   149  // by the facts table is effective for real code while remaining very
   150  // efficient.
   151  type factsTable struct {
   152  	// unsat is true if facts contains a contradiction.
   153  	//
   154  	// Note that the factsTable logic is incomplete, so if unsat
   155  	// is false, the assertions in factsTable could be satisfiable
   156  	// *or* unsatisfiable.
   157  	unsat      bool // true if facts contains a contradiction
   158  	unsatDepth int  // number of unsat checkpoints
   159  
   160  	facts map[pair]relation // current known set of relation
   161  	stack []fact            // previous sets of relations
   162  
   163  	// order is a couple of partial order sets that record information
   164  	// about relations between SSA values in the signed and unsigned
   165  	// domain.
   166  	order [2]*poset
   167  
   168  	// known lower and upper bounds on individual values.
   169  	limits     map[ID]limit
   170  	limitStack []limitFact // previous entries
   171  
   172  	// For each slice s, a map from s to a len(s)/cap(s) value (if any)
   173  	// TODO: check if there are cases that matter where we have
   174  	// more than one len(s) for a slice. We could keep a list if necessary.
   175  	lens map[ID]*Value
   176  	caps map[ID]*Value
   177  }
   178  
   179  // checkpointFact is an invalid value used for checkpointing
   180  // and restoring factsTable.
   181  var checkpointFact = fact{}
   182  var checkpointBound = limitFact{}
   183  
   184  func newFactsTable(f *Func) *factsTable {
   185  	ft := &factsTable{}
   186  	ft.order[0] = f.newPoset() // signed
   187  	ft.order[1] = f.newPoset() // unsigned
   188  	ft.order[0].SetUnsigned(false)
   189  	ft.order[1].SetUnsigned(true)
   190  	ft.facts = make(map[pair]relation)
   191  	ft.stack = make([]fact, 4)
   192  	ft.limits = make(map[ID]limit)
   193  	ft.limitStack = make([]limitFact, 4)
   194  	return ft
   195  }
   196  
   197  // update updates the set of relations between v and w in domain d
   198  // restricting it to r.
   199  func (ft *factsTable) update(parent *Block, v, w *Value, d domain, r relation) {
   200  	// No need to do anything else if we already found unsat.
   201  	if ft.unsat {
   202  		return
   203  	}
   204  
   205  	// Self-fact. It's wasteful to register it into the facts
   206  	// table, so just note whether it's satisfiable
   207  	if v == w {
   208  		if r&eq == 0 {
   209  			ft.unsat = true
   210  		}
   211  		return
   212  	}
   213  
   214  	if d == signed || d == unsigned {
   215  		var ok bool
   216  		idx := 0
   217  		if d == unsigned {
   218  			idx = 1
   219  		}
   220  		switch r {
   221  		case lt:
   222  			ok = ft.order[idx].SetOrder(v, w)
   223  		case gt:
   224  			ok = ft.order[idx].SetOrder(w, v)
   225  		case lt | eq:
   226  			ok = ft.order[idx].SetOrderOrEqual(v, w)
   227  		case gt | eq:
   228  			ok = ft.order[idx].SetOrderOrEqual(w, v)
   229  		case eq:
   230  			ok = ft.order[idx].SetEqual(v, w)
   231  		case lt | gt:
   232  			ok = ft.order[idx].SetNonEqual(v, w)
   233  		default:
   234  			panic("unknown relation")
   235  		}
   236  		if !ok {
   237  			ft.unsat = true
   238  			return
   239  		}
   240  	} else {
   241  		if lessByID(w, v) {
   242  			v, w = w, v
   243  			r = reverseBits[r]
   244  		}
   245  
   246  		p := pair{v, w, d}
   247  		oldR, ok := ft.facts[p]
   248  		if !ok {
   249  			if v == w {
   250  				oldR = eq
   251  			} else {
   252  				oldR = lt | eq | gt
   253  			}
   254  		}
   255  		// No changes compared to information already in facts table.
   256  		if oldR == r {
   257  			return
   258  		}
   259  		ft.stack = append(ft.stack, fact{p, oldR})
   260  		ft.facts[p] = oldR & r
   261  		// If this relation is not satisfiable, mark it and exit right away
   262  		if oldR&r == 0 {
   263  			ft.unsat = true
   264  			return
   265  		}
   266  	}
   267  
   268  	// Extract bounds when comparing against constants
   269  	if v.isGenericIntConst() {
   270  		v, w = w, v
   271  		r = reverseBits[r]
   272  	}
   273  	if v != nil && w.isGenericIntConst() {
   274  		// Note: all the +1/-1 below could overflow/underflow. Either will
   275  		// still generate correct results, it will just lead to imprecision.
   276  		// In fact if there is overflow/underflow, the corresponding
   277  		// code is unreachable because the known range is outside the range
   278  		// of the value's type.
   279  		old, ok := ft.limits[v.ID]
   280  		if !ok {
   281  			old = noLimit
   282  			if v.isGenericIntConst() {
   283  				switch d {
   284  				case signed:
   285  					old.min, old.max = v.AuxInt, v.AuxInt
   286  					if v.AuxInt >= 0 {
   287  						old.umin, old.umax = uint64(v.AuxInt), uint64(v.AuxInt)
   288  					}
   289  				case unsigned:
   290  					old.umin = v.AuxUnsigned()
   291  					old.umax = old.umin
   292  					if int64(old.umin) >= 0 {
   293  						old.min, old.max = int64(old.umin), int64(old.umin)
   294  					}
   295  				}
   296  			}
   297  		}
   298  		lim := noLimit
   299  		switch d {
   300  		case signed:
   301  			c := w.AuxInt
   302  			switch r {
   303  			case lt:
   304  				lim.max = c - 1
   305  			case lt | eq:
   306  				lim.max = c
   307  			case gt | eq:
   308  				lim.min = c
   309  			case gt:
   310  				lim.min = c + 1
   311  			case lt | gt:
   312  				lim = old
   313  				if c == lim.min {
   314  					lim.min++
   315  				}
   316  				if c == lim.max {
   317  					lim.max--
   318  				}
   319  			case eq:
   320  				lim.min = c
   321  				lim.max = c
   322  			}
   323  			if lim.min >= 0 {
   324  				// int(x) >= 0 && int(x) >= N  ⇒  uint(x) >= N
   325  				lim.umin = uint64(lim.min)
   326  			}
   327  			if lim.max != noLimit.max && old.min >= 0 && lim.max >= 0 {
   328  				// 0 <= int(x) <= N  ⇒  0 <= uint(x) <= N
   329  				// This is for a max update, so the lower bound
   330  				// comes from what we already know (old).
   331  				lim.umax = uint64(lim.max)
   332  			}
   333  		case unsigned:
   334  			uc := w.AuxUnsigned()
   335  			switch r {
   336  			case lt:
   337  				lim.umax = uc - 1
   338  			case lt | eq:
   339  				lim.umax = uc
   340  			case gt | eq:
   341  				lim.umin = uc
   342  			case gt:
   343  				lim.umin = uc + 1
   344  			case lt | gt:
   345  				lim = old
   346  				if uc == lim.umin {
   347  					lim.umin++
   348  				}
   349  				if uc == lim.umax {
   350  					lim.umax--
   351  				}
   352  			case eq:
   353  				lim.umin = uc
   354  				lim.umax = uc
   355  			}
   356  			// We could use the contrapositives of the
   357  			// signed implications to derive signed facts,
   358  			// but it turns out not to matter.
   359  		}
   360  		ft.limitStack = append(ft.limitStack, limitFact{v.ID, old})
   361  		lim = old.intersect(lim)
   362  		ft.limits[v.ID] = lim
   363  		if v.Block.Func.pass.debug > 2 {
   364  			v.Block.Func.Warnl(parent.Pos, "parent=%s, new limits %s %s %s", parent, v, w, lim.String())
   365  		}
   366  		if lim.min > lim.max || lim.umin > lim.umax {
   367  			ft.unsat = true
   368  			return
   369  		}
   370  	}
   371  
   372  	// Derived facts below here are only about numbers.
   373  	if d != signed && d != unsigned {
   374  		return
   375  	}
   376  
   377  	// Additional facts we know given the relationship between len and cap.
   378  	//
   379  	// TODO: Since prove now derives transitive relations, it
   380  	// should be sufficient to learn that len(w) <= cap(w) at the
   381  	// beginning of prove where we look for all len/cap ops.
   382  	if v.Op == OpSliceLen && r&lt == 0 && ft.caps[v.Args[0].ID] != nil {
   383  		// len(s) > w implies cap(s) > w
   384  		// len(s) >= w implies cap(s) >= w
   385  		// len(s) == w implies cap(s) >= w
   386  		ft.update(parent, ft.caps[v.Args[0].ID], w, d, r|gt)
   387  	}
   388  	if w.Op == OpSliceLen && r&gt == 0 && ft.caps[w.Args[0].ID] != nil {
   389  		// same, length on the RHS.
   390  		ft.update(parent, v, ft.caps[w.Args[0].ID], d, r|lt)
   391  	}
   392  	if v.Op == OpSliceCap && r&gt == 0 && ft.lens[v.Args[0].ID] != nil {
   393  		// cap(s) < w implies len(s) < w
   394  		// cap(s) <= w implies len(s) <= w
   395  		// cap(s) == w implies len(s) <= w
   396  		ft.update(parent, ft.lens[v.Args[0].ID], w, d, r|lt)
   397  	}
   398  	if w.Op == OpSliceCap && r&lt == 0 && ft.lens[w.Args[0].ID] != nil {
   399  		// same, capacity on the RHS.
   400  		ft.update(parent, v, ft.lens[w.Args[0].ID], d, r|gt)
   401  	}
   402  
   403  	// Process fence-post implications.
   404  	//
   405  	// First, make the condition > or >=.
   406  	if r == lt || r == lt|eq {
   407  		v, w = w, v
   408  		r = reverseBits[r]
   409  	}
   410  	switch r {
   411  	case gt:
   412  		if x, delta := isConstDelta(v); x != nil && delta == 1 {
   413  			// x+1 > w  ⇒  x >= w
   414  			//
   415  			// This is useful for eliminating the
   416  			// growslice branch of append.
   417  			ft.update(parent, x, w, d, gt|eq)
   418  		} else if x, delta := isConstDelta(w); x != nil && delta == -1 {
   419  			// v > x-1  ⇒  v >= x
   420  			ft.update(parent, v, x, d, gt|eq)
   421  		}
   422  	case gt | eq:
   423  		if x, delta := isConstDelta(v); x != nil && delta == -1 {
   424  			// x-1 >= w && x > min  ⇒  x > w
   425  			//
   426  			// Useful for i > 0; s[i-1].
   427  			lim, ok := ft.limits[x.ID]
   428  			if ok && ((d == signed && lim.min > opMin[v.Op]) || (d == unsigned && lim.umin > 0)) {
   429  				ft.update(parent, x, w, d, gt)
   430  			}
   431  		} else if x, delta := isConstDelta(w); x != nil && delta == 1 {
   432  			// v >= x+1 && x < max  ⇒  v > x
   433  			lim, ok := ft.limits[x.ID]
   434  			if ok && ((d == signed && lim.max < opMax[w.Op]) || (d == unsigned && lim.umax < opUMax[w.Op])) {
   435  				ft.update(parent, v, x, d, gt)
   436  			}
   437  		}
   438  	}
   439  
   440  	// Process: x+delta > w (with delta constant)
   441  	// Only signed domain for now (useful for accesses to slices in loops).
   442  	if r == gt || r == gt|eq {
   443  		if x, delta := isConstDelta(v); x != nil && d == signed {
   444  			if parent.Func.pass.debug > 1 {
   445  				parent.Func.Warnl(parent.Pos, "x+d >= w; x:%v %v delta:%v w:%v d:%v", x, parent.String(), delta, w.AuxInt, d)
   446  			}
   447  			if !w.isGenericIntConst() {
   448  				// If we know that x+delta > w but w is not constant, we can derive:
   449  				//    if delta < 0 and x > MinInt - delta, then x > w (because x+delta cannot underflow)
   450  				// This is useful for loops with bounds "len(slice)-K" (delta = -K)
   451  				if l, has := ft.limits[x.ID]; has && delta < 0 {
   452  					if (x.Type.Size() == 8 && l.min >= math.MinInt64-delta) ||
   453  						(x.Type.Size() == 4 && l.min >= math.MinInt32-delta) {
   454  						ft.update(parent, x, w, signed, r)
   455  					}
   456  				}
   457  			} else {
   458  				// With w,delta constants, we want to derive: x+delta > w  ⇒  x > w-delta
   459  				//
   460  				// We compute (using integers of the correct size):
   461  				//    min = w - delta
   462  				//    max = MaxInt - delta
   463  				//
   464  				// And we prove that:
   465  				//    if min<max: min < x AND x <= max
   466  				//    if min>max: min < x OR  x <= max
   467  				//
   468  				// This is always correct, even in case of overflow.
   469  				//
   470  				// If the initial fact is x+delta >= w instead, the derived conditions are:
   471  				//    if min<max: min <= x AND x <= max
   472  				//    if min>max: min <= x OR  x <= max
   473  				//
   474  				// Notice the conditions for max are still <=, as they handle overflows.
   475  				var min, max int64
   476  				var vmin, vmax *Value
   477  				switch x.Type.Size() {
   478  				case 8:
   479  					min = w.AuxInt - delta
   480  					max = int64(^uint64(0)>>1) - delta
   481  
   482  					vmin = parent.NewValue0I(parent.Pos, OpConst64, parent.Func.Config.Types.Int64, min)
   483  					vmax = parent.NewValue0I(parent.Pos, OpConst64, parent.Func.Config.Types.Int64, max)
   484  
   485  				case 4:
   486  					min = int64(int32(w.AuxInt) - int32(delta))
   487  					max = int64(int32(^uint32(0)>>1) - int32(delta))
   488  
   489  					vmin = parent.NewValue0I(parent.Pos, OpConst32, parent.Func.Config.Types.Int32, min)
   490  					vmax = parent.NewValue0I(parent.Pos, OpConst32, parent.Func.Config.Types.Int32, max)
   491  
   492  				default:
   493  					panic("unimplemented")
   494  				}
   495  
   496  				if min < max {
   497  					// Record that x > min and max >= x
   498  					ft.update(parent, x, vmin, d, r)
   499  					ft.update(parent, vmax, x, d, r|eq)
   500  				} else {
   501  					// We know that either x>min OR x<=max. factsTable cannot record OR conditions,
   502  					// so let's see if we can already prove that one of them is false, in which case
   503  					// the other must be true
   504  					if l, has := ft.limits[x.ID]; has {
   505  						if l.max <= min {
   506  							// x>min is impossible, so it must be x<=max
   507  							ft.update(parent, vmax, x, d, r|eq)
   508  						} else if l.min > max {
   509  							// x<=max is impossible, so it must be x>min
   510  							ft.update(parent, x, vmin, d, r)
   511  						}
   512  					}
   513  				}
   514  			}
   515  		}
   516  	}
   517  
   518  }
   519  
   520  var opMin = map[Op]int64{
   521  	OpAdd64: math.MinInt64, OpSub64: math.MinInt64,
   522  	OpAdd32: math.MinInt32, OpSub32: math.MinInt32,
   523  }
   524  
   525  var opMax = map[Op]int64{
   526  	OpAdd64: math.MaxInt64, OpSub64: math.MaxInt64,
   527  	OpAdd32: math.MaxInt32, OpSub32: math.MaxInt32,
   528  }
   529  
   530  var opUMax = map[Op]uint64{
   531  	OpAdd64: math.MaxUint64, OpSub64: math.MaxUint64,
   532  	OpAdd32: math.MaxUint32, OpSub32: math.MaxUint32,
   533  }
   534  
   535  // isNonNegative reports whether v is known to be non-negative.
   536  func (ft *factsTable) isNonNegative(v *Value) bool {
   537  	if isNonNegative(v) {
   538  		return true
   539  	}
   540  
   541  	// Check if the recorded limits can prove that the value is positive
   542  	if l, has := ft.limits[v.ID]; has && (l.min >= 0 || l.umax <= math.MaxInt64) {
   543  		return true
   544  	}
   545  
   546  	// Check if v = x+delta, and we can use x's limits to prove that it's positive
   547  	if x, delta := isConstDelta(v); x != nil {
   548  		if l, has := ft.limits[x.ID]; has {
   549  			if delta > 0 && l.min >= -delta && l.max <= math.MaxInt64-delta {
   550  				return true
   551  			}
   552  			if delta < 0 && l.min >= -delta {
   553  				return true
   554  			}
   555  		}
   556  	}
   557  
   558  	return false
   559  }
   560  
   561  // checkpoint saves the current state of known relations.
   562  // Called when descending on a branch.
   563  func (ft *factsTable) checkpoint() {
   564  	if ft.unsat {
   565  		ft.unsatDepth++
   566  	}
   567  	ft.stack = append(ft.stack, checkpointFact)
   568  	ft.limitStack = append(ft.limitStack, checkpointBound)
   569  	ft.order[0].Checkpoint()
   570  	ft.order[1].Checkpoint()
   571  }
   572  
   573  // restore restores known relation to the state just
   574  // before the previous checkpoint.
   575  // Called when backing up on a branch.
   576  func (ft *factsTable) restore() {
   577  	if ft.unsatDepth > 0 {
   578  		ft.unsatDepth--
   579  	} else {
   580  		ft.unsat = false
   581  	}
   582  	for {
   583  		old := ft.stack[len(ft.stack)-1]
   584  		ft.stack = ft.stack[:len(ft.stack)-1]
   585  		if old == checkpointFact {
   586  			break
   587  		}
   588  		if old.r == lt|eq|gt {
   589  			delete(ft.facts, old.p)
   590  		} else {
   591  			ft.facts[old.p] = old.r
   592  		}
   593  	}
   594  	for {
   595  		old := ft.limitStack[len(ft.limitStack)-1]
   596  		ft.limitStack = ft.limitStack[:len(ft.limitStack)-1]
   597  		if old.vid == 0 { // checkpointBound
   598  			break
   599  		}
   600  		if old.limit == noLimit {
   601  			delete(ft.limits, old.vid)
   602  		} else {
   603  			ft.limits[old.vid] = old.limit
   604  		}
   605  	}
   606  	ft.order[0].Undo()
   607  	ft.order[1].Undo()
   608  }
   609  
   610  func lessByID(v, w *Value) bool {
   611  	if v == nil && w == nil {
   612  		// Should not happen, but just in case.
   613  		return false
   614  	}
   615  	if v == nil {
   616  		return true
   617  	}
   618  	return w != nil && v.ID < w.ID
   619  }
   620  
   621  var (
   622  	reverseBits = [...]relation{0, 4, 2, 6, 1, 5, 3, 7}
   623  
   624  	// maps what we learn when the positive branch is taken.
   625  	// For example:
   626  	//      OpLess8:   {signed, lt},
   627  	//	v1 = (OpLess8 v2 v3).
   628  	// If v1 branch is taken then we learn that the rangeMask
   629  	// can be at most lt.
   630  	domainRelationTable = map[Op]struct {
   631  		d domain
   632  		r relation
   633  	}{
   634  		OpEq8:   {signed | unsigned, eq},
   635  		OpEq16:  {signed | unsigned, eq},
   636  		OpEq32:  {signed | unsigned, eq},
   637  		OpEq64:  {signed | unsigned, eq},
   638  		OpEqPtr: {pointer, eq},
   639  
   640  		OpNeq8:   {signed | unsigned, lt | gt},
   641  		OpNeq16:  {signed | unsigned, lt | gt},
   642  		OpNeq32:  {signed | unsigned, lt | gt},
   643  		OpNeq64:  {signed | unsigned, lt | gt},
   644  		OpNeqPtr: {pointer, lt | gt},
   645  
   646  		OpLess8:   {signed, lt},
   647  		OpLess8U:  {unsigned, lt},
   648  		OpLess16:  {signed, lt},
   649  		OpLess16U: {unsigned, lt},
   650  		OpLess32:  {signed, lt},
   651  		OpLess32U: {unsigned, lt},
   652  		OpLess64:  {signed, lt},
   653  		OpLess64U: {unsigned, lt},
   654  
   655  		OpLeq8:   {signed, lt | eq},
   656  		OpLeq8U:  {unsigned, lt | eq},
   657  		OpLeq16:  {signed, lt | eq},
   658  		OpLeq16U: {unsigned, lt | eq},
   659  		OpLeq32:  {signed, lt | eq},
   660  		OpLeq32U: {unsigned, lt | eq},
   661  		OpLeq64:  {signed, lt | eq},
   662  		OpLeq64U: {unsigned, lt | eq},
   663  
   664  		OpGeq8:   {signed, eq | gt},
   665  		OpGeq8U:  {unsigned, eq | gt},
   666  		OpGeq16:  {signed, eq | gt},
   667  		OpGeq16U: {unsigned, eq | gt},
   668  		OpGeq32:  {signed, eq | gt},
   669  		OpGeq32U: {unsigned, eq | gt},
   670  		OpGeq64:  {signed, eq | gt},
   671  		OpGeq64U: {unsigned, eq | gt},
   672  
   673  		OpGreater8:   {signed, gt},
   674  		OpGreater8U:  {unsigned, gt},
   675  		OpGreater16:  {signed, gt},
   676  		OpGreater16U: {unsigned, gt},
   677  		OpGreater32:  {signed, gt},
   678  		OpGreater32U: {unsigned, gt},
   679  		OpGreater64:  {signed, gt},
   680  		OpGreater64U: {unsigned, gt},
   681  
   682  		// For these ops, the negative branch is different: we can only
   683  		// prove signed/GE (signed/GT) if we can prove that arg0 is non-negative.
   684  		// See the special case in addBranchRestrictions.
   685  		OpIsInBounds:      {signed | unsigned, lt},      // 0 <= arg0 < arg1
   686  		OpIsSliceInBounds: {signed | unsigned, lt | eq}, // 0 <= arg0 <= arg1
   687  	}
   688  )
   689  
   690  // prove removes redundant BlockIf branches that can be inferred
   691  // from previous dominating comparisons.
   692  //
   693  // By far, the most common redundant pair are generated by bounds checking.
   694  // For example for the code:
   695  //
   696  //    a[i] = 4
   697  //    foo(a[i])
   698  //
   699  // The compiler will generate the following code:
   700  //
   701  //    if i >= len(a) {
   702  //        panic("not in bounds")
   703  //    }
   704  //    a[i] = 4
   705  //    if i >= len(a) {
   706  //        panic("not in bounds")
   707  //    }
   708  //    foo(a[i])
   709  //
   710  // The second comparison i >= len(a) is clearly redundant because if the
   711  // else branch of the first comparison is executed, we already know that i < len(a).
   712  // The code for the second panic can be removed.
   713  //
   714  // prove works by finding contradictions and trimming branches whose
   715  // conditions are unsatisfiable given the branches leading up to them.
   716  // It tracks a "fact table" of branch conditions. For each branching
   717  // block, it asserts the branch conditions that uniquely dominate that
   718  // block, and then separately asserts the block's branch condition and
   719  // its negation. If either leads to a contradiction, it can trim that
   720  // successor.
   721  func prove(f *Func) {
   722  	ft := newFactsTable(f)
   723  	ft.checkpoint()
   724  
   725  	// Find length and capacity ops.
   726  	var zero *Value
   727  	for _, b := range f.Blocks {
   728  		for _, v := range b.Values {
   729  			// If we found a zero constant, save it (so we don't have
   730  			// to build one later).
   731  			if zero == nil && v.Op == OpConst64 && v.AuxInt == 0 {
   732  				zero = v
   733  			}
   734  			if v.Uses == 0 {
   735  				// We don't care about dead values.
   736  				// (There can be some that are CSEd but not removed yet.)
   737  				continue
   738  			}
   739  			switch v.Op {
   740  			case OpStringLen:
   741  				if zero == nil {
   742  					zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0)
   743  				}
   744  				ft.update(b, v, zero, signed, gt|eq)
   745  			case OpSliceLen:
   746  				if ft.lens == nil {
   747  					ft.lens = map[ID]*Value{}
   748  				}
   749  				ft.lens[v.Args[0].ID] = v
   750  				if zero == nil {
   751  					zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0)
   752  				}
   753  				ft.update(b, v, zero, signed, gt|eq)
   754  			case OpSliceCap:
   755  				if ft.caps == nil {
   756  					ft.caps = map[ID]*Value{}
   757  				}
   758  				ft.caps[v.Args[0].ID] = v
   759  				if zero == nil {
   760  					zero = b.NewValue0I(b.Pos, OpConst64, f.Config.Types.Int64, 0)
   761  				}
   762  				ft.update(b, v, zero, signed, gt|eq)
   763  			}
   764  		}
   765  	}
   766  
   767  	// Find induction variables. Currently, findIndVars
   768  	// is limited to one induction variable per block.
   769  	var indVars map[*Block]indVar
   770  	for _, v := range findIndVar(f) {
   771  		if indVars == nil {
   772  			indVars = make(map[*Block]indVar)
   773  		}
   774  		indVars[v.entry] = v
   775  	}
   776  
   777  	// current node state
   778  	type walkState int
   779  	const (
   780  		descend walkState = iota
   781  		simplify
   782  	)
   783  	// work maintains the DFS stack.
   784  	type bp struct {
   785  		block *Block    // current handled block
   786  		state walkState // what's to do
   787  	}
   788  	work := make([]bp, 0, 256)
   789  	work = append(work, bp{
   790  		block: f.Entry,
   791  		state: descend,
   792  	})
   793  
   794  	idom := f.Idom()
   795  	sdom := f.sdom()
   796  
   797  	// DFS on the dominator tree.
   798  	//
   799  	// For efficiency, we consider only the dominator tree rather
   800  	// than the entire flow graph. On the way down, we consider
   801  	// incoming branches and accumulate conditions that uniquely
   802  	// dominate the current block. If we discover a contradiction,
   803  	// we can eliminate the entire block and all of its children.
   804  	// On the way back up, we consider outgoing branches that
   805  	// haven't already been considered. This way we consider each
   806  	// branch condition only once.
   807  	for len(work) > 0 {
   808  		node := work[len(work)-1]
   809  		work = work[:len(work)-1]
   810  		parent := idom[node.block.ID]
   811  		branch := getBranch(sdom, parent, node.block)
   812  
   813  		switch node.state {
   814  		case descend:
   815  			ft.checkpoint()
   816  			if iv, ok := indVars[node.block]; ok {
   817  				addIndVarRestrictions(ft, parent, iv)
   818  			}
   819  
   820  			if branch != unknown {
   821  				addBranchRestrictions(ft, parent, branch)
   822  				if ft.unsat {
   823  					// node.block is unreachable.
   824  					// Remove it and don't visit
   825  					// its children.
   826  					removeBranch(parent, branch)
   827  					ft.restore()
   828  					break
   829  				}
   830  				// Otherwise, we can now commit to
   831  				// taking this branch. We'll restore
   832  				// ft when we unwind.
   833  			}
   834  
   835  			// Add inductive facts for phis in this block.
   836  			addLocalInductiveFacts(ft, node.block)
   837  
   838  			work = append(work, bp{
   839  				block: node.block,
   840  				state: simplify,
   841  			})
   842  			for s := sdom.Child(node.block); s != nil; s = sdom.Sibling(s) {
   843  				work = append(work, bp{
   844  					block: s,
   845  					state: descend,
   846  				})
   847  			}
   848  
   849  		case simplify:
   850  			simplifyBlock(sdom, ft, node.block)
   851  			ft.restore()
   852  		}
   853  	}
   854  
   855  	ft.restore()
   856  
   857  	// Return the posets to the free list
   858  	for _, po := range ft.order {
   859  		// Make sure it's empty as it should be. A non-empty poset
   860  		// might cause errors and miscompilations if reused.
   861  		if checkEnabled {
   862  			if err := po.CheckEmpty(); err != nil {
   863  				f.Fatalf("prove poset not empty after function %s: %v", f.Name, err)
   864  			}
   865  		}
   866  		f.retPoset(po)
   867  	}
   868  }
   869  
   870  // getBranch returns the range restrictions added by p
   871  // when reaching b. p is the immediate dominator of b.
   872  func getBranch(sdom SparseTree, p *Block, b *Block) branch {
   873  	if p == nil || p.Kind != BlockIf {
   874  		return unknown
   875  	}
   876  	// If p and p.Succs[0] are dominators it means that every path
   877  	// from entry to b passes through p and p.Succs[0]. We care that
   878  	// no path from entry to b passes through p.Succs[1]. If p.Succs[0]
   879  	// has one predecessor then (apart from the degenerate case),
   880  	// there is no path from entry that can reach b through p.Succs[1].
   881  	// TODO: how about p->yes->b->yes, i.e. a loop in yes.
   882  	if sdom.isAncestorEq(p.Succs[0].b, b) && len(p.Succs[0].b.Preds) == 1 {
   883  		return positive
   884  	}
   885  	if sdom.isAncestorEq(p.Succs[1].b, b) && len(p.Succs[1].b.Preds) == 1 {
   886  		return negative
   887  	}
   888  	return unknown
   889  }
   890  
   891  // addIndVarRestrictions updates the factsTables ft with the facts
   892  // learned from the induction variable indVar which drives the loop
   893  // starting in Block b.
   894  func addIndVarRestrictions(ft *factsTable, b *Block, iv indVar) {
   895  	d := signed
   896  	if isNonNegative(iv.min) && isNonNegative(iv.max) {
   897  		d |= unsigned
   898  	}
   899  
   900  	if iv.flags&indVarMinExc == 0 {
   901  		addRestrictions(b, ft, d, iv.min, iv.ind, lt|eq)
   902  	} else {
   903  		addRestrictions(b, ft, d, iv.min, iv.ind, lt)
   904  	}
   905  
   906  	if iv.flags&indVarMaxInc == 0 {
   907  		addRestrictions(b, ft, d, iv.ind, iv.max, lt)
   908  	} else {
   909  		addRestrictions(b, ft, d, iv.ind, iv.max, lt|eq)
   910  	}
   911  }
   912  
   913  // addBranchRestrictions updates the factsTables ft with the facts learned when
   914  // branching from Block b in direction br.
   915  func addBranchRestrictions(ft *factsTable, b *Block, br branch) {
   916  	c := b.Control
   917  	switch br {
   918  	case negative:
   919  		addRestrictions(b, ft, boolean, nil, c, eq)
   920  	case positive:
   921  		addRestrictions(b, ft, boolean, nil, c, lt|gt)
   922  	default:
   923  		panic("unknown branch")
   924  	}
   925  	if tr, has := domainRelationTable[b.Control.Op]; has {
   926  		// When we branched from parent we learned a new set of
   927  		// restrictions. Update the factsTable accordingly.
   928  		d := tr.d
   929  		if d == signed && ft.isNonNegative(c.Args[0]) && ft.isNonNegative(c.Args[1]) {
   930  			d |= unsigned
   931  		}
   932  		switch br {
   933  		case negative:
   934  			switch b.Control.Op { // Special cases
   935  			case OpIsInBounds, OpIsSliceInBounds:
   936  				// 0 <= a0 < a1 (or 0 <= a0 <= a1)
   937  				//
   938  				// On the positive branch, we learn a0 < a1,
   939  				// both signed and unsigned.
   940  				//
   941  				// On the negative branch, we learn (0 > a0 ||
   942  				// a0 >= a1). In the unsigned domain, this is
   943  				// simply a0 >= a1 (which is the reverse of the
   944  				// positive branch, so nothing surprising).
   945  				// But in the signed domain, we can't express the ||
   946  				// condition, so check if a0 is non-negative instead,
   947  				// to be able to learn something.
   948  				d = unsigned
   949  				if ft.isNonNegative(c.Args[0]) {
   950  					d |= signed
   951  				}
   952  			}
   953  			addRestrictions(b, ft, d, c.Args[0], c.Args[1], tr.r^(lt|gt|eq))
   954  		case positive:
   955  			addRestrictions(b, ft, d, c.Args[0], c.Args[1], tr.r)
   956  		}
   957  	}
   958  }
   959  
   960  // addRestrictions updates restrictions from the immediate
   961  // dominating block (p) using r.
   962  func addRestrictions(parent *Block, ft *factsTable, t domain, v, w *Value, r relation) {
   963  	if t == 0 {
   964  		// Trivial case: nothing to do.
   965  		// Shoult not happen, but just in case.
   966  		return
   967  	}
   968  	for i := domain(1); i <= t; i <<= 1 {
   969  		if t&i == 0 {
   970  			continue
   971  		}
   972  		ft.update(parent, v, w, i, r)
   973  	}
   974  }
   975  
   976  // addLocalInductiveFacts adds inductive facts when visiting b, where
   977  // b is a join point in a loop. In contrast with findIndVar, this
   978  // depends on facts established for b, which is why it happens when
   979  // visiting b. addLocalInductiveFacts specifically targets the pattern
   980  // created by OFORUNTIL, which isn't detected by findIndVar.
   981  //
   982  // TODO: It would be nice to combine this with findIndVar.
   983  func addLocalInductiveFacts(ft *factsTable, b *Block) {
   984  	// This looks for a specific pattern of induction:
   985  	//
   986  	// 1. i1 = OpPhi(min, i2) in b
   987  	// 2. i2 = i1 + 1
   988  	// 3. i2 < max at exit from b.Preds[1]
   989  	// 4. min < max
   990  	//
   991  	// If all of these conditions are true, then i1 < max and i1 >= min.
   992  
   993  	for _, i1 := range b.Values {
   994  		if i1.Op != OpPhi {
   995  			continue
   996  		}
   997  
   998  		// Check for conditions 1 and 2. This is easy to do
   999  		// and will throw out most phis.
  1000  		min, i2 := i1.Args[0], i1.Args[1]
  1001  		if i1q, delta := isConstDelta(i2); i1q != i1 || delta != 1 {
  1002  			continue
  1003  		}
  1004  
  1005  		// Try to prove condition 3. We can't just query the
  1006  		// fact table for this because we don't know what the
  1007  		// facts of b.Preds[1] are (in general, b.Preds[1] is
  1008  		// a loop-back edge, so we haven't even been there
  1009  		// yet). As a conservative approximation, we look for
  1010  		// this condition in the predecessor chain until we
  1011  		// hit a join point.
  1012  		uniquePred := func(b *Block) *Block {
  1013  			if len(b.Preds) == 1 {
  1014  				return b.Preds[0].b
  1015  			}
  1016  			return nil
  1017  		}
  1018  		pred, child := b.Preds[1].b, b
  1019  		for ; pred != nil; pred = uniquePred(pred) {
  1020  			if pred.Kind != BlockIf {
  1021  				continue
  1022  			}
  1023  
  1024  			br := unknown
  1025  			if pred.Succs[0].b == child {
  1026  				br = positive
  1027  			}
  1028  			if pred.Succs[1].b == child {
  1029  				if br != unknown {
  1030  					continue
  1031  				}
  1032  				br = negative
  1033  			}
  1034  
  1035  			tr, has := domainRelationTable[pred.Control.Op]
  1036  			if !has {
  1037  				continue
  1038  			}
  1039  			r := tr.r
  1040  			if br == negative {
  1041  				// Negative branch taken to reach b.
  1042  				// Complement the relations.
  1043  				r = (lt | eq | gt) ^ r
  1044  			}
  1045  
  1046  			// Check for i2 < max or max > i2.
  1047  			var max *Value
  1048  			if r == lt && pred.Control.Args[0] == i2 {
  1049  				max = pred.Control.Args[1]
  1050  			} else if r == gt && pred.Control.Args[1] == i2 {
  1051  				max = pred.Control.Args[0]
  1052  			} else {
  1053  				continue
  1054  			}
  1055  
  1056  			// Check condition 4 now that we have a
  1057  			// candidate max. For this we can query the
  1058  			// fact table. We "prove" min < max by showing
  1059  			// that min >= max is unsat. (This may simply
  1060  			// compare two constants; that's fine.)
  1061  			ft.checkpoint()
  1062  			ft.update(b, min, max, tr.d, gt|eq)
  1063  			proved := ft.unsat
  1064  			ft.restore()
  1065  
  1066  			if proved {
  1067  				// We know that min <= i1 < max.
  1068  				if b.Func.pass.debug > 0 {
  1069  					printIndVar(b, i1, min, max, 1, 0)
  1070  				}
  1071  				ft.update(b, min, i1, tr.d, lt|eq)
  1072  				ft.update(b, i1, max, tr.d, lt)
  1073  			}
  1074  		}
  1075  	}
  1076  }
  1077  
  1078  var ctzNonZeroOp = map[Op]Op{OpCtz8: OpCtz8NonZero, OpCtz16: OpCtz16NonZero, OpCtz32: OpCtz32NonZero, OpCtz64: OpCtz64NonZero}
  1079  var mostNegativeDividend = map[Op]int64{
  1080  	OpDiv16: -1 << 15,
  1081  	OpMod16: -1 << 15,
  1082  	OpDiv32: -1 << 31,
  1083  	OpMod32: -1 << 31,
  1084  	OpDiv64: -1 << 63,
  1085  	OpMod64: -1 << 63}
  1086  
  1087  // simplifyBlock simplifies some constant values in b and evaluates
  1088  // branches to non-uniquely dominated successors of b.
  1089  func simplifyBlock(sdom SparseTree, ft *factsTable, b *Block) {
  1090  	for _, v := range b.Values {
  1091  		switch v.Op {
  1092  		case OpSlicemask:
  1093  			// Replace OpSlicemask operations in b with constants where possible.
  1094  			x, delta := isConstDelta(v.Args[0])
  1095  			if x == nil {
  1096  				continue
  1097  			}
  1098  			// slicemask(x + y)
  1099  			// if x is larger than -y (y is negative), then slicemask is -1.
  1100  			lim, ok := ft.limits[x.ID]
  1101  			if !ok {
  1102  				continue
  1103  			}
  1104  			if lim.umin > uint64(-delta) {
  1105  				if v.Args[0].Op == OpAdd64 {
  1106  					v.reset(OpConst64)
  1107  				} else {
  1108  					v.reset(OpConst32)
  1109  				}
  1110  				if b.Func.pass.debug > 0 {
  1111  					b.Func.Warnl(v.Pos, "Proved slicemask not needed")
  1112  				}
  1113  				v.AuxInt = -1
  1114  			}
  1115  		case OpCtz8, OpCtz16, OpCtz32, OpCtz64:
  1116  			// On some architectures, notably amd64, we can generate much better
  1117  			// code for CtzNN if we know that the argument is non-zero.
  1118  			// Capture that information here for use in arch-specific optimizations.
  1119  			x := v.Args[0]
  1120  			lim, ok := ft.limits[x.ID]
  1121  			if !ok {
  1122  				continue
  1123  			}
  1124  			if lim.umin > 0 || lim.min > 0 || lim.max < 0 {
  1125  				if b.Func.pass.debug > 0 {
  1126  					b.Func.Warnl(v.Pos, "Proved %v non-zero", v.Op)
  1127  				}
  1128  				v.Op = ctzNonZeroOp[v.Op]
  1129  			}
  1130  
  1131  		case OpLsh8x8, OpLsh8x16, OpLsh8x32, OpLsh8x64,
  1132  			OpLsh16x8, OpLsh16x16, OpLsh16x32, OpLsh16x64,
  1133  			OpLsh32x8, OpLsh32x16, OpLsh32x32, OpLsh32x64,
  1134  			OpLsh64x8, OpLsh64x16, OpLsh64x32, OpLsh64x64,
  1135  			OpRsh8x8, OpRsh8x16, OpRsh8x32, OpRsh8x64,
  1136  			OpRsh16x8, OpRsh16x16, OpRsh16x32, OpRsh16x64,
  1137  			OpRsh32x8, OpRsh32x16, OpRsh32x32, OpRsh32x64,
  1138  			OpRsh64x8, OpRsh64x16, OpRsh64x32, OpRsh64x64,
  1139  			OpRsh8Ux8, OpRsh8Ux16, OpRsh8Ux32, OpRsh8Ux64,
  1140  			OpRsh16Ux8, OpRsh16Ux16, OpRsh16Ux32, OpRsh16Ux64,
  1141  			OpRsh32Ux8, OpRsh32Ux16, OpRsh32Ux32, OpRsh32Ux64,
  1142  			OpRsh64Ux8, OpRsh64Ux16, OpRsh64Ux32, OpRsh64Ux64:
  1143  			// Check whether, for a << b, we know that b
  1144  			// is strictly less than the number of bits in a.
  1145  			by := v.Args[1]
  1146  			lim, ok := ft.limits[by.ID]
  1147  			if !ok {
  1148  				continue
  1149  			}
  1150  			bits := 8 * v.Args[0].Type.Size()
  1151  			if lim.umax < uint64(bits) || (lim.max < bits && ft.isNonNegative(by)) {
  1152  				v.AuxInt = 1 // see shiftIsBounded
  1153  				if b.Func.pass.debug > 0 {
  1154  					b.Func.Warnl(v.Pos, "Proved %v bounded", v.Op)
  1155  				}
  1156  			}
  1157  		case OpDiv16, OpDiv32, OpDiv64, OpMod16, OpMod32, OpMod64:
  1158  			// On amd64 and 386 fix-up code can be avoided if we know
  1159  			//  the divisor is not -1 or the dividend > MinIntNN.
  1160  			divr := v.Args[1]
  1161  			divrLim, divrLimok := ft.limits[divr.ID]
  1162  			divd := v.Args[0]
  1163  			divdLim, divdLimok := ft.limits[divd.ID]
  1164  			if (divrLimok && (divrLim.max < -1 || divrLim.min > -1)) ||
  1165  				(divdLimok && divdLim.min > mostNegativeDividend[v.Op]) {
  1166  				v.AuxInt = 1 // see NeedsFixUp in genericOps - v.AuxInt = 0 means we have not proved
  1167  				// that the divisor is not -1 and the dividend is not the most negative,
  1168  				// so we need to add fix-up code.
  1169  				if b.Func.pass.debug > 0 {
  1170  					b.Func.Warnl(v.Pos, "Proved %v does not need fix-up", v.Op)
  1171  				}
  1172  			}
  1173  		}
  1174  	}
  1175  
  1176  	if b.Kind != BlockIf {
  1177  		return
  1178  	}
  1179  
  1180  	// Consider outgoing edges from this block.
  1181  	parent := b
  1182  	for i, branch := range [...]branch{positive, negative} {
  1183  		child := parent.Succs[i].b
  1184  		if getBranch(sdom, parent, child) != unknown {
  1185  			// For edges to uniquely dominated blocks, we
  1186  			// already did this when we visited the child.
  1187  			continue
  1188  		}
  1189  		// For edges to other blocks, this can trim a branch
  1190  		// even if we couldn't get rid of the child itself.
  1191  		ft.checkpoint()
  1192  		addBranchRestrictions(ft, parent, branch)
  1193  		unsat := ft.unsat
  1194  		ft.restore()
  1195  		if unsat {
  1196  			// This branch is impossible, so remove it
  1197  			// from the block.
  1198  			removeBranch(parent, branch)
  1199  			// No point in considering the other branch.
  1200  			// (It *is* possible for both to be
  1201  			// unsatisfiable since the fact table is
  1202  			// incomplete. We could turn this into a
  1203  			// BlockExit, but it doesn't seem worth it.)
  1204  			break
  1205  		}
  1206  	}
  1207  }
  1208  
  1209  func removeBranch(b *Block, branch branch) {
  1210  	if b.Func.pass.debug > 0 {
  1211  		verb := "Proved"
  1212  		if branch == positive {
  1213  			verb = "Disproved"
  1214  		}
  1215  		c := b.Control
  1216  		if b.Func.pass.debug > 1 {
  1217  			b.Func.Warnl(b.Pos, "%s %s (%s)", verb, c.Op, c)
  1218  		} else {
  1219  			b.Func.Warnl(b.Pos, "%s %s", verb, c.Op)
  1220  		}
  1221  	}
  1222  	b.Kind = BlockFirst
  1223  	b.SetControl(nil)
  1224  	if branch == positive {
  1225  		b.swapSuccessors()
  1226  	}
  1227  }
  1228  
  1229  // isNonNegative reports whether v is known to be greater or equal to zero.
  1230  func isNonNegative(v *Value) bool {
  1231  	switch v.Op {
  1232  	case OpConst64:
  1233  		return v.AuxInt >= 0
  1234  
  1235  	case OpConst32:
  1236  		return int32(v.AuxInt) >= 0
  1237  
  1238  	case OpStringLen, OpSliceLen, OpSliceCap,
  1239  		OpZeroExt8to64, OpZeroExt16to64, OpZeroExt32to64:
  1240  		return true
  1241  
  1242  	case OpRsh64Ux64:
  1243  		by := v.Args[1]
  1244  		return by.Op == OpConst64 && by.AuxInt > 0
  1245  
  1246  	case OpRsh64x64:
  1247  		return isNonNegative(v.Args[0])
  1248  	}
  1249  	return false
  1250  }
  1251  
  1252  // isConstDelta returns non-nil if v is equivalent to w+delta (signed).
  1253  func isConstDelta(v *Value) (w *Value, delta int64) {
  1254  	cop := OpConst64
  1255  	switch v.Op {
  1256  	case OpAdd32, OpSub32:
  1257  		cop = OpConst32
  1258  	}
  1259  	switch v.Op {
  1260  	case OpAdd64, OpAdd32:
  1261  		if v.Args[0].Op == cop {
  1262  			return v.Args[1], v.Args[0].AuxInt
  1263  		}
  1264  		if v.Args[1].Op == cop {
  1265  			return v.Args[0], v.Args[1].AuxInt
  1266  		}
  1267  	case OpSub64, OpSub32:
  1268  		if v.Args[1].Op == cop {
  1269  			aux := v.Args[1].AuxInt
  1270  			if aux != -aux { // Overflow; too bad
  1271  				return v.Args[0], -aux
  1272  			}
  1273  		}
  1274  	}
  1275  	return nil, 0
  1276  }