mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
cmd/compile: fix MIPS SGTconst-with-shift rules
(SGTconst [c] (SRLconst _ [d])) && 0 <= int32(c) && uint32(d) <= 31 && 1<<(32-uint32(d)) <= int32(c) -> (MOVWconst [1]) This rule is problematic. 1<<(32-uint32(d)) <= int32(c) meant to say that it is true if c is greater than the largest possible value of the right shift. But when d==1, 1<<(32-1) is negative and results in the wrong comparison. Rewrite the rules in a more direct way. Fixes #29402. Change-Id: I5940fc9538d9bc3a4bcae8aa34672867540dc60e Reviewed-on: https://go-review.googlesource.com/c/155798 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
bfaf11c158
commit
6a64efc250
|
@ -670,8 +670,8 @@
|
||||||
(SGTUconst [c] (MOVHUreg _)) && 0xffff < uint32(c) -> (MOVWconst [1])
|
(SGTUconst [c] (MOVHUreg _)) && 0xffff < uint32(c) -> (MOVWconst [1])
|
||||||
(SGTconst [c] (ANDconst [m] _)) && 0 <= int32(m) && int32(m) < int32(c) -> (MOVWconst [1])
|
(SGTconst [c] (ANDconst [m] _)) && 0 <= int32(m) && int32(m) < int32(c) -> (MOVWconst [1])
|
||||||
(SGTUconst [c] (ANDconst [m] _)) && uint32(m) < uint32(c) -> (MOVWconst [1])
|
(SGTUconst [c] (ANDconst [m] _)) && uint32(m) < uint32(c) -> (MOVWconst [1])
|
||||||
(SGTconst [c] (SRLconst _ [d])) && 0 <= int32(c) && uint32(d) <= 31 && 1<<(32-uint32(d)) <= int32(c) -> (MOVWconst [1])
|
(SGTconst [c] (SRLconst _ [d])) && 0 <= int32(c) && uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c) -> (MOVWconst [1])
|
||||||
(SGTUconst [c] (SRLconst _ [d])) && uint32(d) <= 31 && 1<<(32-uint32(d)) <= uint32(c) -> (MOVWconst [1])
|
(SGTUconst [c] (SRLconst _ [d])) && uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c) -> (MOVWconst [1])
|
||||||
|
|
||||||
// absorb constants into branches
|
// absorb constants into branches
|
||||||
(EQ (MOVWconst [0]) yes no) -> (First nil yes no)
|
(EQ (MOVWconst [0]) yes no) -> (First nil yes no)
|
||||||
|
|
|
@ -667,8 +667,8 @@
|
||||||
(SGTconst [c] (MOVWUreg _)) && c < 0 -> (MOVVconst [0])
|
(SGTconst [c] (MOVWUreg _)) && c < 0 -> (MOVVconst [0])
|
||||||
(SGTconst [c] (ANDconst [m] _)) && 0 <= m && m < c -> (MOVVconst [1])
|
(SGTconst [c] (ANDconst [m] _)) && 0 <= m && m < c -> (MOVVconst [1])
|
||||||
(SGTUconst [c] (ANDconst [m] _)) && uint64(m) < uint64(c) -> (MOVVconst [1])
|
(SGTUconst [c] (ANDconst [m] _)) && uint64(m) < uint64(c) -> (MOVVconst [1])
|
||||||
(SGTconst [c] (SRLVconst _ [d])) && 0 <= c && 0 < d && d <= 63 && 1<<uint64(64-d) <= c -> (MOVVconst [1])
|
(SGTconst [c] (SRLVconst _ [d])) && 0 <= c && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c) -> (MOVVconst [1])
|
||||||
(SGTUconst [c] (SRLVconst _ [d])) && 0 < d && d <= 63 && 1<<uint64(64-d) <= uint64(c) -> (MOVVconst [1])
|
(SGTUconst [c] (SRLVconst _ [d])) && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c) -> (MOVVconst [1])
|
||||||
|
|
||||||
// absorb constants into branches
|
// absorb constants into branches
|
||||||
(EQ (MOVVconst [0]) yes no) -> (First nil yes no)
|
(EQ (MOVVconst [0]) yes no) -> (First nil yes no)
|
||||||
|
|
|
@ -5625,7 +5625,7 @@ func rewriteValueMIPS_OpMIPSSGTUconst_0(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SGTUconst [c] (SRLconst _ [d]))
|
// match: (SGTUconst [c] (SRLconst _ [d]))
|
||||||
// cond: uint32(d) <= 31 && 1<<(32-uint32(d)) <= uint32(c)
|
// cond: uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c)
|
||||||
// result: (MOVWconst [1])
|
// result: (MOVWconst [1])
|
||||||
for {
|
for {
|
||||||
c := v.AuxInt
|
c := v.AuxInt
|
||||||
|
@ -5634,7 +5634,7 @@ func rewriteValueMIPS_OpMIPSSGTUconst_0(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
d := v_0.AuxInt
|
d := v_0.AuxInt
|
||||||
if !(uint32(d) <= 31 && 1<<(32-uint32(d)) <= uint32(c)) {
|
if !(uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpMIPSMOVWconst)
|
v.reset(OpMIPSMOVWconst)
|
||||||
|
@ -5862,7 +5862,7 @@ func rewriteValueMIPS_OpMIPSSGTconst_10(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SGTconst [c] (SRLconst _ [d]))
|
// match: (SGTconst [c] (SRLconst _ [d]))
|
||||||
// cond: 0 <= int32(c) && uint32(d) <= 31 && 1<<(32-uint32(d)) <= int32(c)
|
// cond: 0 <= int32(c) && uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c)
|
||||||
// result: (MOVWconst [1])
|
// result: (MOVWconst [1])
|
||||||
for {
|
for {
|
||||||
c := v.AuxInt
|
c := v.AuxInt
|
||||||
|
@ -5871,7 +5871,7 @@ func rewriteValueMIPS_OpMIPSSGTconst_10(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
d := v_0.AuxInt
|
d := v_0.AuxInt
|
||||||
if !(0 <= int32(c) && uint32(d) <= 31 && 1<<(32-uint32(d)) <= int32(c)) {
|
if !(0 <= int32(c) && uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpMIPSMOVWconst)
|
v.reset(OpMIPSMOVWconst)
|
||||||
|
|
|
@ -6005,7 +6005,7 @@ func rewriteValueMIPS64_OpMIPS64SGTUconst_0(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SGTUconst [c] (SRLVconst _ [d]))
|
// match: (SGTUconst [c] (SRLVconst _ [d]))
|
||||||
// cond: 0 < d && d <= 63 && 1<<uint64(64-d) <= uint64(c)
|
// cond: 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c)
|
||||||
// result: (MOVVconst [1])
|
// result: (MOVVconst [1])
|
||||||
for {
|
for {
|
||||||
c := v.AuxInt
|
c := v.AuxInt
|
||||||
|
@ -6014,7 +6014,7 @@ func rewriteValueMIPS64_OpMIPS64SGTUconst_0(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
d := v_0.AuxInt
|
d := v_0.AuxInt
|
||||||
if !(0 < d && d <= 63 && 1<<uint64(64-d) <= uint64(c)) {
|
if !(0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpMIPS64MOVVconst)
|
v.reset(OpMIPS64MOVVconst)
|
||||||
|
@ -6223,7 +6223,7 @@ func rewriteValueMIPS64_OpMIPS64SGTconst_10(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SGTconst [c] (SRLVconst _ [d]))
|
// match: (SGTconst [c] (SRLVconst _ [d]))
|
||||||
// cond: 0 <= c && 0 < d && d <= 63 && 1<<uint64(64-d) <= c
|
// cond: 0 <= c && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c)
|
||||||
// result: (MOVVconst [1])
|
// result: (MOVVconst [1])
|
||||||
for {
|
for {
|
||||||
c := v.AuxInt
|
c := v.AuxInt
|
||||||
|
@ -6232,7 +6232,7 @@ func rewriteValueMIPS64_OpMIPS64SGTconst_10(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
d := v_0.AuxInt
|
d := v_0.AuxInt
|
||||||
if !(0 <= c && 0 < d && d <= 63 && 1<<uint64(64-d) <= c) {
|
if !(0 <= c && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpMIPS64MOVVconst)
|
v.reset(OpMIPS64MOVVconst)
|
||||||
|
|
23
test/fixedbugs/issue29402.go
Normal file
23
test/fixedbugs/issue29402.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Issue 29402: wrong optimization of comparison of
|
||||||
|
// constant and shift on MIPS.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func F(s []int) bool {
|
||||||
|
half := len(s) / 2
|
||||||
|
return half >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
b := F([]int{1, 2, 3, 4})
|
||||||
|
if !b {
|
||||||
|
panic("FAIL")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue