]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: improve generic rules for BCE based on AND operations.
authorGiovanni Bajo <rasky@develer.com>
Sun, 26 Feb 2017 01:54:32 +0000 (02:54 +0100)
committerKeith Randall <khr@golang.org>
Sat, 4 Mar 2017 16:13:07 +0000 (16:13 +0000)
Match more patterns generated by the compiler where the index for
a bound check is bounded through a AND operation, with different
register sizes.

These rules trigger a dozen of times in a bootstrap.

Change-Id: Ic9fff16f21d08580f19a366c3ee1a372e58357d1
Reviewed-on: https://go-review.googlesource.com/37442
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
test/checkbce.go

index c7d1743d5b38807c454515ff0e4e3dd853712caa..00103babe5153c8f95299bcf84440d777c294c52 100644 (file)
 (IsInBounds (ZeroExt16to32 _) (Const32 [c])) && (1 << 16) <= c -> (ConstBool [1])
 (IsInBounds (ZeroExt16to64 _) (Const64 [c])) && (1 << 16) <= c -> (ConstBool [1])
 (IsInBounds x x) -> (ConstBool [0])
-(IsInBounds (And32 (Const32 [c]) _) (Const32 [d])) && 0 <= c && c < d -> (ConstBool [1])
-(IsInBounds (And64 (Const64 [c]) _) (Const64 [d])) && 0 <= c && c < d -> (ConstBool [1])
+(IsInBounds                (And8  (Const8  [c]) _)  (Const8  [d])) && 0 <= c && c < d -> (ConstBool [1])
+(IsInBounds (ZeroExt8to16  (And8  (Const8  [c]) _)) (Const16 [d])) && 0 <= c && c < d -> (ConstBool [1])
+(IsInBounds (ZeroExt8to32  (And8  (Const8  [c]) _)) (Const32 [d])) && 0 <= c && c < d -> (ConstBool [1])
+(IsInBounds (ZeroExt8to64  (And8  (Const8  [c]) _)) (Const64 [d])) && 0 <= c && c < d -> (ConstBool [1])
+(IsInBounds                (And16 (Const16 [c]) _)  (Const16 [d])) && 0 <= c && c < d -> (ConstBool [1])
+(IsInBounds (ZeroExt16to32 (And16 (Const16 [c]) _)) (Const32 [d])) && 0 <= c && c < d -> (ConstBool [1])
+(IsInBounds (ZeroExt16to64 (And16 (Const16 [c]) _)) (Const64 [d])) && 0 <= c && c < d -> (ConstBool [1])
+(IsInBounds                (And32 (Const32 [c]) _)  (Const32 [d])) && 0 <= c && c < d -> (ConstBool [1])
+(IsInBounds (ZeroExt32to64 (And32 (Const32 [c]) _)) (Const64 [d])) && 0 <= c && c < d -> (ConstBool [1])
+(IsInBounds                (And64 (Const64 [c]) _)  (Const64 [d])) && 0 <= c && c < d -> (ConstBool [1])
 (IsInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(0 <= c && c < d)])
 (IsInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(0 <= c && c < d)])
 // (Mod64u x y) is always between 0 (inclusive) and y (exclusive).
index c14a3e000c1733e33367ee351ff35cc85c4512d7..5c09ea03f4a65e093e4be11260a01eb479f82f0f 100644 (file)
@@ -5814,7 +5814,202 @@ func rewriteValuegeneric_OpIsInBounds(v *Value, config *Config) bool {
                v.AuxInt = 0
                return true
        }
-       // match: (IsInBounds (And32 (Const32 [c]) _) (Const32 [d]))
+       // match: (IsInBounds                (And8  (Const8  [c]) _)  (Const8  [d]))
+       // cond: 0 <= c && c < d
+       // result: (ConstBool [1])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpAnd8 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpConst8 {
+                       break
+               }
+               c := v_0_0.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst8 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 <= c && c < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (ZeroExt8to16  (And8  (Const8  [c]) _)) (Const16 [d]))
+       // cond: 0 <= c && c < d
+       // result: (ConstBool [1])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt8to16 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAnd8 {
+                       break
+               }
+               v_0_0_0 := v_0_0.Args[0]
+               if v_0_0_0.Op != OpConst8 {
+                       break
+               }
+               c := v_0_0_0.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst16 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 <= c && c < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (ZeroExt8to32  (And8  (Const8  [c]) _)) (Const32 [d]))
+       // cond: 0 <= c && c < d
+       // result: (ConstBool [1])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt8to32 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAnd8 {
+                       break
+               }
+               v_0_0_0 := v_0_0.Args[0]
+               if v_0_0_0.Op != OpConst8 {
+                       break
+               }
+               c := v_0_0_0.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst32 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 <= c && c < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (ZeroExt8to64  (And8  (Const8  [c]) _)) (Const64 [d]))
+       // cond: 0 <= c && c < d
+       // result: (ConstBool [1])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt8to64 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAnd8 {
+                       break
+               }
+               v_0_0_0 := v_0_0.Args[0]
+               if v_0_0_0.Op != OpConst8 {
+                       break
+               }
+               c := v_0_0_0.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst64 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 <= c && c < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds                (And16 (Const16 [c]) _)  (Const16 [d]))
+       // cond: 0 <= c && c < d
+       // result: (ConstBool [1])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpAnd16 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpConst16 {
+                       break
+               }
+               c := v_0_0.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst16 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 <= c && c < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (ZeroExt16to32 (And16 (Const16 [c]) _)) (Const32 [d]))
+       // cond: 0 <= c && c < d
+       // result: (ConstBool [1])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt16to32 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAnd16 {
+                       break
+               }
+               v_0_0_0 := v_0_0.Args[0]
+               if v_0_0_0.Op != OpConst16 {
+                       break
+               }
+               c := v_0_0_0.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst32 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 <= c && c < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (ZeroExt16to64 (And16 (Const16 [c]) _)) (Const64 [d]))
+       // cond: 0 <= c && c < d
+       // result: (ConstBool [1])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt16to64 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAnd16 {
+                       break
+               }
+               v_0_0_0 := v_0_0.Args[0]
+               if v_0_0_0.Op != OpConst16 {
+                       break
+               }
+               c := v_0_0_0.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst64 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 <= c && c < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds                (And32 (Const32 [c]) _)  (Const32 [d]))
        // cond: 0 <= c && c < d
        // result: (ConstBool [1])
        for {
@@ -5839,7 +6034,36 @@ func rewriteValuegeneric_OpIsInBounds(v *Value, config *Config) bool {
                v.AuxInt = 1
                return true
        }
-       // match: (IsInBounds (And64 (Const64 [c]) _) (Const64 [d]))
+       // match: (IsInBounds (ZeroExt32to64 (And32 (Const32 [c]) _)) (Const64 [d]))
+       // cond: 0 <= c && c < d
+       // result: (ConstBool [1])
+       for {
+               v_0 := v.Args[0]
+               if v_0.Op != OpZeroExt32to64 {
+                       break
+               }
+               v_0_0 := v_0.Args[0]
+               if v_0_0.Op != OpAnd32 {
+                       break
+               }
+               v_0_0_0 := v_0_0.Args[0]
+               if v_0_0_0.Op != OpConst32 {
+                       break
+               }
+               c := v_0_0_0.AuxInt
+               v_1 := v.Args[1]
+               if v_1.Op != OpConst64 {
+                       break
+               }
+               d := v_1.AuxInt
+               if !(0 <= c && c < d) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds                (And64 (Const64 [c]) _)  (Const64 [d]))
        // cond: 0 <= c && c < d
        // result: (ConstBool [1])
        for {
index 4f9574d4209d2af45ba787f419781f89200eb5fc..a4b0fe0d2a486e07d0d53a35aac7e84f7c1001a2 100644 (file)
@@ -13,10 +13,14 @@ func f0(a []int) {
 }
 
 func f1(a [256]int, i int) {
-       useInt(a[i])     // ERROR "Found IsInBounds$"
-       useInt(a[i%256]) // ERROR "Found IsInBounds$"
-       useInt(a[i&255])
-       useInt(a[i&17])
+       var j int
+       useInt(a[i]) // ERROR "Found IsInBounds$"
+       j = i % 256
+       useInt(a[j]) // ERROR "Found IsInBounds$"
+       j = i & 255
+       useInt(a[j])
+       j = i & 17
+       useInt(a[j])
 
        if 4 <= i && i < len(a) {
                useInt(a[i])
@@ -29,9 +33,36 @@ func f1(a [256]int, i int) {
 
 func f2(a [256]int, i uint) {
        useInt(a[i]) // ERROR "Found IsInBounds$"
-       useInt(a[i%256])
-       useInt(a[i&255])
-       useInt(a[i&17])
+       j := i % 256
+       useInt(a[j])
+       j = i & 255
+       useInt(a[j])
+       j = i & 17
+       useInt(a[j])
+}
+
+func f2a(a [35]int, i uint8) {
+       useInt(a[i]) // ERROR "Found IsInBounds$"
+       j := i & 34
+       useInt(a[j])
+       j = i & 17
+       useInt(a[j])
+}
+
+func f2b(a [35]int, i uint16) {
+       useInt(a[i]) // ERROR "Found IsInBounds$"
+       j := i & 34
+       useInt(a[j])
+       j = i & 17
+       useInt(a[j])
+}
+
+func f2c(a [35]int, i uint32) {
+       useInt(a[i]) // ERROR "Found IsInBounds$"
+       j := i & 34
+       useInt(a[j])
+       j = i & 17
+       useInt(a[j])
 }
 
 func f3(a [256]int, i uint8) {