diff options
| author | Giovanni Bajo <rasky@develer.com> | 2018-04-15 16:52:49 +0200 |
|---|---|---|
| committer | Giovanni Bajo <rasky@develer.com> | 2018-04-29 09:38:32 +0000 |
| commit | e0d37a33ab6260f5acc68dbb9a02c3135d19bcbb (patch) | |
| tree | 7b4b421739d0e12b6a4a964721dcd52560857168 /src/cmd/compile/internal/ssa/loopbce.go | |
| parent | 6d379add0fefcc17ed7b763078526800a3c1d705 (diff) | |
| download | go-e0d37a33ab6260f5acc68dbb9a02c3135d19bcbb.tar.xz | |
cmd/compile: teach prove to handle expressions like len(s)-delta
When a loop has bound len(s)-delta, findIndVar detected it and
returned len(s) as (conservative) upper bound. This little lie
allowed loopbce to drop bound checks.
It is obviously more generic to teach prove about relations like
x+d<w for non-constant "w"; we already handled the case for
constant "w", so we just want to learn that if d<0, then x+d<w
proves that x<w.
To be able to remove the code from findIndVar, we also need
to teach prove that len() and cap() are always non-negative.
This CL allows to prove 633 more checks in cmd+std. Most
of them are cases where the code was already testing before
accessing a slice but the compiler didn't know it. For instance,
take strings.HasSuffix:
func HasSuffix(s, suffix string) bool {
return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
}
When suffix is a literal string, the compiler now understands
that the explicit check is enough to not emit a slice check.
I also found a loopbce test that was incorrectly
written to detect an overflow but had a off-by-one (on the
conservative side), so it unexpectly passed with this CL; I
changed it to really trigger the overflow as intended.
Change-Id: Ib5abade337db46b8811425afebad4719b6e46c4a
Reviewed-on: https://go-review.googlesource.com/105635
Run-TryBot: Giovanni Bajo <rasky@develer.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd/compile/internal/ssa/loopbce.go')
| -rw-r--r-- | src/cmd/compile/internal/ssa/loopbce.go | 7 |
1 files changed, 0 insertions, 7 deletions
diff --git a/src/cmd/compile/internal/ssa/loopbce.go b/src/cmd/compile/internal/ssa/loopbce.go index d484d12a78..692e55e17a 100644 --- a/src/cmd/compile/internal/ssa/loopbce.go +++ b/src/cmd/compile/internal/ssa/loopbce.go @@ -150,13 +150,6 @@ nextb: continue } - // If max is c + SliceLen with c <= 0 then we drop c. - // Makes sure c + SliceLen doesn't overflow when SliceLen == 0. - // TODO: save c as an offset from max. - if w, c := dropAdd64(max); (w.Op == OpStringLen || w.Op == OpSliceLen) && 0 >= c && -c >= 0 { - max = w - } - // We can only guarantee that the loops runs within limits of induction variable // if the increment is ±1 or when the limits are constants. if inc.AuxInt != 1 && inc.AuxInt != -1 { |
