]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: constant fold more of IsInBounds and IsSliceInBounds
authorAlexandru Moșoi <mosoi@google.com>
Wed, 9 Mar 2016 10:00:58 +0000 (11:00 +0100)
committerAlexandru Moșoi <alexandru@mosoi.ro>
Wed, 9 Mar 2016 18:05:28 +0000 (18:05 +0000)
Fixes #14721

Change-Id: Id1d5a819e5c242b91a37c4e464ed3f00c691aff5
Reviewed-on: https://go-review.googlesource.com/20482
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Alexandru Moșoi <alexandru@mosoi.ro>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go

index 8bdb6c04367311192ee3bee6bfa93af23973a951..d99ea5b66e71bc489e98d37a6b14d3c707160781 100644 (file)
 (Rsh8x64   (Const8  [0]) _) -> (Const8  [0])
 (Rsh8Ux64  (Const8  [0]) _) -> (Const8  [0])
 
+(IsInBounds (And32 (Const32 [c]) _) (Const32 [d])) && inBounds32(c, d) -> (ConstBool [1])
+(IsInBounds (And64 (Const64 [c]) _) (Const64 [d])) && inBounds64(c, d) -> (ConstBool [1])
 (IsInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(inBounds32(c,d))])
 (IsInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(inBounds64(c,d))])
+(IsSliceInBounds (And32 (Const32 [c]) _) (Const32 [d])) && sliceInBounds32(c, d) -> (ConstBool [1])
+(IsSliceInBounds (And64 (Const64 [c]) _) (Const64 [d])) && sliceInBounds64(c, d) -> (ConstBool [1])
 (IsSliceInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(sliceInBounds32(c,d))])
 (IsSliceInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(sliceInBounds64(c,d))])
 
 //(Mod64 n (Const64 [1])) -> (Const64 [0])
 //(Mod64u n (Const64 [1])) -> (Const64 [0])
 
-// Unsigned divide by power of 2.  Currently handled by frontend.
-//(Div64u <t> n (Const64 [c])) && isPowerOfTwo(c) -> (Rsh64Ux64 n (Const64 <t> [log2(c)]))
-//(Mod64u <t> n (Const64 [c])) && isPowerOfTwo(c) -> (And64 n (Const64 <t> [c-1]))
+// Unsigned divide by power of 2.
+(Div64u <t> n (Const64 [c])) && isPowerOfTwo(c) -> (Rsh64Ux64 n (Const64 <t> [log2(c)]))
+(Mod64u <t> n (Const64 [c])) && isPowerOfTwo(c) -> (And64 n (Const64 <t> [c-1]))
 
 // Signed divide by power of 2.  Currently handled by frontend.
 // n / c = n >> log(c)       if n >= 0
