]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: simplify limit logic in prove
authorAustin Clements <austin@google.com>
Wed, 10 Jan 2018 22:39:43 +0000 (17:39 -0500)
committerAustin Clements <austin@google.com>
Thu, 8 Mar 2018 22:25:24 +0000 (22:25 +0000)
This replaces the open-coded intersection of limits in the prove pass
with a general limit intersection operation. This should get identical
results except in one case where it's more precise: when handling an
equality relation, if the value is *outside* the existing range, this
will reduce the range to empty rather than resetting it. This will be
important to a follow-up CL where we can take advantage of empty
ranges.

For #23354.

Change-Id: I3d3d75924f61b1da1cb604b3a9d189b26fb3a14e
Reviewed-on: https://go-review.googlesource.com/87477
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Alexandru Moșoi <alexandru@mosoi.ro>
src/cmd/compile/internal/ssa/prove.go

index 448a92ae579fd6039c1daa746e00bd439bb84633..8a17302a01d2e0e3d0e4198e3db3e8dc60645c2a 100644 (file)
@@ -117,6 +117,22 @@ func (l limit) String() string {
        return fmt.Sprintf("sm,SM,um,UM=%d,%d,%d,%d", l.min, l.max, l.umin, l.umax)
 }
 
+func (l limit) intersect(l2 limit) limit {
+       if l.min < l2.min {
+               l.min = l2.min
+       }
+       if l.umin < l2.umin {
+               l.umin = l2.umin
+       }
+       if l.max > l2.max {
+               l.max = l2.max
+       }
+       if l.umax > l2.umax {
+               l.umax = l2.umax
+       }
+       return l
+}
+
 var noLimit = limit{math.MinInt64, math.MaxInt64, 0, math.MaxUint64}
 
 // a limitFact is a limit known for a particular value.
@@ -273,28 +289,20 @@ func (ft *factsTable) update(parent *Block, v, w *Value, d domain, r relation) {
                if !ok {
                        old = noLimit
                }
-               lim := old
-               // Update lim with the new information we know.
+               lim := noLimit
                switch d {
                case signed:
                        switch r {
                        case lt:
-                               if c-1 < lim.max {
-                                       lim.max = c - 1
-                               }
+                               lim.max = c - 1
                        case lt | eq:
-                               if c < lim.max {
-                                       lim.max = c
-                               }
+                               lim.max = c
                        case gt | eq:
-                               if c > lim.min {
-                                       lim.min = c
-                               }
+                               lim.min = c
                        case gt:
-                               if c+1 > lim.min {
-                                       lim.min = c + 1
-                               }
+                               lim.min = c + 1
                        case lt | gt:
+                               lim = old
                                if c == lim.min {
                                        lim.min++
                                }
@@ -319,22 +327,15 @@ func (ft *factsTable) update(parent *Block, v, w *Value, d domain, r relation) {
                        }
                        switch r {
                        case lt:
-                               if uc-1 < lim.umax {
-                                       lim.umax = uc - 1
-                               }
+                               lim.umax = uc - 1
                        case lt | eq:
-                               if uc < lim.umax {
-                                       lim.umax = uc
-                               }
+                               lim.umax = uc
                        case gt | eq:
-                               if uc > lim.umin {
-                                       lim.umin = uc
-                               }
+                               lim.umin = uc
                        case gt:
-                               if uc+1 > lim.umin {
-                                       lim.umin = uc + 1
-                               }
+                               lim.umin = uc + 1
                        case lt | gt:
+                               lim = old
                                if uc == lim.umin {
                                        lim.umin++
                                }
@@ -347,6 +348,7 @@ func (ft *factsTable) update(parent *Block, v, w *Value, d domain, r relation) {
                        }
                }
                ft.limitStack = append(ft.limitStack, limitFact{v.ID, old})
+               lim = old.intersect(lim)
                ft.limits[v.ID] = lim
                if v.Block.Func.pass.debug > 2 {
                        v.Block.Func.Warnl(parent.Pos, "parent=%s, new limits %s %s %s", parent, v, w, lim.String())