]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: don't constant fold divide by zero
authorKeith Randall <khr@golang.org>
Wed, 9 Dec 2020 16:27:54 +0000 (08:27 -0800)
committerKeith Randall <khr@golang.org>
Thu, 10 Dec 2020 03:18:00 +0000 (03:18 +0000)
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>
src/cmd/compile/internal/ssa/gen/ARM.rules
src/cmd/compile/internal/ssa/gen/ARM64.rules
src/cmd/compile/internal/ssa/gen/MIPS.rules
src/cmd/compile/internal/ssa/gen/MIPS64.rules
src/cmd/compile/internal/ssa/rewriteARM.go
src/cmd/compile/internal/ssa/rewriteARM64.go
src/cmd/compile/internal/ssa/rewriteMIPS.go
src/cmd/compile/internal/ssa/rewriteMIPS64.go
test/fixedbugs/issue43099.go [new file with mode: 0644]

index 6637c6cae4620151edd45fe977b153e9ea271e2f..11c36b5da3567ed6728cdfc191d5676e28e401e6 100644 (file)
 (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])
index 9edc0c94b00e7f8f717a9335ea9d6feb107f9a91..3f4d0c1c52769e33091e92312800b77bda669617 100644 (file)
 (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)
index 470cc668694fa46e670a07a1ad956ce38be8f239..8ad2c90ac33c59c6d9ff7e1a9fd8ca9a19babdf9 100644 (file)
 (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])
index 9af0f9333334c6b2ec5cb04cbc7b3b750907e7c5..088c9b1ac44c148ecd910e2d2b5e4aaf4e12efd5 100644 (file)
 (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])
index 68495c558c07d6875d677b2ad7a452b234f4c7a8..d9d439fa63ee1d5c93930552d1c7aefeef7a83df 100644 (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
index 353696bf39335ee0030e821fb6a63764affd7abb..5d5e526add31fbd8ca8fafd4f1e7861b750bfbab 100644 (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
index bbc331014fed77cb4d973f2c47a782603189ec91..3fc552795507c256582aec4deb41a53dabf80b26 100644 (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
index 29e3a8a3636661be734e1c5b70a85462b34e0221..d78f6089afff28f780226dbb8afe515d69d14363 100644 (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
diff --git a/test/fixedbugs/issue43099.go b/test/fixedbugs/issue43099.go
new file mode 100644 (file)
index 0000000..16f18e5
--- /dev/null
@@ -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
+}