1
0
mirror of https://github.com/golang/go synced 2024-09-23 15:20:13 -06:00

cmd/compile: don't constant fold divide by zero

It just makes the compiler crash. Oops.

Fixes #43099

Change-Id: Id996c14799c1a5d0063ecae3b8770568161c2440
Reviewed-on: https://go-review.googlesource.com/c/go/+/276652
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Keith Randall 2020-12-09 08:27:54 -08:00
parent 89f465c2b5
commit 6c64b6db68
9 changed files with 124 additions and 18 deletions

View File

@ -760,8 +760,8 @@
(MUL (MOVWconst [c]) (MOVWconst [d])) => (MOVWconst [c*d])
(MULA (MOVWconst [c]) (MOVWconst [d]) a) => (ADDconst [c*d] a)
(MULS (MOVWconst [c]) (MOVWconst [d]) a) => (SUBconst [c*d] a)
(Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)/uint32(d))])
(Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)%uint32(d))])
(Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)/uint32(d))])
(Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)%uint32(d))])
(ANDconst [c] (MOVWconst [d])) => (MOVWconst [c&d])
(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
(ORconst [c] (MOVWconst [d])) => (MOVWconst [c|d])

View File

@ -1372,14 +1372,14 @@
(MADDW a (MOVDconst [c]) (MOVDconst [d])) => (ADDconst [int64(int32(c)*int32(d))] a)
(MSUB a (MOVDconst [c]) (MOVDconst [d])) => (SUBconst [c*d] a)
(MSUBW a (MOVDconst [c]) (MOVDconst [d])) => (SUBconst [int64(int32(c)*int32(d))] a)
(DIV (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c/d])
(UDIV (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint64(c)/uint64(d))])
(DIVW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(int32(c)/int32(d))])
(UDIVW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint32(c)/uint32(d))])
(MOD (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [c%d])
(UMOD (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint64(c)%uint64(d))])
(MODW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(int32(c)%int32(d))])
(UMODW (MOVDconst [c]) (MOVDconst [d])) => (MOVDconst [int64(uint32(c)%uint32(d))])
(DIV (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [c/d])
(UDIV (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint64(c)/uint64(d))])
(DIVW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(int32(c)/int32(d))])
(UDIVW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint32(c)/uint32(d))])
(MOD (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [c%d])
(UMOD (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint64(c)%uint64(d))])
(MODW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(int32(c)%int32(d))])
(UMODW (MOVDconst [c]) (MOVDconst [d])) && d != 0 => (MOVDconst [int64(uint32(c)%uint32(d))])
(ANDconst [c] (MOVDconst [d])) => (MOVDconst [c&d])
(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
(ANDconst [c] (MOVWUreg x)) => (ANDconst [c&(1<<32-1)] x)

View File

@ -626,10 +626,10 @@
(MUL (MOVWconst [c]) (MOVWconst [d])) => (MOVWconst [c*d])
(Select1 (MULTU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)*uint32(d))])
(Select0 (MULTU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32((int64(uint32(c))*int64(uint32(d)))>>32)])
(Select1 (DIV (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [c/d])
(Select1 (DIVU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)/uint32(d))])
(Select0 (DIV (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [c%d])
(Select0 (DIVU (MOVWconst [c]) (MOVWconst [d]))) => (MOVWconst [int32(uint32(c)%uint32(d))])
(Select1 (DIV (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [c/d])
(Select1 (DIVU (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)/uint32(d))])
(Select0 (DIV (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [c%d])
(Select0 (DIVU (MOVWconst [c]) (MOVWconst [d]))) && d != 0 => (MOVWconst [int32(uint32(c)%uint32(d))])
(ANDconst [c] (MOVWconst [d])) => (MOVWconst [c&d])
(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
(ORconst [c] (MOVWconst [d])) => (MOVWconst [c|d])

View File

@ -617,10 +617,10 @@
(SRLVconst [c] (MOVVconst [d])) => (MOVVconst [int64(uint64(d)>>uint64(c))])
(SRAVconst [c] (MOVVconst [d])) => (MOVVconst [d>>uint64(c)])
(Select1 (MULVU (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [c*d])
(Select1 (DIVV (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [c/d])
(Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [int64(uint64(c)/uint64(d))])
(Select0 (DIVV (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [c%d]) // mod
(Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [int64(uint64(c)%uint64(d))]) // mod
(Select1 (DIVV (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c/d])
(Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [int64(uint64(c)/uint64(d))])
(Select0 (DIVV (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c%d]) // mod
(Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [int64(uint64(c)%uint64(d))]) // mod
(ANDconst [c] (MOVVconst [d])) => (MOVVconst [c&d])
(ANDconst [c] (ANDconst [d] x)) => (ANDconst [c&d] x)
(ORconst [c] (MOVVconst [d])) => (MOVVconst [c|d])

View File

@ -15599,6 +15599,7 @@ func rewriteValueARM_OpSelect0(v *Value) bool {
return true
}
// match: (Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d])))
// cond: d != 0
// result: (MOVWconst [int32(uint32(c)/uint32(d))])
for {
if v_0.Op != OpARMCALLudiv {
@ -15615,6 +15616,9 @@ func rewriteValueARM_OpSelect0(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpARMMOVWconst)
v.AuxInt = int32ToAuxInt(int32(uint32(c) / uint32(d)))
return true
@ -15661,6 +15665,7 @@ func rewriteValueARM_OpSelect1(v *Value) bool {
return true
}
// match: (Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d])))
// cond: d != 0
// result: (MOVWconst [int32(uint32(c)%uint32(d))])
for {
if v_0.Op != OpARMCALLudiv {
@ -15677,6 +15682,9 @@ func rewriteValueARM_OpSelect1(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpARMMOVWconst)
v.AuxInt = int32ToAuxInt(int32(uint32(c) % uint32(d)))
return true

View File

@ -3396,6 +3396,7 @@ func rewriteValueARM64_OpARM64DIV(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (DIV (MOVDconst [c]) (MOVDconst [d]))
// cond: d != 0
// result: (MOVDconst [c/d])
for {
if v_0.Op != OpARM64MOVDconst {
@ -3406,6 +3407,9 @@ func rewriteValueARM64_OpARM64DIV(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(c / d)
return true
@ -3416,6 +3420,7 @@ func rewriteValueARM64_OpARM64DIVW(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (DIVW (MOVDconst [c]) (MOVDconst [d]))
// cond: d != 0
// result: (MOVDconst [int64(int32(c)/int32(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@ -3426,6 +3431,9 @@ func rewriteValueARM64_OpARM64DIVW(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(int32(c) / int32(d)))
return true
@ -6165,6 +6173,7 @@ func rewriteValueARM64_OpARM64MOD(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (MOD (MOVDconst [c]) (MOVDconst [d]))
// cond: d != 0
// result: (MOVDconst [c%d])
for {
if v_0.Op != OpARM64MOVDconst {
@ -6175,6 +6184,9 @@ func rewriteValueARM64_OpARM64MOD(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(c % d)
return true
@ -6185,6 +6197,7 @@ func rewriteValueARM64_OpARM64MODW(v *Value) bool {
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (MODW (MOVDconst [c]) (MOVDconst [d]))
// cond: d != 0
// result: (MOVDconst [int64(int32(c)%int32(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@ -6195,6 +6208,9 @@ func rewriteValueARM64_OpARM64MODW(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(int32(c) % int32(d)))
return true
@ -20423,6 +20439,7 @@ func rewriteValueARM64_OpARM64UDIV(v *Value) bool {
return true
}
// match: (UDIV (MOVDconst [c]) (MOVDconst [d]))
// cond: d != 0
// result: (MOVDconst [int64(uint64(c)/uint64(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@ -20433,6 +20450,9 @@ func rewriteValueARM64_OpARM64UDIV(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d)))
return true
@ -20475,6 +20495,7 @@ func rewriteValueARM64_OpARM64UDIVW(v *Value) bool {
return true
}
// match: (UDIVW (MOVDconst [c]) (MOVDconst [d]))
// cond: d != 0
// result: (MOVDconst [int64(uint32(c)/uint32(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@ -20485,6 +20506,9 @@ func rewriteValueARM64_OpARM64UDIVW(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(uint32(c) / uint32(d)))
return true
@ -20539,6 +20563,7 @@ func rewriteValueARM64_OpARM64UMOD(v *Value) bool {
return true
}
// match: (UMOD (MOVDconst [c]) (MOVDconst [d]))
// cond: d != 0
// result: (MOVDconst [int64(uint64(c)%uint64(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@ -20549,6 +20574,9 @@ func rewriteValueARM64_OpARM64UMOD(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d)))
return true
@ -20608,6 +20636,7 @@ func rewriteValueARM64_OpARM64UMODW(v *Value) bool {
return true
}
// match: (UMODW (MOVDconst [c]) (MOVDconst [d]))
// cond: d != 0
// result: (MOVDconst [int64(uint32(c)%uint32(d))])
for {
if v_0.Op != OpARM64MOVDconst {
@ -20618,6 +20647,9 @@ func rewriteValueARM64_OpARM64UMODW(v *Value) bool {
break
}
d := auxIntToInt64(v_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpARM64MOVDconst)
v.AuxInt = int64ToAuxInt(int64(uint32(c) % uint32(d)))
return true

View File

@ -6421,6 +6421,7 @@ func rewriteValueMIPS_OpSelect0(v *Value) bool {
break
}
// match: (Select0 (DIV (MOVWconst [c]) (MOVWconst [d])))
// cond: d != 0
// result: (MOVWconst [c%d])
for {
if v_0.Op != OpMIPSDIV {
@ -6437,11 +6438,15 @@ func rewriteValueMIPS_OpSelect0(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpMIPSMOVWconst)
v.AuxInt = int32ToAuxInt(c % d)
return true
}
// match: (Select0 (DIVU (MOVWconst [c]) (MOVWconst [d])))
// cond: d != 0
// result: (MOVWconst [int32(uint32(c)%uint32(d))])
for {
if v_0.Op != OpMIPSDIVU {
@ -6458,6 +6463,9 @@ func rewriteValueMIPS_OpSelect0(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpMIPSMOVWconst)
v.AuxInt = int32ToAuxInt(int32(uint32(c) % uint32(d)))
return true
@ -6609,6 +6617,7 @@ func rewriteValueMIPS_OpSelect1(v *Value) bool {
break
}
// match: (Select1 (DIV (MOVWconst [c]) (MOVWconst [d])))
// cond: d != 0
// result: (MOVWconst [c/d])
for {
if v_0.Op != OpMIPSDIV {
@ -6625,11 +6634,15 @@ func rewriteValueMIPS_OpSelect1(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpMIPSMOVWconst)
v.AuxInt = int32ToAuxInt(c / d)
return true
}
// match: (Select1 (DIVU (MOVWconst [c]) (MOVWconst [d])))
// cond: d != 0
// result: (MOVWconst [int32(uint32(c)/uint32(d))])
for {
if v_0.Op != OpMIPSDIVU {
@ -6646,6 +6659,9 @@ func rewriteValueMIPS_OpSelect1(v *Value) bool {
break
}
d := auxIntToInt32(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpMIPSMOVWconst)
v.AuxInt = int32ToAuxInt(int32(uint32(c) / uint32(d)))
return true

View File

@ -6887,6 +6887,7 @@ func rewriteValueMIPS64_OpSelect0(v *Value) bool {
return true
}
// match: (Select0 (DIVV (MOVVconst [c]) (MOVVconst [d])))
// cond: d != 0
// result: (MOVVconst [c%d])
for {
if v_0.Op != OpMIPS64DIVV {
@ -6903,11 +6904,15 @@ func rewriteValueMIPS64_OpSelect0(v *Value) bool {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpMIPS64MOVVconst)
v.AuxInt = int64ToAuxInt(c % d)
return true
}
// match: (Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d])))
// cond: d != 0
// result: (MOVVconst [int64(uint64(c)%uint64(d))])
for {
if v_0.Op != OpMIPS64DIVVU {
@ -6924,6 +6929,9 @@ func rewriteValueMIPS64_OpSelect0(v *Value) bool {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpMIPS64MOVVconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) % uint64(d)))
return true
@ -7099,6 +7107,7 @@ func rewriteValueMIPS64_OpSelect1(v *Value) bool {
break
}
// match: (Select1 (DIVV (MOVVconst [c]) (MOVVconst [d])))
// cond: d != 0
// result: (MOVVconst [c/d])
for {
if v_0.Op != OpMIPS64DIVV {
@ -7115,11 +7124,15 @@ func rewriteValueMIPS64_OpSelect1(v *Value) bool {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpMIPS64MOVVconst)
v.AuxInt = int64ToAuxInt(c / d)
return true
}
// match: (Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d])))
// cond: d != 0
// result: (MOVVconst [int64(uint64(c)/uint64(d))])
for {
if v_0.Op != OpMIPS64DIVVU {
@ -7136,6 +7149,9 @@ func rewriteValueMIPS64_OpSelect1(v *Value) bool {
break
}
d := auxIntToInt64(v_0_1.AuxInt)
if !(d != 0) {
break
}
v.reset(OpMIPS64MOVVconst)
v.AuxInt = int64ToAuxInt(int64(uint64(c) / uint64(d)))
return true

View File

@ -0,0 +1,34 @@
// compile
// Copyright 2020 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.
// Check to make sure we don't try to constant fold a divide by zero.
// This is a tricky test, as we need a value that's not recognized as 0
// until lowering (otherwise it gets handled in a different path).
package p
func f() {
var i int
var s string
for i > 0 {
_ = s[0]
i++
}
var c chan int
c <- 1 % i
}
func f32() uint32 {
s := "\x00\x00\x00\x00"
c := uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 | uint32(s[3])<<24
return 1 / c
}
func f64() uint64 {
s := "\x00\x00\x00\x00\x00\x00\x00\x00"
c := uint64(s[0]) | uint64(s[1])<<8 | uint64(s[2])<<16 | uint64(s[3])<<24 | uint64(s[4])<<32 | uint64(s[5])<<40 | uint64(s[6])<<48 | uint64(s[7])<<56
return 1 / c
}