]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: arithmetic optimization for shifts
authorYoulin Feng <fengyoulin@live.com>
Mon, 21 Oct 2024 09:22:00 +0000 (17:22 +0800)
committerGopher Robot <gobot@golang.org>
Wed, 23 Oct 2024 15:14:28 +0000 (15:14 +0000)
Fixes #69635

Change-Id: I4f8d7dafb34ccfb943c29f96c982278ab7edcd05
Reviewed-on: https://go-review.googlesource.com/c/go/+/621357
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
src/cmd/compile/internal/ssa/_gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go

index 7228acd14e213d58a2221d0f7228889e3ff29f22..2c79c9dcb0f090c070032a785171609d02cc3e6f 100644 (file)
 (Rsh64x64 (Lsh64x64 x (Const64 [48])) (Const64 [48])) => (SignExt16to64 (Trunc64to16 <typ.Int16> x))
 (Rsh64x64 (Lsh64x64 x (Const64 [32])) (Const64 [32])) => (SignExt32to64 (Trunc64to32 <typ.Int32> x))
 
+// ((x >> c) & d) << e
+(Lsh64x64 (And64 (Rsh(64|64U)x64 <t> x (Const64 <t2> [c])) (Const64 [d])) (Const64 [e])) && c >= e => (And64 (Rsh(64|64U)x64 <t> x (Const64 <t2> [c-e])) (Const64 <t> [d<<e]))
+(Lsh32x64 (And32 (Rsh(32|32U)x64 <t> x (Const64 <t2> [c])) (Const32 [d])) (Const64 [e])) && c >= e => (And32 (Rsh(32|32U)x64 <t> x (Const64 <t2> [c-e])) (Const32 <t> [d<<e]))
+(Lsh16x64 (And16 (Rsh(16|16U)x64 <t> x (Const64 <t2> [c])) (Const16 [d])) (Const64 [e])) && c >= e => (And16 (Rsh(16|16U)x64 <t> x (Const64 <t2> [c-e])) (Const16 <t> [d<<e]))
+(Lsh8x64  (And8  (Rsh(8|8U)x64   <t> x (Const64 <t2> [c])) (Const8  [d])) (Const64 [e])) && c >= e => (And8  (Rsh(8|8U)x64   <t> x (Const64 <t2> [c-e])) (Const8  <t> [d<<e]))
+(Lsh64x64 (And64 (Rsh(64|64U)x64 <t> x (Const64 <t2> [c])) (Const64 [d])) (Const64 [e])) && c < e =>  (And64 (Lsh64x64 <t> x (Const64 <t2> [e-c])) (Const64 <t> [d<<e]))
+(Lsh32x64 (And32 (Rsh(32|32U)x64 <t> x (Const64 <t2> [c])) (Const32 [d])) (Const64 [e])) && c < e =>  (And32 (Lsh32x64 <t> x (Const64 <t2> [e-c])) (Const32 <t> [d<<e]))
+(Lsh16x64 (And16 (Rsh(16|16U)x64 <t> x (Const64 <t2> [c])) (Const16 [d])) (Const64 [e])) && c < e =>  (And16 (Lsh16x64 <t> x (Const64 <t2> [e-c])) (Const16 <t> [d<<e]))
+(Lsh8x64  (And8  (Rsh(8|8U)x64   <t> x (Const64 <t2> [c])) (Const8  [d])) (Const64 [e])) && c < e =>  (And8  (Lsh8x64  <t> x (Const64 <t2> [e-c])) (Const8  <t> [d<<e]))
+
 // constant comparisons
 (Eq(64|32|16|8)   (Const(64|32|16|8) [c]) (Const(64|32|16|8) [d])) => (ConstBool [c == d])
 (Neq(64|32|16|8)  (Const(64|32|16|8) [c]) (Const(64|32|16|8) [d])) => (ConstBool [c != d])
