diff options
| author | Jorropo <jorropo.pgm@gmail.com> | 2025-07-03 02:57:25 +0200 |
|---|---|---|
| committer | Jorropo <jorropo.pgm@gmail.com> | 2025-07-24 14:42:15 -0700 |
| commit | ce05ad448fe6ea3b9b33c0eab1143dcb40e3bbc3 (patch) | |
| tree | 70236648e475e034764fd106f6717b913587cc8d /src | |
| parent | fcd28070fe4fe86b04c760dd7ce5fff2aa63bad5 (diff) | |
| download | go-ce05ad448fe6ea3b9b33c0eab1143dcb40e3bbc3.tar.xz | |
cmd/compile: rewrite condselects into doublings and halvings
For performance see CL 685676.
This allows something like:
if y { x *= 2 }
To be compiled to:
SHLXQ BX, AX, AX
Instead of:
MOVQ AX, CX
SHLQ $1, CX
MOVBLZX BL, DX
TESTQ DX, DX
CMOVQNE CX, AX
While ./make.bash uniqued per LOC, there is 2 doublings and 4 halvings.
Change-Id: Ic0727cbf429528a2dbf17cbfc3b0121db8387444
Reviewed-on: https://go-review.googlesource.com/c/go/+/685695
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/compile/internal/ssa/_gen/generic.rules | 7 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/rewritegeneric.go | 240 |
2 files changed, 247 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index 89657bdabb..b98dfae2d5 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -2855,3 +2855,10 @@ // if b { x-- } => x -= b (CondSelect (Add8 <t> x (Const8 [-1])) x bool) => (Sub8 x (CvtBoolToUint8 <t> bool)) (CondSelect (Add(64|32|16) <t> x (Const(64|32|16) [-1])) x bool) => (Sub(64|32|16) x (ZeroExt8to(64|32|16) <t> (CvtBoolToUint8 <types.Types[types.TUINT8]> bool))) + +// if b { x <<= 1 } => x <<= b +(CondSelect (Lsh(64|32|16|8)x64 x (Const64 [1])) x bool) => (Lsh(64|32|16|8)x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + +// if b { x >>= 1 } => x >>= b +(CondSelect (Rsh(64|32|16|8)x64 x (Const64 [1])) x bool) => (Rsh(64|32|16|8)x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) +(CondSelect (Rsh(64|32|16|8)Ux64 x (Const64 [1])) x bool) => (Rsh(64|32|16|8)Ux8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index a8c3373e40..0b9f9c09f9 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -5942,6 +5942,246 @@ func rewriteValuegeneric_OpCondSelect(v *Value) bool { } break } + // match: (CondSelect (Lsh64x64 x (Const64 [1])) x bool) + // result: (Lsh64x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpLsh64x64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpLsh64x8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (Lsh32x64 x (Const64 [1])) x bool) + // result: (Lsh32x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpLsh32x64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpLsh32x8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (Lsh16x64 x (Const64 [1])) x bool) + // result: (Lsh16x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpLsh16x64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpLsh16x8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (Lsh8x64 x (Const64 [1])) x bool) + // result: (Lsh8x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpLsh8x64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpLsh8x8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (Rsh64x64 x (Const64 [1])) x bool) + // result: (Rsh64x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpRsh64x64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpRsh64x8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (Rsh32x64 x (Const64 [1])) x bool) + // result: (Rsh32x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpRsh32x64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpRsh32x8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (Rsh16x64 x (Const64 [1])) x bool) + // result: (Rsh16x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpRsh16x64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpRsh16x8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (Rsh8x64 x (Const64 [1])) x bool) + // result: (Rsh8x8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpRsh8x64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpRsh8x8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (Rsh64Ux64 x (Const64 [1])) x bool) + // result: (Rsh64Ux8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpRsh64Ux64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpRsh64Ux8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (Rsh32Ux64 x (Const64 [1])) x bool) + // result: (Rsh32Ux8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpRsh32Ux64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpRsh32Ux8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (Rsh16Ux64 x (Const64 [1])) x bool) + // result: (Rsh16Ux8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpRsh16Ux64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpRsh16Ux8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } + // match: (CondSelect (Rsh8Ux64 x (Const64 [1])) x bool) + // result: (Rsh8Ux8 [true] x (CvtBoolToUint8 <types.Types[types.TUINT8]> bool)) + for { + if v_0.Op != OpRsh8Ux64 { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + v_0_1 := v_0.Args[1] + if v_0_1.Op != OpConst64 || auxIntToInt64(v_0_1.AuxInt) != 1 || x != v_1 { + break + } + bool := v_2 + v.reset(OpRsh8Ux8) + v.AuxInt = boolToAuxInt(true) + v0 := b.NewValue0(v.Pos, OpCvtBoolToUint8, types.Types[types.TUINT8]) + v0.AddArg(bool) + v.AddArg2(x, v0) + return true + } return false } func rewriteValuegeneric_OpConstInterface(v *Value) bool { |
