| // 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) |
| } |