index f0685c205e925751e5ebc43820a52382f03d2310..59199379812e5e64b6b90bc23d2033865cdbbdd1 100644 (file)
@@ -14484,6 +14484,190 @@ func rewriteValuegeneric_OpLsh16x64(v *Value) bool {
                v.AddArg2(x, v0)
                return true
        }
+       // match: (Lsh16x64 (And16 (Rsh16x64 <t> x (Const64 <t2> [c])) (Const16 [d])) (Const64 [e]))
+       // cond: c >= e
+       // result: (And16 (Rsh16x64 <t> x (Const64 <t2> [c-e])) (Const16 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd16 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh16x64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst16 {
+                               continue
+                       }
+                       d := auxIntToInt16(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c >= e) {
+                               continue
+                       }
+                       v.reset(OpAnd16)
+                       v0 := b.NewValue0(v.Pos, OpRsh16x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(c - e)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst16, t)
+                       v2.AuxInt = int16ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh16x64 (And16 (Rsh16Ux64 <t> x (Const64 <t2> [c])) (Const16 [d])) (Const64 [e]))
+       // cond: c >= e
+       // result: (And16 (Rsh16Ux64 <t> x (Const64 <t2> [c-e])) (Const16 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd16 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh16Ux64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst16 {
+                               continue
+                       }
+                       d := auxIntToInt16(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c >= e) {
+                               continue
+                       }
+                       v.reset(OpAnd16)
+                       v0 := b.NewValue0(v.Pos, OpRsh16Ux64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(c - e)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst16, t)
+                       v2.AuxInt = int16ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh16x64 (And16 (Rsh16x64 <t> x (Const64 <t2> [c])) (Const16 [d])) (Const64 [e]))
+       // cond: c < e
+       // result: (And16 (Lsh16x64 <t> x (Const64 <t2> [e-c])) (Const16 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd16 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh16x64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst16 {
+                               continue
+                       }
+                       d := auxIntToInt16(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c < e) {
+                               continue
+                       }
+                       v.reset(OpAnd16)
+                       v0 := b.NewValue0(v.Pos, OpLsh16x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(e - c)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst16, t)
+                       v2.AuxInt = int16ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh16x64 (And16 (Rsh16Ux64 <t> x (Const64 <t2> [c])) (Const16 [d])) (Const64 [e]))
+       // cond: c < e
+       // result: (And16 (Lsh16x64 <t> x (Const64 <t2> [e-c])) (Const16 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd16 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh16Ux64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst16 {
+                               continue
+                       }
+                       d := auxIntToInt16(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c < e) {
+                               continue
+                       }
+                       v.reset(OpAnd16)
+                       v0 := b.NewValue0(v.Pos, OpLsh16x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(e - c)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst16, t)
+                       v2.AuxInt = int16ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
        return false
 }
 func rewriteValuegeneric_OpLsh16x8(v *Value) bool {
@@ -14747,6 +14931,190 @@ func rewriteValuegeneric_OpLsh32x64(v *Value) bool {
                v.AddArg2(x, v0)
                return true
        }
+       // match: (Lsh32x64 (And32 (Rsh32x64 <t> x (Const64 <t2> [c])) (Const32 [d])) (Const64 [e]))
+       // cond: c >= e
+       // result: (And32 (Rsh32x64 <t> x (Const64 <t2> [c-e])) (Const32 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd32 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh32x64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst32 {
+                               continue
+                       }
+                       d := auxIntToInt32(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c >= e) {
+                               continue
+                       }
+                       v.reset(OpAnd32)
+                       v0 := b.NewValue0(v.Pos, OpRsh32x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(c - e)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst32, t)
+                       v2.AuxInt = int32ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh32x64 (And32 (Rsh32Ux64 <t> x (Const64 <t2> [c])) (Const32 [d])) (Const64 [e]))
+       // cond: c >= e
+       // result: (And32 (Rsh32Ux64 <t> x (Const64 <t2> [c-e])) (Const32 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd32 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh32Ux64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst32 {
+                               continue
+                       }
+                       d := auxIntToInt32(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c >= e) {
+                               continue
+                       }
+                       v.reset(OpAnd32)
+                       v0 := b.NewValue0(v.Pos, OpRsh32Ux64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(c - e)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst32, t)
+                       v2.AuxInt = int32ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh32x64 (And32 (Rsh32x64 <t> x (Const64 <t2> [c])) (Const32 [d])) (Const64 [e]))
+       // cond: c < e
+       // result: (And32 (Lsh32x64 <t> x (Const64 <t2> [e-c])) (Const32 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd32 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh32x64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst32 {
+                               continue
+                       }
+                       d := auxIntToInt32(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c < e) {
+                               continue
+                       }
+                       v.reset(OpAnd32)
+                       v0 := b.NewValue0(v.Pos, OpLsh32x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(e - c)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst32, t)
+                       v2.AuxInt = int32ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh32x64 (And32 (Rsh32Ux64 <t> x (Const64 <t2> [c])) (Const32 [d])) (Const64 [e]))
+       // cond: c < e
+       // result: (And32 (Lsh32x64 <t> x (Const64 <t2> [e-c])) (Const32 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd32 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh32Ux64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst32 {
+                               continue
+                       }
+                       d := auxIntToInt32(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c < e) {
+                               continue
+                       }
+                       v.reset(OpAnd32)
+                       v0 := b.NewValue0(v.Pos, OpLsh32x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(e - c)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst32, t)
+                       v2.AuxInt = int32ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
        return false
 }
 func rewriteValuegeneric_OpLsh32x8(v *Value) bool {
@@ -15010,6 +15378,190 @@ func rewriteValuegeneric_OpLsh64x64(v *Value) bool {
                v.AddArg2(x, v0)
                return true
        }
+       // match: (Lsh64x64 (And64 (Rsh64x64 <t> x (Const64 <t2> [c])) (Const64 [d])) (Const64 [e]))
+       // cond: c >= e
+       // result: (And64 (Rsh64x64 <t> x (Const64 <t2> [c-e])) (Const64 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd64 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh64x64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       d := auxIntToInt64(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c >= e) {
+                               continue
+                       }
+                       v.reset(OpAnd64)
+                       v0 := b.NewValue0(v.Pos, OpRsh64x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(c - e)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst64, t)
+                       v2.AuxInt = int64ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh64x64 (And64 (Rsh64Ux64 <t> x (Const64 <t2> [c])) (Const64 [d])) (Const64 [e]))
+       // cond: c >= e
+       // result: (And64 (Rsh64Ux64 <t> x (Const64 <t2> [c-e])) (Const64 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd64 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh64Ux64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       d := auxIntToInt64(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c >= e) {
+                               continue
+                       }
+                       v.reset(OpAnd64)
+                       v0 := b.NewValue0(v.Pos, OpRsh64Ux64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(c - e)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst64, t)
+                       v2.AuxInt = int64ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh64x64 (And64 (Rsh64x64 <t> x (Const64 <t2> [c])) (Const64 [d])) (Const64 [e]))
+       // cond: c < e
+       // result: (And64 (Lsh64x64 <t> x (Const64 <t2> [e-c])) (Const64 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd64 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh64x64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       d := auxIntToInt64(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c < e) {
+                               continue
+                       }
+                       v.reset(OpAnd64)
+                       v0 := b.NewValue0(v.Pos, OpLsh64x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(e - c)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst64, t)
+                       v2.AuxInt = int64ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh64x64 (And64 (Rsh64Ux64 <t> x (Const64 <t2> [c])) (Const64 [d])) (Const64 [e]))
+       // cond: c < e
+       // result: (And64 (Lsh64x64 <t> x (Const64 <t2> [e-c])) (Const64 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd64 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh64Ux64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       d := auxIntToInt64(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c < e) {
+                               continue
+                       }
+                       v.reset(OpAnd64)
+                       v0 := b.NewValue0(v.Pos, OpLsh64x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(e - c)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst64, t)
+                       v2.AuxInt = int64ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
        return false
 }
 func rewriteValuegeneric_OpLsh64x8(v *Value) bool {
@@ -15273,6 +15825,190 @@ func rewriteValuegeneric_OpLsh8x64(v *Value) bool {
                v.AddArg2(x, v0)
                return true
        }
+       // match: (Lsh8x64 (And8 (Rsh8x64 <t> x (Const64 <t2> [c])) (Const8 [d])) (Const64 [e]))
+       // cond: c >= e
+       // result: (And8 (Rsh8x64 <t> x (Const64 <t2> [c-e])) (Const8 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd8 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh8x64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst8 {
+                               continue
+                       }
+                       d := auxIntToInt8(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c >= e) {
+                               continue
+                       }
+                       v.reset(OpAnd8)
+                       v0 := b.NewValue0(v.Pos, OpRsh8x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(c - e)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst8, t)
+                       v2.AuxInt = int8ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh8x64 (And8 (Rsh8Ux64 <t> x (Const64 <t2> [c])) (Const8 [d])) (Const64 [e]))
+       // cond: c >= e
+       // result: (And8 (Rsh8Ux64 <t> x (Const64 <t2> [c-e])) (Const8 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd8 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh8Ux64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst8 {
+                               continue
+                       }
+                       d := auxIntToInt8(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c >= e) {
+                               continue
+                       }
+                       v.reset(OpAnd8)
+                       v0 := b.NewValue0(v.Pos, OpRsh8Ux64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(c - e)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst8, t)
+                       v2.AuxInt = int8ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh8x64 (And8 (Rsh8x64 <t> x (Const64 <t2> [c])) (Const8 [d])) (Const64 [e]))
+       // cond: c < e
+       // result: (And8 (Lsh8x64 <t> x (Const64 <t2> [e-c])) (Const8 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd8 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh8x64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst8 {
+                               continue
+                       }
+                       d := auxIntToInt8(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c < e) {
+                               continue
+                       }
+                       v.reset(OpAnd8)
+                       v0 := b.NewValue0(v.Pos, OpLsh8x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(e - c)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst8, t)
+                       v2.AuxInt = int8ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
+       // match: (Lsh8x64 (And8 (Rsh8Ux64 <t> x (Const64 <t2> [c])) (Const8 [d])) (Const64 [e]))
+       // cond: c < e
+       // result: (And8 (Lsh8x64 <t> x (Const64 <t2> [e-c])) (Const8 <t> [d<<e]))
+       for {
+               if v_0.Op != OpAnd8 {
+                       break
+               }
+               _ = v_0.Args[1]
+               v_0_0 := v_0.Args[0]
+               v_0_1 := v_0.Args[1]
+               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
+                       if v_0_0.Op != OpRsh8Ux64 {
+                               continue
+                       }
+                       t := v_0_0.Type
+                       _ = v_0_0.Args[1]
+                       x := v_0_0.Args[0]
+                       v_0_0_1 := v_0_0.Args[1]
+                       if v_0_0_1.Op != OpConst64 {
+                               continue
+                       }
+                       t2 := v_0_0_1.Type
+                       c := auxIntToInt64(v_0_0_1.AuxInt)
+                       if v_0_1.Op != OpConst8 {
+                               continue
+                       }
+                       d := auxIntToInt8(v_0_1.AuxInt)
+                       if v_1.Op != OpConst64 {
+                               continue
+                       }
+                       e := auxIntToInt64(v_1.AuxInt)
+                       if !(c < e) {
+                               continue
+                       }
+                       v.reset(OpAnd8)
+                       v0 := b.NewValue0(v.Pos, OpLsh8x64, t)
+                       v1 := b.NewValue0(v.Pos, OpConst64, t2)
+                       v1.AuxInt = int64ToAuxInt(e - c)
+                       v0.AddArg2(x, v1)
+                       v2 := b.NewValue0(v.Pos, OpConst8, t)
+                       v2.AuxInt = int8ToAuxInt(d << e)
+                       v.AddArg2(v0, v2)
+                       return true
+               }
+               break
+       }
        return false
 }
 func rewriteValuegeneric_OpLsh8x8(v *Value) bool {