cmd/compile: do not misscompile x+x << 63 to x << 0 on amd64

Fixes #79182

Change-Id: I63ca6cb1bd3f6752a7e9b809cfffc8d45b7adc51
Reviewed-on: https://go-review.googlesource.com/c/go/+/774040
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Jorropo 2026-05-05 00:32:58 +02:00 committed by Gopher Robot
parent 784ea961a4
commit c3bfc824a5
3 changed files with 38 additions and 3 deletions

View file

@ -912,7 +912,8 @@
(LEA(Q|L)2 [0] {s} (ADD(Q|L) x x) x) && s == nil => (SHL(Q|L)const [2] x)
// (x + x) << 2 -> x << 3 and similar
(SHL(Q|L)const [c] (ADD(Q|L) x x)) => (SHL(Q|L)const [c+1] x)
(SHLQconst [c] (ADDQ x x)) && c < 63 => (SHLQconst [c+1] x)
(SHLLconst [c] (ADDL x x)) && c < 31 => (SHLLconst [c+1] x)
// reverse ordering of compare instruction
(SETL (InvertFlags x)) => (SETG x)

View file

@ -26294,6 +26294,7 @@ func rewriteValueAMD64_OpAMD64SHLLconst(v *Value) bool {
return true
}
// match: (SHLLconst [c] (ADDL x x))
// cond: c < 31
// result: (SHLLconst [c+1] x)
for {
c := auxIntToInt8(v.AuxInt)
@ -26301,7 +26302,7 @@ func rewriteValueAMD64_OpAMD64SHLLconst(v *Value) bool {
break
}
x := v_0.Args[1]
if x != v_0.Args[0] {
if x != v_0.Args[0] || !(c < 31) {
break
}
v.reset(OpAMD64SHLLconst)
@ -26565,6 +26566,7 @@ func rewriteValueAMD64_OpAMD64SHLQconst(v *Value) bool {
return true
}
// match: (SHLQconst [c] (ADDQ x x))
// cond: c < 63
// result: (SHLQconst [c+1] x)
for {
c := auxIntToInt8(v.AuxInt)
@ -26572,7 +26574,7 @@ func rewriteValueAMD64_OpAMD64SHLQconst(v *Value) bool {
break
}
x := v_0.Args[1]
if x != v_0.Args[0] {
if x != v_0.Args[0] || !(c < 63) {
break
}
v.reset(OpAMD64SHLQconst)

View file

@ -0,0 +1,32 @@
// run
// 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.
// Issue 79182: SHLQconst/SHLLconst rewrite rule for (x+x)<<c
// missed a bounds check on c, causing c+1 to overflow the valid
// shift range and producing incorrect results on amd64.
package main
//go:noinline
func shl32(x uint32) uint32 {
return (x + x) << 31
}
//go:noinline
func shl64(x uint64) uint64 {
return (x + x) << 63
}
func main() {
if got := shl32(1); got != 0 {
println("shl32(1) =", got, "want 0")
panic("FAIL")
}
if got := shl64(1); got != 0 {
println("shl64(1) =", got, "want 0")
panic("FAIL")
}
}