diff options
author | Alexandru Moșoi <mosoi@google.com> | 2016-04-01 15:09:19 +0200 |
---|---|---|
committer | Alexandru Moșoi <alexandru@mosoi.ro> | 2016-04-11 16:01:22 +0000 |
commit | 6c6089b3fdba9eb0cff863a03074dbac47c92f63 (patch) | |
tree | 8d4eacf7fc80504db1a2bf1468b3192060ce1dcd /src/cmd/compile/internal/ssa/loopbce.go | |
parent | 00681eec6aec03b8b2822c9220fba27c18923c01 (diff) | |
download | go-6c6089b3fdba9eb0cff863a03074dbac47c92f63.tar.gz go-6c6089b3fdba9eb0cff863a03074dbac47c92f63.zip |
cmd/compile: bce when max and limit are consts
Removes 49 more bound checks in make.bash. For example:
var a[100]int
for i := 0; i < 50; i++ {
use a[i+25]
}
Change-Id: I85e0130ee5d07f0ece9b17044bba1a2047414ce7
Reviewed-on: https://go-review.googlesource.com/21379
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Alexandru Moșoi <alexandru@mosoi.ro>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/ssa/loopbce.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/loopbce.go | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/loopbce.go b/src/cmd/compile/internal/ssa/loopbce.go index 17486ac49f..c937ead1b2 100644 --- a/src/cmd/compile/internal/ssa/loopbce.go +++ b/src/cmd/compile/internal/ssa/loopbce.go @@ -240,6 +240,37 @@ func removeBoundsChecks(f *Func, sdom sparseTree, m map[*Value]indVar) { } skip2: + // Simplify + // (IsInBounds (Add64 ind) (Const64 [c])) where 0 <= min <= ind < max <= (Const64 [c]) + // (IsSliceInBounds ind (Const64 [c])) where 0 <= min <= ind < max <= (Const64 [c]) + if v.Op == OpIsInBounds || v.Op == OpIsSliceInBounds { + ind, add := dropAdd64(v.Args[0]) + if ind.Op != OpPhi { + goto skip3 + } + + // ind + add >= 0 <-> min + add >= 0 <-> min >= -add + if iv, has := m[ind]; has && sdom.isAncestorEq(iv.entry, b) && isGreaterOrEqualThan(iv.min, -add) { + if !v.Args[1].isGenericIntConst() || !iv.max.isGenericIntConst() { + goto skip3 + } + + limit := v.Args[1].AuxInt + if v.Op == OpIsSliceInBounds { + // If limit++ overflows signed integer then 0 <= max && max <= limit will be false. + limit++ + } + + if max := iv.max.AuxInt + add; 0 <= max && max <= limit { // handle overflow + if f.pass.debug > 0 { + f.Config.Warnl(b.Line, "Found redundant (%s ind %d), ind < %d", v.Op, v.Args[1].AuxInt, iv.max.AuxInt+add) + } + goto simplify + } + } + } + skip3: + continue simplify: @@ -258,3 +289,13 @@ func dropAdd64(v *Value) (*Value, int64) { } return v, 0 } + +func isGreaterOrEqualThan(v *Value, c int64) bool { + if c == 0 { + return isNonNegative(v) + } + if v.isGenericIntConst() && v.AuxInt >= c { + return true + } + return false +} |