Closed
Description
Both arm and arm64 have rules like:
(SUBshiftLL x (SLLconst x [c]) [d]) && c==d => (MOVDconst [0])
This actually encodes the identity x - x<<c<<c == 0
, which is incorrect. It should be
(SUBshiftLL (SLLconst x [c]) x [d]) && c==d => (MOVDconst [0])
Which encodes the correct identity x<<c - x<<c == 0
.
It turns out to be quite hard to trigger this bad rule, as x<<c<<c
is almost always reduced by the generic rewrite pass. But here's a case which gets through:
package main
func f(x uint64) uint64 {
s := "\x05"
c := s[0]
return x - x<<c<<5
}
func main() {
println(f(5))
}
This should print some giant number (18446744073709546501), but on arm64 it prints 0.