From 32f4864216366f355a589c99a8d789f3341bc85c Mon Sep 17 00:00:00 2001 From: Youlin Feng Date: Mon, 21 Oct 2024 17:22:00 +0800 Subject: [PATCH] cmd/compile: arithmetic optimization for shifts Fixes #69635 Change-Id: I4f8d7dafb34ccfb943c29f96c982278ab7edcd05 Reviewed-on: https://go-review.googlesource.com/c/go/+/621357 Reviewed-by: Keith Randall Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI Auto-Submit: Keith Randall Reviewed-by: Michael Pratt --- .../compile/internal/ssa/_gen/generic.rules | 10 + .../compile/internal/ssa/rewritegeneric.go | 736 ++++++++++++++++++ 2 files changed, 746 insertions(+) diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index 7228acd14e..2c79c9dcb0 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -504,6 +504,16 @@ (Rsh64x64 (Lsh64x64 x (Const64 [48])) (Const64 [48])) => (SignExt16to64 (Trunc64to16 x)) (Rsh64x64 (Lsh64x64 x (Const64 [32])) (Const64 [32])) => (SignExt32to64 (Trunc64to32 x)) +// ((x >> c) & d) << e +(Lsh64x64 (And64 (Rsh(64|64U)x64 x (Const64 [c])) (Const64 [d])) (Const64 [e])) && c >= e => (And64 (Rsh(64|64U)x64 x (Const64 [c-e])) (Const64 [d< x (Const64 [c])) (Const32 [d])) (Const64 [e])) && c >= e => (And32 (Rsh(32|32U)x64 x (Const64 [c-e])) (Const32 [d< x (Const64 [c])) (Const16 [d])) (Const64 [e])) && c >= e => (And16 (Rsh(16|16U)x64 x (Const64 [c-e])) (Const16 [d< x (Const64 [c])) (Const8 [d])) (Const64 [e])) && c >= e => (And8 (Rsh(8|8U)x64 x (Const64 [c-e])) (Const8 [d< x (Const64 [c])) (Const64 [d])) (Const64 [e])) && c < e => (And64 (Lsh64x64 x (Const64 [e-c])) (Const64 [d< x (Const64 [c])) (Const32 [d])) (Const64 [e])) && c < e => (And32 (Lsh32x64 x (Const64 [e-c])) (Const32 [d< x (Const64 [c])) (Const16 [d])) (Const64 [e])) && c < e => (And16 (Lsh16x64 x (Const64 [e-c])) (Const16 [d< x (Const64 [c])) (Const8 [d])) (Const64 [e])) && c < e => (And8 (Lsh8x64 x (Const64 [e-c])) (Const8 [d< (ConstBool [c == d]) (Neq(64|32|16|8) (Const(64|32|16|8) [c]) (Const(64|32|16|8) [d])) => (ConstBool [c != d]) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index f0685c205e..5919937981 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -14484,6 +14484,190 @@ func rewriteValuegeneric_OpLsh16x64(v *Value) bool { v.AddArg2(x, v0) return true } + // match: (Lsh16x64 (And16 (Rsh16x64 x (Const64 [c])) (Const16 [d])) (Const64 [e])) + // cond: c >= e + // result: (And16 (Rsh16x64 x (Const64 [c-e])) (Const16 [d<= 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 x (Const64 [c])) (Const16 [d])) (Const64 [e])) + // cond: c >= e + // result: (And16 (Rsh16Ux64 x (Const64 [c-e])) (Const16 [d<= 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 x (Const64 [c])) (Const16 [d])) (Const64 [e])) + // cond: c < e + // result: (And16 (Lsh16x64 x (Const64 [e-c])) (Const16 [d< x (Const64 [c])) (Const16 [d])) (Const64 [e])) + // cond: c < e + // result: (And16 (Lsh16x64 x (Const64 [e-c])) (Const16 [d< x (Const64 [c])) (Const32 [d])) (Const64 [e])) + // cond: c >= e + // result: (And32 (Rsh32x64 x (Const64 [c-e])) (Const32 [d<= 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 x (Const64 [c])) (Const32 [d])) (Const64 [e])) + // cond: c >= e + // result: (And32 (Rsh32Ux64 x (Const64 [c-e])) (Const32 [d<= 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 x (Const64 [c])) (Const32 [d])) (Const64 [e])) + // cond: c < e + // result: (And32 (Lsh32x64 x (Const64 [e-c])) (Const32 [d< x (Const64 [c])) (Const32 [d])) (Const64 [e])) + // cond: c < e + // result: (And32 (Lsh32x64 x (Const64 [e-c])) (Const32 [d< x (Const64 [c])) (Const64 [d])) (Const64 [e])) + // cond: c >= e + // result: (And64 (Rsh64x64 x (Const64 [c-e])) (Const64 [d<= 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 x (Const64 [c])) (Const64 [d])) (Const64 [e])) + // cond: c >= e + // result: (And64 (Rsh64Ux64 x (Const64 [c-e])) (Const64 [d<= 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 x (Const64 [c])) (Const64 [d])) (Const64 [e])) + // cond: c < e + // result: (And64 (Lsh64x64 x (Const64 [e-c])) (Const64 [d< x (Const64 [c])) (Const64 [d])) (Const64 [e])) + // cond: c < e + // result: (And64 (Lsh64x64 x (Const64 [e-c])) (Const64 [d< x (Const64 [c])) (Const8 [d])) (Const64 [e])) + // cond: c >= e + // result: (And8 (Rsh8x64 x (Const64 [c-e])) (Const8 [d<= 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 x (Const64 [c])) (Const8 [d])) (Const64 [e])) + // cond: c >= e + // result: (And8 (Rsh8Ux64 x (Const64 [c-e])) (Const8 [d<= 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 x (Const64 [c])) (Const8 [d])) (Const64 [e])) + // cond: c < e + // result: (And8 (Lsh8x64 x (Const64 [e-c])) (Const8 [d< x (Const64 [c])) (Const8 [d])) (Const64 [e])) + // cond: c < e + // result: (And8 (Lsh8x64 x (Const64 [e-c])) (Const8 [d<