mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: simplify limit logic in prove
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>
This commit is contained in:
parent
44e20b64ef
commit
2e9cf5f66e
1 changed files with 28 additions and 26 deletions
|
|
@ -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)
|
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}
|
var noLimit = limit{math.MinInt64, math.MaxInt64, 0, math.MaxUint64}
|
||||||
|
|
||||||
// a limitFact is a limit known for a particular value.
|
// 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 {
|
if !ok {
|
||||||
old = noLimit
|
old = noLimit
|
||||||
}
|
}
|
||||||
lim := old
|
lim := noLimit
|
||||||
// Update lim with the new information we know.
|
|
||||||
switch d {
|
switch d {
|
||||||
case signed:
|
case signed:
|
||||||
switch r {
|
switch r {
|
||||||
case lt:
|
case lt:
|
||||||
if c-1 < lim.max {
|
lim.max = c - 1
|
||||||
lim.max = c - 1
|
|
||||||
}
|
|
||||||
case lt | eq:
|
case lt | eq:
|
||||||
if c < lim.max {
|
lim.max = c
|
||||||
lim.max = c
|
|
||||||
}
|
|
||||||
case gt | eq:
|
case gt | eq:
|
||||||
if c > lim.min {
|
lim.min = c
|
||||||
lim.min = c
|
|
||||||
}
|
|
||||||
case gt:
|
case gt:
|
||||||
if c+1 > lim.min {
|
lim.min = c + 1
|
||||||
lim.min = c + 1
|
|
||||||
}
|
|
||||||
case lt | gt:
|
case lt | gt:
|
||||||
|
lim = old
|
||||||
if c == lim.min {
|
if c == lim.min {
|
||||||
lim.min++
|
lim.min++
|
||||||
}
|
}
|
||||||
|
|
@ -319,22 +327,15 @@ func (ft *factsTable) update(parent *Block, v, w *Value, d domain, r relation) {
|
||||||
}
|
}
|
||||||
switch r {
|
switch r {
|
||||||
case lt:
|
case lt:
|
||||||
if uc-1 < lim.umax {
|
lim.umax = uc - 1
|
||||||
lim.umax = uc - 1
|
|
||||||
}
|
|
||||||
case lt | eq:
|
case lt | eq:
|
||||||
if uc < lim.umax {
|
lim.umax = uc
|
||||||
lim.umax = uc
|
|
||||||
}
|
|
||||||
case gt | eq:
|
case gt | eq:
|
||||||
if uc > lim.umin {
|
lim.umin = uc
|
||||||
lim.umin = uc
|
|
||||||
}
|
|
||||||
case gt:
|
case gt:
|
||||||
if uc+1 > lim.umin {
|
lim.umin = uc + 1
|
||||||
lim.umin = uc + 1
|
|
||||||
}
|
|
||||||
case lt | gt:
|
case lt | gt:
|
||||||
|
lim = old
|
||||||
if uc == lim.umin {
|
if uc == lim.umin {
|
||||||
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})
|
ft.limitStack = append(ft.limitStack, limitFact{v.ID, old})
|
||||||
|
lim = old.intersect(lim)
|
||||||
ft.limits[v.ID] = lim
|
ft.limits[v.ID] = lim
|
||||||
if v.Block.Func.pass.debug > 2 {
|
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())
|
v.Block.Func.Warnl(parent.Pos, "parent=%s, new limits %s %s %s", parent, v, w, lim.String())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue