]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: use right shifts to eliminate bounds checks
authorJosh Bleecher Snyder <josharian@gmail.com>
Fri, 19 May 2017 22:10:10 +0000 (15:10 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Wed, 9 Aug 2017 00:21:25 +0000 (00:21 +0000)
These rules trigger a few times during make.bash.
When we eliminate boundedness checks from walk.go
we'll rely on them more heavily.

Updates #19692

Change-Id: I268c36ae2f1401c68dd685b15f2d30f5d6971176
Reviewed-on: https://go-review.googlesource.com/43775
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go

index b8d7381420204796aaf49ce982be452bfc1aafe3..bb4a83738f5a5de28c2bab17615cfad4c57120f8 100644 (file)
 // (Mod64u x y) is always between 0 (inclusive) and y (exclusive).
 (IsInBounds (Mod32u _ y) y) -> (ConstBool [1])
 (IsInBounds (Mod64u _ y) y) -> (ConstBool [1])
+// Right shifting a unsigned number limits its value.
+(IsInBounds (ZeroExt8to64  (Rsh8Ux64  _ (Const64 [c]))) (Const64 [d])) && 0 < c && c <  8 && 1<<uint( 8-c)-1 < d -> (ConstBool [1])
+(IsInBounds (ZeroExt8to32  (Rsh8Ux64  _ (Const64 [c]))) (Const32 [d])) && 0 < c && c <  8 && 1<<uint( 8-c)-1 < d -> (ConstBool [1])
+(IsInBounds (ZeroExt8to16  (Rsh8Ux64  _ (Const64 [c]))) (Const16 [d])) && 0 < c && c <  8 && 1<<uint( 8-c)-1 < d -> (ConstBool [1])
+(IsInBounds                (Rsh8Ux64  _ (Const64 [c]))  (Const64 [d])) && 0 < c && c <  8 && 1<<uint( 8-c)-1 < d -> (ConstBool [1])
+(IsInBounds (ZeroExt16to64 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d])) && 0 < c && c < 16 && 1<<uint(16-c)-1 < d -> (ConstBool [1])
+(IsInBounds (ZeroExt16to32 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d])) && 0 < c && c < 16 && 1<<uint(16-c)-1 < d -> (ConstBool [1])
+(IsInBounds                (Rsh16Ux64 _ (Const64 [c]))  (Const64 [d])) && 0 < c && c < 16 && 1<<uint(16-c)-1 < d -> (ConstBool [1])
+(IsInBounds (ZeroExt32to64 (Rsh32Ux64 _ (Const64 [c]))) (Const64 [d])) && 0 < c && c < 32 && 1<<uint(32-c)-1 < d -> (ConstBool [1])
+(IsInBounds                (Rsh32Ux64 _ (Const64 [c]))  (Const64 [d])) && 0 < c && c < 32 && 1<<uint(32-c)-1 < d -> (ConstBool [1])
+(IsInBounds                (Rsh64Ux64 _ (Const64 [c]))  (Const64 [d])) && 0 < c && c < 64 && 1<<uint(64-c)-1 < d -> (ConstBool [1])
 
 (IsSliceInBounds x x) -> (ConstBool [1])
 (IsSliceInBounds (And32 (Const32 [c]) _) (Const32 [d])) && 0 <= c && c <= d -> (ConstBool [1])
index 95b2c62f0771ec0c08ad105550c78f82e7e75ffe..89ef75e1361f7404c5f74d8847a61b328080858c 100644 (file)
@@ -134,7 +134,7 @@ func rewriteValuegeneric(v *Value) bool {
        case OpInterCall:
                return rewriteValuegeneric_OpInterCall_0(v)
        case OpIsInBounds:
-               return rewriteValuegeneric_OpIsInBounds_0(v) || rewriteValuegeneric_OpIsInBounds_10(v) || rewriteValuegeneric_OpIsInBounds_20(v)
+               return rewriteValuegeneric_OpIsInBounds_0(v) || rewriteValuegeneric_OpIsInBounds_10(v) || rewriteValuegeneric_OpIsInBounds_20(v) || rewriteValuegeneric_OpIsInBounds_30(v)
        case OpIsNonNil:
                return rewriteValuegeneric_OpIsNonNil_0(v)
        case OpIsSliceInBounds:
@@ -9754,6 +9754,303 @@ func rewriteValuegeneric_OpIsInBounds_20(v *Value) bool {
                v.AuxInt = 1
                return true
        }
+       // match: (IsInBounds (ZeroExt8to64 (Rsh8Ux64 _ (Const64 [c]))) (Const64 [d]))
+       // cond: 0 < c && c <  8 && 1<<uint( 8-c)-1 < d
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt8to64 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpRsh8Ux64 {
+                       break
+               }
+               _ = v_0_0.Args[1]
+               v_0_0_1 := v_0_0.Args[1]
+               if v_0_0_1.Op != OpConst64 {
+                       break
+               }
+               c := v_0_0_1.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst64 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       return false
+}
+func rewriteValuegeneric_OpIsInBounds_30(v *Value) bool {
+       // match: (IsInBounds (ZeroExt8to32 (Rsh8Ux64 _ (Const64 [c]))) (Const32 [d]))
+       // cond: 0 < c && c <  8 && 1<<uint( 8-c)-1 < d
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt8to32 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpRsh8Ux64 {
+                       break
+               }
+               _ = v_0_0.Args[1]
+               v_0_0_1 := v_0_0.Args[1]
+               if v_0_0_1.Op != OpConst64 {
+                       break
+               }
+               c := v_0_0_1.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst32 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (ZeroExt8to16 (Rsh8Ux64 _ (Const64 [c]))) (Const16 [d]))
+       // cond: 0 < c && c <  8 && 1<<uint( 8-c)-1 < d
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt8to16 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpRsh8Ux64 {
+                       break
+               }
+               _ = v_0_0.Args[1]
+               v_0_0_1 := v_0_0.Args[1]
+               if v_0_0_1.Op != OpConst64 {
+                       break
+               }
+               c := v_0_0_1.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst16 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (Rsh8Ux64 _ (Const64 [c])) (Const64 [d]))
+       // cond: 0 < c && c <  8 && 1<<uint( 8-c)-1 < d
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpRsh8Ux64 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_1 := v_0.Args[1]
+               if v_0_1.Op != OpConst64 {
+                       break
+               }
+               c := v_0_1.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst64 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 < c && c < 8 && 1<<uint(8-c)-1 < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (ZeroExt16to64 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d]))
+       // cond: 0 < c && c < 16 && 1<<uint(16-c)-1 < d
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt16to64 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpRsh16Ux64 {
+                       break
+               }
+               _ = v_0_0.Args[1]
+               v_0_0_1 := v_0_0.Args[1]
+               if v_0_0_1.Op != OpConst64 {
+                       break
+               }
+               c := v_0_0_1.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst64 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 < c && c < 16 && 1<<uint(16-c)-1 < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (ZeroExt16to32 (Rsh16Ux64 _ (Const64 [c]))) (Const64 [d]))
+       // cond: 0 < c && c < 16 && 1<<uint(16-c)-1 < d
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt16to32 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpRsh16Ux64 {
+                       break
+               }
+               _ = v_0_0.Args[1]
+               v_0_0_1 := v_0_0.Args[1]
+               if v_0_0_1.Op != OpConst64 {
+                       break
+               }
+               c := v_0_0_1.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst64 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 < c && c < 16 && 1<<uint(16-c)-1 < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (Rsh16Ux64 _ (Const64 [c])) (Const64 [d]))
+       // cond: 0 < c && c < 16 && 1<<uint(16-c)-1 < d
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpRsh16Ux64 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_1 := v_0.Args[1]
+               if v_0_1.Op != OpConst64 {
+                       break
+               }
+               c := v_0_1.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst64 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 < c && c < 16 && 1<<uint(16-c)-1 < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (ZeroExt32to64 (Rsh32Ux64 _ (Const64 [c]))) (Const64 [d]))
+       // cond: 0 < c && c < 32 && 1<<uint(32-c)-1 < d
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt32to64 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpRsh32Ux64 {
+                       break
+               }
+               _ = v_0_0.Args[1]
+               v_0_0_1 := v_0_0.Args[1]
+               if v_0_0_1.Op != OpConst64 {
+                       break
+               }
+               c := v_0_0_1.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst64 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 < c && c < 32 && 1<<uint(32-c)-1 < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (Rsh32Ux64 _ (Const64 [c])) (Const64 [d]))
+       // cond: 0 < c && c < 32 && 1<<uint(32-c)-1 < d
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpRsh32Ux64 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_1 := v_0.Args[1]
+               if v_0_1.Op != OpConst64 {
+                       break
+               }
+               c := v_0_1.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst64 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 < c && c < 32 && 1<<uint(32-c)-1 < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (Rsh64Ux64 _ (Const64 [c])) (Const64 [d]))
+       // cond: 0 < c && c < 64 && 1<<uint(64-c)-1 < d
+       // result: (ConstBool [1])
+       for {
+               _ = v.Args[1]
+               v_0 := v.Args[0]
+               if v_0.Op != OpRsh64Ux64 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_1 := v_0.Args[1]
+               if v_0_1.Op != OpConst64 {
+                       break
+               }
+               c := v_0_1.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst64 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 < c && c < 64 && 1<<uint(64-c)-1 < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
        return false
 }
 func rewriteValuegeneric_OpIsNonNil_0(v *Value) bool {