src/cmd/compile/internal/ssa/loopbce.go | 36 +++++++++++++++++++++++++----------- test/loopbce.go | 28 ++++++++++++++++++++++++++++ diff --git a/src/cmd/compile/internal/ssa/loopbce.go b/src/cmd/compile/internal/ssa/loopbce.go index aa6cc48cacbbe7110488c34706dc045a2174be86..a63a314043fe89cded8725d4cc5b099c31d3f7e8 100644 --- a/src/cmd/compile/internal/ssa/loopbce.go +++ b/src/cmd/compile/internal/ssa/loopbce.go @@ -219,9 +219,11 @@ // Use stride to compute a better lower limit. if init.AuxInt > v { return false } + // TODO(1.27): investigate passing a smaller-magnitude overflow limit to addU + // for addWillOverflow. v = addU(init.AuxInt, diff(v, init.AuxInt)/uint64(step)*uint64(step)) } - if addWillOverflow(v, step) { + if addWillOverflow(v, step, maxSignedValue(ind.Type)) { return false } if inclusive && v != limit.AuxInt || !inclusive && v+1 != limit.AuxInt { @@ -250,7 +252,7 @@ } // ind < knn - k cannot overflow if step is at most k+1 return step <= k+1 && k != maxSignedValue(limit.Type) } else { // step < 0 - if limit.Op == OpConst64 { + if limit.isGenericIntConst() { // Figure out the actual smallest value. v := limit.AuxInt if !inclusive { @@ -264,9 +266,11 @@ // Use stride to compute a better lower limit. if init.AuxInt < v { return false } + // TODO(1.27): investigate passing a smaller-magnitude underflow limit to subU + // for subWillUnderflow. v = subU(init.AuxInt, diff(init.AuxInt, v)/uint64(-step)*uint64(-step)) } - if subWillUnderflow(v, -step) { + if subWillUnderflow(v, -step, minSignedValue(ind.Type)) { return false } if inclusive && v != limit.AuxInt || !inclusive && v-1 != limit.AuxInt { @@ -328,14 +332,22 @@ return iv } -// addWillOverflow reports whether x+y would result in a value more than maxint. -func addWillOverflow(x, y int64) bool { - return x+y < x +// subWillUnderflow checks if x - y underflows the min value. +// y must be positive. +func subWillUnderflow(x, y int64, min int64) bool { + if y < 0 { + base.Fatalf("expecting positive value") + } + return x < min+y } -// subWillUnderflow reports whether x-y would result in a value less than minint. -func subWillUnderflow(x, y int64) bool { - return x-y > x +// addWillOverflow checks if x + y overflows the max value. +// y must be positive. +func addWillOverflow(x, y int64, max int64) bool { + if y < 0 { + base.Fatalf("expecting positive value") + } + return x > max-y } // diff returns x-y as a uint64. Requires x>=y. @@ -356,7 +368,8 @@ x += 1<<63 - 1 x += 1 y -= 1 << 63 } - if addWillOverflow(x, int64(y)) { + // TODO(1.27): investigate passing a smaller-magnitude overflow limit in here. + if addWillOverflow(x, int64(y), maxSignedValue(types.Types[types.TINT64])) { base.Fatalf("addU overflowed %d + %d", x, y) } return x + int64(y) @@ -372,7 +385,8 @@ x -= 1<<63 - 1 x -= 1 y -= 1 << 63 } - if subWillUnderflow(x, int64(y)) { + // TODO(1.27): investigate passing a smaller-magnitude underflow limit in here. + if subWillUnderflow(x, int64(y), minSignedValue(types.Types[types.TINT64])) { base.Fatalf("subU underflowed %d - %d", x, y) } return x - int64(y) diff --git a/test/loopbce.go b/test/loopbce.go index aabd56c682b878de9b1edfd414a6c2b4b539ae7d..9b1b1cc4c83d897e0a1e2ae0eedefcd23c9dbec8 100644 --- a/test/loopbce.go +++ b/test/loopbce.go @@ -469,6 +469,34 @@ } return s } +// This loop should not be proved anything. +func smallIntUp(arr *[128]int) { + for i := int8(0); i <= int8(120); i += int8(10) { + arr[i] = int(i) + } +} + +// This loop should not be proved anything. +func smallIntDown(arr *[128]int) { + for i := int8(0); i >= int8(-120); i -= int8(10) { + arr[127+i] = int(i) + } +} + +// This loop should not be proved anything. +func smallUintUp(arr *[128]int) { + for i := uint8(0); i <= uint8(250); i += uint8(10) { + arr[i] = int(i) + } +} + +// This loop should not be proved anything. +func smallUintDown(arr *[128]int) { + for i := uint8(255); i >= uint8(0); i -= uint8(10) { + arr[127+i] = int(i) + } +} + //go:noinline func useString(a string) { }