Skip to content

Commit 2f31659

Browse files
Jorroporandall77
authored andcommitted
cmd/compile: compute Complement's limits from argument's limits
I was not sure this was correct so I exhaustively checked all possibilities: https://go.dev/play/p/hjmCLm4Iagz https://go.dev/play/p/R9RuRGKwCbN Change-Id: I85f053df825a4d77f978de42f8a1fcaf4b881def Reviewed-on: https://go-review.googlesource.com/c/go/+/605696 Reviewed-by: Keith Randall <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: David Chase <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Carlos Amedee <[email protected]>
1 parent 4f2c0e5 commit 2f31659

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

src/cmd/compile/internal/ssa/prove.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,42 @@ func (l limit) exp2(b uint) limit {
341341
return r
342342
}
343343

344+
// Similar to add, but computes the complement of the limit for bitsize b.
345+
func (l limit) com(b uint) limit {
346+
switch b {
347+
case 64:
348+
return limit{
349+
min: ^l.max,
350+
max: ^l.min,
351+
umin: ^l.umax,
352+
umax: ^l.umin,
353+
}
354+
case 32:
355+
return limit{
356+
min: int64(^int32(l.max)),
357+
max: int64(^int32(l.min)),
358+
umin: uint64(^uint32(l.umax)),
359+
umax: uint64(^uint32(l.umin)),
360+
}
361+
case 16:
362+
return limit{
363+
min: int64(^int16(l.max)),
364+
max: int64(^int16(l.min)),
365+
umin: uint64(^uint16(l.umax)),
366+
umax: uint64(^uint16(l.umin)),
367+
}
368+
case 8:
369+
return limit{
370+
min: int64(^int8(l.max)),
371+
max: int64(^int8(l.min)),
372+
umin: uint64(^uint8(l.umax)),
373+
umax: uint64(^uint8(l.umin)),
374+
}
375+
default:
376+
panic("unreachable")
377+
}
378+
}
379+
344380
var noLimit = limit{math.MinInt64, math.MaxInt64, 0, math.MaxUint64}
345381

346382
// a limitFact is a limit known for a particular value.
@@ -1714,6 +1750,9 @@ func (ft *factsTable) flowLimit(v *Value) bool {
17141750
a := ft.limits[v.Args[0].ID]
17151751
b := ft.limits[v.Args[1].ID]
17161752
return ft.unsignedMax(v, 1<<bits.Len64(a.umax|b.umax)-1)
1753+
case OpCom64, OpCom32, OpCom16, OpCom8:
1754+
a := ft.limits[v.Args[0].ID]
1755+
return ft.newLimit(v, a.com(uint(v.Type.Size())*8))
17171756

17181757
// Arithmetic.
17191758
case OpAdd64:

test/prove.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,27 @@ func trunc64to16(a uint64, ensureAllBranchesCouldHappen func() bool) uint16 {
16061606
return z
16071607
}
16081608

1609+
func com64(a uint64, ensureAllBranchesCouldHappen func() bool) uint64 {
1610+
a &= 0xffff
1611+
a |= 0xff
1612+
1613+
z := ^a
1614+
1615+
if ensureAllBranchesCouldHappen() && z > ^uint64(0xff) { // ERROR "Disproved Less64U$"
1616+
return 42
1617+
}
1618+
if ensureAllBranchesCouldHappen() && z <= ^uint64(0xff) { // ERROR "Proved Leq64U$"
1619+
return 1337
1620+
}
1621+
if ensureAllBranchesCouldHappen() && z < ^uint64(0xffff) { // ERROR "Disproved Less64U$"
1622+
return 42
1623+
}
1624+
if ensureAllBranchesCouldHappen() && z >= ^uint64(0xffff) { // ERROR "Proved Leq64U$"
1625+
return 1337
1626+
}
1627+
return z
1628+
}
1629+
16091630
//go:noinline
16101631
func useInt(a int) {
16111632
}

0 commit comments

Comments
 (0)