Commit 68def820 authored by Giovanni Bajo's avatar Giovanni Bajo

cmd/compile: fix bit-test rules for highest bit

Bit-test rules failed to match when matching the highest bit
of a word because operands in SSA are signed int64. Fix
them by treating them as unsigned (and correctly handling
32-bit operands as well).

Tests will be added in next CL.

Change-Id: I491c4e88e7e2f87e9bb72bd0d9fa5d4025b90736
Reviewed-on: https://go-review.googlesource.com/94765Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent 098208a0
......@@ -582,30 +582,30 @@
// Same, mutatis mutandis, for UGE and SETAE, and CC and SETCC.
((NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) && !config.nacl -> ((ULT|UGE) (BTL x y))
((NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) && !config.nacl -> ((ULT|UGE) (BTQ x y))
((NE|EQ) (TESTLconst [c] x)) && isPowerOfTwo(c) && log2(c) < 32 && !config.nacl
-> ((ULT|UGE) (BTLconst [log2(c)] x))
((NE|EQ) (TESTQconst [c] x)) && isPowerOfTwo(c) && log2(c) < 64 && !config.nacl
((NE|EQ) (TESTLconst [c] x)) && isUint32PowerOfTwo(c) && !config.nacl
-> ((ULT|UGE) (BTLconst [log2uint32(c)] x))
((NE|EQ) (TESTQconst [c] x)) && isUint64PowerOfTwo(c) && !config.nacl
-> ((ULT|UGE) (BTQconst [log2(c)] x))
((NE|EQ) (TESTQ (MOVQconst [c]) x)) && isPowerOfTwo(c) && log2(c) < 64 && !config.nacl
((NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUint64PowerOfTwo(c) && !config.nacl
-> ((ULT|UGE) (BTQconst [log2(c)] x))
(SET(NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) && !config.nacl -> (SET(B|AE) (BTL x y))
(SET(NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) && !config.nacl -> (SET(B|AE) (BTQ x y))
(SET(NE|EQ) (TESTLconst [c] x)) && isPowerOfTwo(c) && log2(c) < 32 && !config.nacl
-> (SET(B|AE) (BTLconst [log2(c)] x))
(SET(NE|EQ) (TESTQconst [c] x)) && isPowerOfTwo(c) && log2(c) < 64 && !config.nacl
(SET(NE|EQ) (TESTLconst [c] x)) && isUint32PowerOfTwo(c) && !config.nacl
-> (SET(B|AE) (BTLconst [log2uint32(c)] x))
(SET(NE|EQ) (TESTQconst [c] x)) && isUint64PowerOfTwo(c) && !config.nacl
-> (SET(B|AE) (BTQconst [log2(c)] x))
(SET(NE|EQ) (TESTQ (MOVQconst [c]) x)) && isPowerOfTwo(c) && log2(c) < 64 && !config.nacl
(SET(NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUint64PowerOfTwo(c) && !config.nacl
-> (SET(B|AE) (BTQconst [log2(c)] x))
// SET..mem variant
(SET(NE|EQ)mem [off] {sym} ptr (TESTL (SHLL (MOVLconst [1]) x) y) mem) && !config.nacl
-> (SET(B|AE)mem [off] {sym} ptr (BTL x y) mem)
(SET(NE|EQ)mem [off] {sym} ptr (TESTQ (SHLQ (MOVQconst [1]) x) y) mem) && !config.nacl
-> (SET(B|AE)mem [off] {sym} ptr (BTQ x y) mem)
(SET(NE|EQ)mem [off] {sym} ptr (TESTLconst [c] x) mem) && isPowerOfTwo(c) && log2(c) < 32 && !config.nacl
-> (SET(B|AE)mem [off] {sym} ptr (BTLconst [log2(c)] x) mem)
(SET(NE|EQ)mem [off] {sym} ptr (TESTQconst [c] x) mem) && isPowerOfTwo(c) && log2(c) < 64 && !config.nacl
(SET(NE|EQ)mem [off] {sym} ptr (TESTLconst [c] x) mem) && isUint32PowerOfTwo(c) && !config.nacl
-> (SET(B|AE)mem [off] {sym} ptr (BTLconst [log2uint32(c)] x) mem)
(SET(NE|EQ)mem [off] {sym} ptr (TESTQconst [c] x) mem) && isUint64PowerOfTwo(c) && !config.nacl
-> (SET(B|AE)mem [off] {sym} ptr (BTQconst [log2(c)] x) mem)
(SET(NE|EQ)mem [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem) && isPowerOfTwo(c) && log2(c) < 64 && !config.nacl
(SET(NE|EQ)mem [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem) && isUint64PowerOfTwo(c) && !config.nacl
-> (SET(B|AE)mem [off] {sym} ptr (BTQconst [log2(c)] x) mem)
// Fold boolean negation into SETcc.
......
......@@ -329,11 +329,29 @@ func log2(n int64) (l int64) {
return
}
// log2uint32 returns logarithm in base 2 of uint32(n), with log2(0) = -1.
// Rounds down.
func log2uint32(n int64) (l int64) {
return log2(int64(uint32(n)))
}
// isPowerOfTwo reports whether n is a power of 2.
func isPowerOfTwo(n int64) bool {
return n > 0 && n&(n-1) == 0
}
// isUint64PowerOfTwo reports whether uint64(n) is a power of 2.
func isUint64PowerOfTwo(in int64) bool {
n := uint64(in)
return n > 0 && n&(n-1) == 0
}
// isUint32PowerOfTwo reports whether uint32(n) is a power of 2.
func isUint32PowerOfTwo(in int64) bool {
n := uint64(uint32(in))
return n > 0 && n&(n-1) == 0
}
// is32Bit reports whether n can be represented as a signed 32 bit integer.
func is32Bit(n int64) bool {
return n == int64(int32(n))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment