mirror of
https://github.com/golang/go.git
synced 2026-06-28 03:40:37 +00:00
cmd/compile: add RshU support to known bits
I havn't searched a real world usecase for this but it seems fine for completeness. This doesn't have any hits in the std. Updates #78633 Change-Id: Id69a3c9ccf945f0d91dac6618afe7dfaf1af8da8 Reviewed-on: https://go-review.googlesource.com/c/go/+/766080 Reviewed-by: Mark Freeman <markfreeman@google.com> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Jorropo <jorropo.pgm@gmail.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Carlos Amedee <carlos@golang.org>
This commit is contained in:
parent
977041b065
commit
767140eff2
2 changed files with 89 additions and 0 deletions
|
|
@ -122,6 +122,11 @@ func (kb *knownBitsState) fold(v *Value) (value, known int64) {
|
|||
OpLsh8x32, OpLsh16x32, OpLsh32x32, OpLsh64x32,
|
||||
OpLsh8x64, OpLsh16x64, OpLsh32x64, OpLsh64x64:
|
||||
return kb.computeKnownBitsForLsh(v)
|
||||
case OpRsh8Ux8, OpRsh16Ux8, OpRsh32Ux8, OpRsh64Ux8,
|
||||
OpRsh8Ux16, OpRsh16Ux16, OpRsh32Ux16, OpRsh64Ux16,
|
||||
OpRsh8Ux32, OpRsh16Ux32, OpRsh32Ux32, OpRsh64Ux32,
|
||||
OpRsh8Ux64, OpRsh16Ux64, OpRsh32Ux64, OpRsh64Ux64:
|
||||
return kb.computeKnownBitsForRshU(v)
|
||||
default:
|
||||
return 0, 0
|
||||
}
|
||||
|
|
@ -287,3 +292,42 @@ func (kb *knownBitsState) computeKnownBitsForLsh(v *Value) (value, known int64)
|
|||
|
||||
return value & known, known
|
||||
}
|
||||
|
||||
// computeKnownBitsForRshU is the same as computeKnownBitsForLsh but for unsigned right shifts.
|
||||
func (kb *knownBitsState) computeKnownBitsForRshU(v *Value) (value, known int64) {
|
||||
xSize := v.Args[0].Type.Size() * 8
|
||||
x, xk := kb.fold(v.Args[0])
|
||||
y, yk := kb.fold(v.Args[1])
|
||||
if uint64(y) >= uint64(xSize) {
|
||||
return 0, -1
|
||||
}
|
||||
|
||||
set := false
|
||||
if v.AuxInt == 0 && uint64(^yk) >= uint64(xSize) {
|
||||
// this implement the default case of the equivalent switch.
|
||||
// if the shift isn't bounded and there are unknown bits above the shift size we might completely stomp all bits.
|
||||
value = 0
|
||||
known = -1
|
||||
set = true
|
||||
}
|
||||
xk |= -1 << xSize
|
||||
x &= (1<<xSize - 1)
|
||||
yk &= xSize - 1
|
||||
|
||||
for i := range xSize {
|
||||
if i&yk != y {
|
||||
continue
|
||||
}
|
||||
a, k := uint64(x)>>i, uint64(xk)>>i|(^uint64(0)<<(64-i))
|
||||
if !set {
|
||||
value, known = int64(a), int64(k)
|
||||
set = true
|
||||
} else {
|
||||
known &^= value ^ int64(a)
|
||||
known &= int64(k)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
return value & known, known
|
||||
}
|
||||
|
|
|
|||
|
|
@ -294,3 +294,48 @@ func unknownBitsLshRightSide(x uint32, y uint32) uint32 {
|
|||
|
||||
return (x << y) & 0b11000
|
||||
}
|
||||
|
||||
func knownBitsRshU(x, y uint32) uint32 {
|
||||
x |= 0b11110
|
||||
x &^= 0b100000
|
||||
y &= 2
|
||||
|
||||
// ?01111?
|
||||
// ???0111
|
||||
// -------
|
||||
// ????11?
|
||||
|
||||
return (x >> y) & 0b110 // ERROR "known value of v[0-9]+ \(And32\): 6$"
|
||||
}
|
||||
|
||||
func knownBitsRshUZero(x, y uint64) uint64 {
|
||||
x &^= 4
|
||||
y &^= 2
|
||||
y |= 128
|
||||
|
||||
return (x >> y) & 1 // ERROR "known value of v[0-9]+ \(And64\): 0$" "known value of v[0-9]+ \(Rsh64Ux[0-9]+\): 0$"
|
||||
}
|
||||
|
||||
func unknownBitsRshULeftSideMsb(x uint32, y uint32) uint32 {
|
||||
x |= 0b11110
|
||||
x &^= 0b100000
|
||||
y &= 2
|
||||
|
||||
return (x >> y) & 0b1110
|
||||
}
|
||||
|
||||
func unknownBitsRshULeftSideLsb(x uint32, y uint32) uint32 {
|
||||
x |= 0b11110
|
||||
x &^= 0b100000
|
||||
y &= 2
|
||||
|
||||
return (x >> y) & 0b111
|
||||
}
|
||||
|
||||
func unknownBitsRshURightSide(x uint32, y uint32) uint32 {
|
||||
x |= 0b11110
|
||||
x &^= 0b100000
|
||||
y &= 6
|
||||
|
||||
return (x >> y) & 0b110
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue