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