index bad4a90a4ad376df1c1858b32ab4b80d37b40772..95a2caeb1e221eab5edefa9b2e9b245bb2f3a931 100644 (file)
@@ -1577,6 +1577,26 @@ func rewriteValuegeneric_OpDiv64(v *Value, config *Config) bool {
 func rewriteValuegeneric_OpDiv64u(v *Value, config *Config) bool {
        b := v.Block
        _ = b
+       // match: (Div64u <t> n (Const64 [c]))
+       // cond: isPowerOfTwo(c)
+       // result: (Rsh64Ux64 n (Const64 <t> [log2(c)]))
+       for {
+               t := v.Type
+               n := v.Args[0]
+               if v.Args[1].Op != OpConst64 {
+                       break
+               }
+               c := v.Args[1].AuxInt
+               if !(isPowerOfTwo(c)) {
+                       break
+               }
+               v.reset(OpRsh64Ux64)
+               v.AddArg(n)
+               v0 := b.NewValue0(v.Line, OpConst64, t)
+               v0.AuxInt = log2(c)
+               v.AddArg(v0)
+               return true
+       }
        // match: (Div64u <t> x (Const64 [c]))
        // cond: umagic64ok(c) && !umagic64a(c)
        // result: (Rsh64Ux64     (Hmul64u <t>       (Const64 <t> [umagic64m(c)])       x)     (Const64 <t> [umagic64s(c)]))
@@ -2467,6 +2487,50 @@ func rewriteValuegeneric_OpITab(v *Value, config *Config) bool {
 func rewriteValuegeneric_OpIsInBounds(v *Value, config *Config) bool {
        b := v.Block
        _ = b
+       // match: (IsInBounds (And32 (Const32 [c]) _) (Const32 [d]))
+       // cond: inBounds32(c, d)
+       // result: (ConstBool [1])
+       for {
+               if v.Args[0].Op != OpAnd32 {
+                       break
+               }
+               if v.Args[0].Args[0].Op != OpConst32 {
+                       break
+               }
+               c := v.Args[0].Args[0].AuxInt
+               if v.Args[1].Op != OpConst32 {
+                       break
+               }
+               d := v.Args[1].AuxInt
+               if !(inBounds32(c, d)) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsInBounds (And64 (Const64 [c]) _) (Const64 [d]))
+       // cond: inBounds64(c, d)
+       // result: (ConstBool [1])
+       for {
+               if v.Args[0].Op != OpAnd64 {
+                       break
+               }
+               if v.Args[0].Args[0].Op != OpConst64 {
+                       break
+               }
+               c := v.Args[0].Args[0].AuxInt
+               if v.Args[1].Op != OpConst64 {
+                       break
+               }
+               d := v.Args[1].AuxInt
+               if !(inBounds64(c, d)) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
        // match: (IsInBounds (Const32 [c]) (Const32 [d]))
        // cond:
        // result: (ConstBool [b2i(inBounds32(c,d))])
@@ -2504,6 +2568,50 @@ func rewriteValuegeneric_OpIsInBounds(v *Value, config *Config) bool {
 func rewriteValuegeneric_OpIsSliceInBounds(v *Value, config *Config) bool {
        b := v.Block
        _ = b
+       // match: (IsSliceInBounds (And32 (Const32 [c]) _) (Const32 [d]))
+       // cond: sliceInBounds32(c, d)
+       // result: (ConstBool [1])
+       for {
+               if v.Args[0].Op != OpAnd32 {
+                       break
+               }
+               if v.Args[0].Args[0].Op != OpConst32 {
+                       break
+               }
+               c := v.Args[0].Args[0].AuxInt
+               if v.Args[1].Op != OpConst32 {
+                       break
+               }
+               d := v.Args[1].AuxInt
+               if !(sliceInBounds32(c, d)) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
+       // match: (IsSliceInBounds (And64 (Const64 [c]) _) (Const64 [d]))
+       // cond: sliceInBounds64(c, d)
+       // result: (ConstBool [1])
+       for {
+               if v.Args[0].Op != OpAnd64 {
+                       break
+               }
+               if v.Args[0].Args[0].Op != OpConst64 {
+                       break
+               }
+               c := v.Args[0].Args[0].AuxInt
+               if v.Args[1].Op != OpConst64 {
+                       break
+               }
+               d := v.Args[1].AuxInt
+               if !(sliceInBounds64(c, d)) {
+                       break
+               }
+               v.reset(OpConstBool)
+               v.AuxInt = 1
+               return true
+       }
        // match: (IsSliceInBounds (Const32 [c]) (Const32 [d]))
        // cond:
        // result: (ConstBool [b2i(sliceInBounds32(c,d))])
@@ -3875,6 +3983,26 @@ func rewriteValuegeneric_OpMod64(v *Value, config *Config) bool {
 func rewriteValuegeneric_OpMod64u(v *Value, config *Config) bool {
        b := v.Block
        _ = b
+       // match: (Mod64u <t> n (Const64 [c]))
+       // cond: isPowerOfTwo(c)
+       // result: (And64 n (Const64 <t> [c-1]))
+       for {
+               t := v.Type
+               n := v.Args[0]
+               if v.Args[1].Op != OpConst64 {
+                       break
+               }
+               c := v.Args[1].AuxInt
+               if !(isPowerOfTwo(c)) {
+                       break
+               }
+               v.reset(OpAnd64)
+               v.AddArg(n)
+               v0 := b.NewValue0(v.Line, OpConst64, t)
+               v0.AuxInt = c - 1
+               v.AddArg(v0)
+               return true
+       }
        // match: (Mod64u <t> x (Const64 [c]))
        // cond: umagic64ok(c)
        // result: (Sub64 x (Mul64 <t> (Div64u <t> x (Const64 <t> [c])) (Const64 <t> [c])))