From: Keith Randall Date: Wed, 9 Dec 2020 16:27:54 +0000 (-0800) Subject: cmd/compile: don't constant fold divide by zero X-Git-Tag: go1.16beta1~56 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=6c64b6db6802818dd9a4789cdd564f19b70b6b4c;p=gostls13.git 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 Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules index 6637c6cae4..11c36b5da3 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM.rules @@ -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]) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 9edc0c94b0..3f4d0c1c52 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -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) diff --git a/src/cmd/compile/internal/ssa/gen/MIPS.rules b/src/cmd/compile/internal/ssa/gen/MIPS.rules index 470cc66869..8ad2c90ac3 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS.rules +++ b/src/cmd/compile/internal/ssa/gen/MIPS.rules @@ -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]) diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64.rules b/src/cmd/compile/internal/ssa/gen/MIPS64.rules index 9af0f93333..088c9b1ac4 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS64.rules +++ b/src/cmd/compile/internal/ssa/gen/MIPS64.rules @@ -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]) diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go index 68495c558c..d9d439fa63 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM.go +++ b/src/cmd/compile/internal/ssa/rewriteARM.go @@ -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 diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 353696bf39..5d5e526add 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -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 diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS.go b/src/cmd/compile/internal/ssa/rewriteMIPS.go index bbc331014f..3fc5527955 100644 --- a/src/cmd/compile/internal/ssa/rewriteMIPS.go +++ b/src/cmd/compile/internal/ssa/rewriteMIPS.go @@ -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 diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS64.go b/src/cmd/compile/internal/ssa/rewriteMIPS64.go index 29e3a8a363..d78f6089af 100644 --- a/src/cmd/compile/internal/ssa/rewriteMIPS64.go +++ b/src/cmd/compile/internal/ssa/rewriteMIPS64.go @@ -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 diff --git a/test/fixedbugs/issue43099.go b/test/fixedbugs/issue43099.go new file mode 100644 index 0000000000..16f18e5f96 --- /dev/null +++ b/test/fixedbugs/issue43099.go @@ -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 +}