blob: d334163b6260bf5b2e92ed99156b3b406694513d [file] [edit]
// errorcheck -0 -d=ssa/known_bits/debug=1
//go:build amd64 || arm64 || s390x || ppc64le || riscv64
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package a
func knownBitsPhiAnd(cond bool) int {
x := 1
if cond {
x = 3
}
return x & 1 // ERROR "known value of v[0-9]+ \(And64\): 1$"
}
func knownBitsPhiAndGarbage(cond bool, x int) int {
x &^= 1
if cond {
x = 2
}
return x & 1 // ERROR "known value of v[0-9]+ \(And64\): 0$"
}
func unknownBitsPhiAnd(cond bool) int {
x := 1
if cond {
x = 2
}
return x & 1
}
func knownBitsOrGarbage(x, unknown int) int {
x |= 7
x |= unknown &^ 3
return x & 3 // ERROR "known value of v[0-9]+ \(And64\): 3$"
}
func unknownBitsOrGarbage(x, unknown int) int {
x |= 1
x |= unknown
return x & 3
}
func knownBitsDeferPattern(a, b bool) int {
bits := 0
bits |= 1 << 0
if a {
bits |= 1 << 1
}
bits |= 1 << 2
if b {
bits |= 1 << 3
}
return bits & (1<<2 | 1<<0) // ERROR "known value of v[0-9]+ \(And64\): 5$"
}
func knownBitsDeferPatternGarbage(a, b bool, garbage int) int {
bits := 0
bits |= 1 << 0
if a {
bits |= 1 << 1
}
bits |= 1 << 2
if b {
bits |= 1 << 3
}
bits ^= garbage &^ (1<<2 | 1<<0)
return bits & (1<<2 | 1<<0) // ERROR "known value of v[0-9]+ \(And64\): 5$"
}
func knownBitsXorToggle(a, b, c bool) int {
bits := 0
bits ^= 1 << 0
if a {
bits ^= 1 << 1
}
bits ^= 1 << 2
if b {
bits ^= 1 << 3
}
bits ^= 1 << 2
if c {
bits ^= 1 << 4
}
return bits & (1<<2 | 1<<0) // ERROR "known value of v[0-9]+ \(And64\): 1$"
}
func knownBitsXorToggleGarbage(a, b, c bool, garbage int) int {
bits := 0
bits ^= 1 << 0
if a {
bits ^= 1 << 1
}
bits ^= 1 << 2
if b {
bits ^= 1 << 3
}
bits ^= 1 << 2
if c {
bits ^= 1 << 4
}
bits ^= garbage &^ (1<<2 | 1<<0)
return bits & (1<<2 | 1<<0) // ERROR "known value of v[0-9]+ \(And64\): 1$"
}
func unknownBitsXorToggle(a, b, c bool) int {
bits := 0
bits ^= 1 << 0
if a {
bits ^= 1 << 1
}
bits ^= 1 << 2
if b {
bits ^= 1 << 2
}
bits ^= 1 << 2
if c {
bits ^= 1 << 4
}
return bits & (1<<2 | 1<<0)
}
func knownBitsPhiComAnd(cond bool) int {
x := 1
if cond {
x = 3
}
return ^x & 1 // ERROR "known value of v[0-9]+ \(And64\): 0$"
}
func knownBitsPhiComAndGarbage(cond bool, garbage int) int {
x := 1
if cond {
x = 3
}
x ^= garbage &^ 1
return ^x & 1 // ERROR "known value of v[0-9]+ \(And64\): 0$"
}
func unknownBitsPhiComAnd(cond bool) int {
x := 1
if cond {
x = 2
}
return ^x & 1
}
func knownBitsEqFalse(x, y uint64) bool {
x |= 1
y &^= 1
return x == y // ERROR "known value of v[0-9]+ \(Eq64\): false$"
}
func knownBitsEqTrue(x uint64, cond bool) bool {
x |= (1<<32 - 1) << 32
if cond {
x |= 42
}
x |= 1<<32 - 1 // ERROR "known value of v[0-9]+ \(Or64\): -1$"
return x == 1<<64-1 // ERROR "known value of v[0-9]+ \(Eq64\): true$"
}
func unknownBitsEq(x, y uint64) bool {
x |= 1
return x == y
}
func knownBitsNeqTrue(x, y uint64) bool {
x |= 1
y &^= 1
return x != y // ERROR "known value of v[0-9]+ \(Neq64\): true$"
}
func knownBitsNeqFalse(x uint64, cond bool) bool {
x |= (1<<32 - 1) << 32
if cond {
x |= 42
}
x |= 1<<32 - 1
return x != 1<<64-1 // ERROR "known value of v[0-9]+ \(Neq64\): false$"
}
func unknownBitsNeq(x, y uint64) bool {
x |= 1
return x != y
}
func knownBitsZeroExtPassThrough(x uint8) uint64 {
x |= 6
return uint64(x) & 6 // ERROR "known value of v[0-9]+ \(And64\): 6$"
}
func knownBitsZeroExtUpperHalf(x uint16) uint32 {
return uint32(x) & 0xFFFF0000 // ERROR "known value of v[0-9]+ \(And32\): 0$"
}
func unknownBitsZeroExt(x uint16) uint32 {
x |= 0xAAAA
return uint32(x) & 0xFFFFF000
}
func cvtBoolToUint8(cond bool) (r uint8) {
if cond {
r = 1
}
return r
}
func knownBitsCvtBoolToUint8False(x, y uint64) uint8 {
x |= 1
y &^= 1
bool := x == y // ERROR "known value of v[0-9]+ \(Eq64\): false$"
return cvtBoolToUint8(bool) & 1 // ERROR "known value of v[0-9]+ \(CvtBoolToUint8\): 0$"
}
func knownBitsCvtBoolToUint8True(x int64, cond bool) uint8 {
x |= 6
if cond {
x |= 1
x |= 4
}
// I would expect "known value of v[0-9]+ \(And64\): 6$" to be required, but somehow it's not there even tho the AND is being folded.
// I think it's an issue with the And's LOC meaning known bits prints it without a LOC and errorcheck skips it.
r := cvtBoolToUint8(x&6 == 6) // ERROR "known value of v[0-9]+ \(Eq64\): true$" "known value of v[0-9]+ \(CvtBoolToUint8\): 1$"
if cond {
r |= 4 // ERROR "known value of v[0-9]+ \(Or8\): 5$"
}
return r & 3 // ERROR "known value of v[0-9]+ \(And8\): 1$"
}
func unknownBitsCvtBoolToUint8(cond bool) uint8 {
return cvtBoolToUint8(cond) & 1
}
func knownBitsSignExtPassThrough(x int8) int64 {
x |= 6
return int64(x) & 6 // ERROR "known value of v[0-9]+ \(And64\): 6$"
}
func knownBitsSignExtUpperHalf(x int16) int32 {
x |= -1 << 15
return int32(x) & (-1 << 16) // ERROR "known value of v[0-9]+ \(And32\): -65536$"
}
func unknownBitsSignExt(x int16) int32 {
x |= -0b010101010101010
return int32(x) & -1 << 12
}
func knownBitsLsh(x, y uint32) uint32 {
x |= 0b11110
x &^= 0b100000
y &= 2
// ???01111?
// ?01111???
// ---------
// ????11???
return (x << y) & 0b11000 // ERROR "known value of v[0-9]+ \(And32\): 24$"
}
func knownBitsLshZero(x, y uint64) uint64 {
x &^= 2
y &^= 2
y |= 128
return (x << y) & 8 // ERROR "known value of v[0-9]+ \(And64\): 0$" "known value of v[0-9]+ \(Lsh64x[0-9]+\): 0$"
}
func unknownBitsLshLeftSideMsb(x uint32, y uint32) uint32 {
x |= 0b11110
x &^= 0b100000
y &= 2
return (x << y) & 0b111000
}
func unknownBitsLshLeftSideLsb(x uint32, y uint32) uint32 {
x |= 0b11110
x &^= 0b100000
y &= 2
return (x << y) & 0b011100
}
func unknownBitsLshRightSide(x uint32, y uint32) uint32 {
x |= 0b11110
x &^= 0b100000
y &= 6
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
}
func knownBitsRsh(x, y int32) int32 {
x |= 0b11110
x &^= 0b100000
y &= 2
// ?01111?
// ???0111
// -------
// ????11?
return (x >> y) & 0b110 // ERROR "known value of v[0-9]+ \(And32\): 6$"
}
func knownBitsRshSignCopy(x, y int64) int64 {
x |= -1 << 63
y |= 128
return (x >> y) & 1 // ERROR "known value of v[0-9]+ \(And64\): 1$"
}
func unknownBitsRshLeftSideMsb(x int32, y int32) int32 {
x |= 0b11110
x &^= 0b100000
y &= 2
return (x >> y) & 0b1110
}
func unknownBitsRshLeftSideLsb(x int32, y int32) int32 {
x |= 0b11110
x &^= 0b100000
y &= 2
return (x >> y) & 0b111
}
func unknownBitsRshRightSide(x int32, y int32) int32 {
x |= 0b11110
x &^= 0b100000
y &= 6
return (x >> y) & 0b110
}
func knownBitsTrunc(x int64, cond bool) int32 {
x |= 2
if cond {
x = 3
}
return int32(x) & 2 // ERROR "known value of v[0-9]+ \(And32\): 2$"
}
func unknownBitsTrunc(x int64, cond bool) int32 {
x |= 2
if cond {
x = 3
}
return int32(x) & 1
}
func knownBitsSextAfterTrunc(x int64, cond1, cond2 bool) int64 {
x |= -1 << 31
if cond1 {
x = -3
}
truncated := int32(x)
if cond2 {
truncated |= 4
}
return int64(truncated) & (-1 << 63) // ERROR "known value of v[0-9]+ \(And64\): -9223372036854775808$"
}
func unknownBitsSextAfterTrunc(x int64, cond1, cond2 bool) int64 {
x |= 2
if cond1 {
x = 3
}
truncated := int32(x)
if cond2 {
truncated |= 4
}
return int64(truncated) & (-1 << 63)
}