mirror of
https://github.com/golang/go
synced 2024-11-26 10:38:07 -07:00
cmd/compile: use unsigned loads for multi-element comparisons
When loading multiple elements of an array into a single register, make sure we treat them as unsigned. When treated as signed, the upper bits might all be set, causing the shift-or combo to clobber the values higher in the register. Fixes #23719. Change-Id: Ic87da03e9bd0fe2c60bb214b99f846e4e9446052 Reviewed-on: https://go-review.googlesource.com/92335 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ilya Tocar <ilya.tocar@intel.com>
This commit is contained in:
parent
85bdd05c05
commit
23e8e197b0
@ -1002,6 +1002,20 @@ var linuxAMD64Tests = []*asmTest{
|
|||||||
}`,
|
}`,
|
||||||
pos: []string{"\tCMPL\t[A-Z]"},
|
pos: []string{"\tCMPL\t[A-Z]"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fn: `
|
||||||
|
func $(a,b [3]int16) bool {
|
||||||
|
return a == b
|
||||||
|
}`,
|
||||||
|
pos: []string{"\tCMPL\t[A-Z]"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fn: `
|
||||||
|
func $(a,b [12]int8) bool {
|
||||||
|
return a == b
|
||||||
|
}`,
|
||||||
|
pos: []string{"\tCMPQ\t[A-Z]", "\tCMPL\t[A-Z]"},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fn: `
|
fn: `
|
||||||
func f70(a,b [15]byte) bool {
|
func f70(a,b [15]byte) bool {
|
||||||
|
@ -3415,18 +3415,23 @@ func walkcompare(n *Node, init *Nodes) *Node {
|
|||||||
i++
|
i++
|
||||||
remains -= t.Elem().Width
|
remains -= t.Elem().Width
|
||||||
} else {
|
} else {
|
||||||
|
elemType := t.Elem().ToUnsigned()
|
||||||
cmplw := nod(OINDEX, cmpl, nodintconst(int64(i)))
|
cmplw := nod(OINDEX, cmpl, nodintconst(int64(i)))
|
||||||
cmplw = conv(cmplw, convType)
|
cmplw = conv(cmplw, elemType) // convert to unsigned
|
||||||
|
cmplw = conv(cmplw, convType) // widen
|
||||||
cmprw := nod(OINDEX, cmpr, nodintconst(int64(i)))
|
cmprw := nod(OINDEX, cmpr, nodintconst(int64(i)))
|
||||||
|
cmprw = conv(cmprw, elemType)
|
||||||
cmprw = conv(cmprw, convType)
|
cmprw = conv(cmprw, convType)
|
||||||
// For code like this: uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 ...
|
// For code like this: uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 ...
|
||||||
// ssa will generate a single large load.
|
// ssa will generate a single large load.
|
||||||
for offset := int64(1); offset < step; offset++ {
|
for offset := int64(1); offset < step; offset++ {
|
||||||
lb := nod(OINDEX, cmpl, nodintconst(int64(i+offset)))
|
lb := nod(OINDEX, cmpl, nodintconst(int64(i+offset)))
|
||||||
|
lb = conv(lb, elemType)
|
||||||
lb = conv(lb, convType)
|
lb = conv(lb, convType)
|
||||||
lb = nod(OLSH, lb, nodintconst(int64(8*t.Elem().Width*offset)))
|
lb = nod(OLSH, lb, nodintconst(int64(8*t.Elem().Width*offset)))
|
||||||
cmplw = nod(OOR, cmplw, lb)
|
cmplw = nod(OOR, cmplw, lb)
|
||||||
rb := nod(OINDEX, cmpr, nodintconst(int64(i+offset)))
|
rb := nod(OINDEX, cmpr, nodintconst(int64(i+offset)))
|
||||||
|
rb = conv(rb, elemType)
|
||||||
rb = conv(rb, convType)
|
rb = conv(rb, convType)
|
||||||
rb = nod(OLSH, rb, nodintconst(int64(8*t.Elem().Width*offset)))
|
rb = nod(OLSH, rb, nodintconst(int64(8*t.Elem().Width*offset)))
|
||||||
cmprw = nod(OOR, cmprw, rb)
|
cmprw = nod(OOR, cmprw, rb)
|
||||||
|
42
test/fixedbugs/issue23719.go
Normal file
42
test/fixedbugs/issue23719.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// run
|
||||||
|
|
||||||
|
// Copyright 2018 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 main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
v1 := [2]int32{-1, 88}
|
||||||
|
v2 := [2]int32{-1, 99}
|
||||||
|
if v1 == v2 {
|
||||||
|
panic("bad comparison")
|
||||||
|
}
|
||||||
|
|
||||||
|
w1 := [2]int16{-1, 88}
|
||||||
|
w2 := [2]int16{-1, 99}
|
||||||
|
if w1 == w2 {
|
||||||
|
panic("bad comparison")
|
||||||
|
}
|
||||||
|
x1 := [4]int16{-1, 88, 88, 88}
|
||||||
|
x2 := [4]int16{-1, 99, 99, 99}
|
||||||
|
if x1 == x2 {
|
||||||
|
panic("bad comparison")
|
||||||
|
}
|
||||||
|
|
||||||
|
a1 := [2]int8{-1, 88}
|
||||||
|
a2 := [2]int8{-1, 99}
|
||||||
|
if a1 == a2 {
|
||||||
|
panic("bad comparison")
|
||||||
|
}
|
||||||
|
b1 := [4]int8{-1, 88, 88, 88}
|
||||||
|
b2 := [4]int8{-1, 99, 99, 99}
|
||||||
|
if b1 == b2 {
|
||||||
|
panic("bad comparison")
|
||||||
|
}
|
||||||
|
c1 := [8]int8{-1, 88, 88, 88, 88, 88, 88, 88}
|
||||||
|
c2 := [8]int8{-1, 99, 99, 99, 99, 99, 99, 99}
|
||||||
|
if c1 == c2 {
|
||||||
|
panic("bad comparison")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user