From 4ff70cf868c9bc9d3836c53b998c8f9d9f3ede21 Mon Sep 17 00:00:00 2001 From: Jorropo Date: Tue, 11 Mar 2025 09:52:10 +0100 Subject: [PATCH] cmd/compile: add MakeTuple generic SSA op to remove duplicate Select[01] rules Change-Id: Id94a5e503f02aa29dc1e334b521770107d4261db Reviewed-on: https://go-review.googlesource.com/c/go/+/656615 Reviewed-by: Keith Randall Reviewed-by: Keith Randall Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI Auto-Submit: Jorropo --- .../compile/internal/ssa/_gen/generic.rules | 13 +- .../compile/internal/ssa/_gen/genericOps.go | 1 + src/cmd/compile/internal/ssa/opGen.go | 6 + .../compile/internal/ssa/rewritegeneric.go | 296 ++++++++---------- 4 files changed, 136 insertions(+), 180 deletions(-) diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index 49696cea2a..e671568d79 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -174,8 +174,7 @@ (Div64u (Const64 [c]) (Const64 [d])) && d != 0 => (Const64 [int64(uint64(c)/uint64(d))]) (Div32F (Const32F [c]) (Const32F [d])) && c/d == c/d => (Const32F [c/d]) (Div64F (Const64F [c]) (Const64F [d])) && c/d == c/d => (Const64F [c/d]) -(Select0 (Div128u (Const64 [0]) lo y)) => (Div64u lo y) -(Select1 (Div128u (Const64 [0]) lo y)) => (Mod64u lo y) +(Div128u (Const64 [0]) lo y) => (MakeTuple (Div64u lo y) (Mod64u lo y)) (Not (ConstBool [c])) => (ConstBool [!c]) @@ -186,8 +185,7 @@ // Convert x * 1 to x. (Mul(8|16|32|64) (Const(8|16|32|64) [1]) x) => x -(Select0 (Mul(32|64)uover (Const(32|64) [1]) x)) => x -(Select1 (Mul(32|64)uover (Const(32|64) [1]) x)) => (ConstBool [false]) +(Mul(32|64)uover (Const(32|64) [1]) x) => (MakeTuple x (ConstBool [false])) // Convert x * -1 to -x. (Mul(8|16|32|64) (Const(8|16|32|64) [-1]) x) => (Neg(8|16|32|64) x) @@ -592,8 +590,7 @@ (Add(64|32|16|8) (Const(64|32|16|8) [0]) x) => x (Sub(64|32|16|8) x x) => (Const(64|32|16|8) [0]) (Mul(64|32|16|8) (Const(64|32|16|8) [0]) _) => (Const(64|32|16|8) [0]) -(Select0 (Mul(64|32)uover (Const(64|32) [0]) x)) => (Const(64|32) [0]) -(Select1 (Mul(64|32)uover (Const(64|32) [0]) x)) => (ConstBool [false]) +(Mul(64|32)uover (Const(64|32) [0]) x) => (MakeTuple (Const(64|32) [0]) (ConstBool [false])) (Com(64|32|16|8) (Com(64|32|16|8) x)) => x (Com(64|32|16|8) (Const(64|32|16|8) [c])) => (Const(64|32|16|8) [^c]) @@ -2046,6 +2043,10 @@ (Sqrt (Const64F [c])) && !math.IsNaN(math.Sqrt(c)) => (Const64F [math.Sqrt(c)]) +// for rewriting constant folded math/bits ops +(Select0 (MakeTuple x y)) => x +(Select1 (MakeTuple x y)) => y + // for rewriting results of some late-expanded rewrites (below) (SelectN [0] (MakeResult x ___)) => x (SelectN [1] (MakeResult x y ___)) => y diff --git a/src/cmd/compile/internal/ssa/_gen/genericOps.go b/src/cmd/compile/internal/ssa/_gen/genericOps.go index 37de6e9919..0acb1fef55 100644 --- a/src/cmd/compile/internal/ssa/_gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/_gen/genericOps.go @@ -585,6 +585,7 @@ var genericOps = []opData{ // pseudo-ops for breaking Tuple {name: "Select0", argLength: 1, zeroWidth: true}, // the first component of a tuple {name: "Select1", argLength: 1, zeroWidth: true}, // the second component of a tuple + {name: "MakeTuple", argLength: 2}, // arg0 arg1 are components of a "Tuple" (like the result from a 128bits op). {name: "SelectN", argLength: 1, aux: "Int64"}, // arg0=result, auxint=field index. Returns the auxint'th member. {name: "SelectNAddr", argLength: 1, aux: "Int64"}, // arg0=result, auxint=field index. Returns the address of auxint'th member. Used for un-SSA-able result types. {name: "MakeResult", argLength: -1}, // arg0 .. are components of a "Result" (like the result from a Call). The last arg should be memory (like the result from a call). diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 03ccc0f5d7..8ceff3f449 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -3327,6 +3327,7 @@ const ( OpCvt64Fto64U OpSelect0 OpSelect1 + OpMakeTuple OpSelectN OpSelectNAddr OpMakeResult @@ -42299,6 +42300,11 @@ var opcodeTable = [...]opInfo{ zeroWidth: true, generic: true, }, + { + name: "MakeTuple", + argLen: 2, + generic: true, + }, { name: "SelectN", auxType: auxInt64, diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index b951ecdfc5..d5a50f4204 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -92,6 +92,8 @@ func rewriteValuegeneric(v *Value) bool { return rewriteValuegeneric_OpCvt64to64F(v) case OpCvtBoolToUint8: return rewriteValuegeneric_OpCvtBoolToUint8(v) + case OpDiv128u: + return rewriteValuegeneric_OpDiv128u(v) case OpDiv16: return rewriteValuegeneric_OpDiv16(v) case OpDiv16u: @@ -242,10 +244,14 @@ func rewriteValuegeneric(v *Value) bool { return rewriteValuegeneric_OpMul32(v) case OpMul32F: return rewriteValuegeneric_OpMul32F(v) + case OpMul32uover: + return rewriteValuegeneric_OpMul32uover(v) case OpMul64: return rewriteValuegeneric_OpMul64(v) case OpMul64F: return rewriteValuegeneric_OpMul64F(v) + case OpMul64uover: + return rewriteValuegeneric_OpMul64uover(v) case OpMul8: return rewriteValuegeneric_OpMul8(v) case OpNeg16: @@ -6246,6 +6252,30 @@ func rewriteValuegeneric_OpCvtBoolToUint8(v *Value) bool { } return false } +func rewriteValuegeneric_OpDiv128u(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + // match: (Div128u (Const64 [0]) lo y) + // result: (MakeTuple (Div64u lo y) (Mod64u lo y)) + for { + t := v.Type + if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 { + break + } + lo := v_1 + y := v_2 + v.reset(OpMakeTuple) + v0 := b.NewValue0(v.Pos, OpDiv64u, t.FieldType(0)) + v0.AddArg2(lo, y) + v1 := b.NewValue0(v.Pos, OpMod64u, t.FieldType(1)) + v1.AddArg2(lo, y) + v.AddArg2(v0, v1) + return true + } + return false +} func rewriteValuegeneric_OpDiv16(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -18696,6 +18726,47 @@ func rewriteValuegeneric_OpMul32F(v *Value) bool { } return false } +func rewriteValuegeneric_OpMul32uover(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + // match: (Mul32uover (Const32 [1]) x) + // result: (MakeTuple x (ConstBool [false])) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 1 { + continue + } + x := v_1 + v.reset(OpMakeTuple) + v0 := b.NewValue0(v.Pos, OpConstBool, t.FieldType(1)) + v0.AuxInt = boolToAuxInt(false) + v.AddArg2(x, v0) + return true + } + break + } + // match: (Mul32uover (Const32 [0]) x) + // result: (MakeTuple (Const32 [0]) (ConstBool [false])) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst32 || auxIntToInt32(v_0.AuxInt) != 0 { + continue + } + v.reset(OpMakeTuple) + v0 := b.NewValue0(v.Pos, OpConst32, t.FieldType(0)) + v0.AuxInt = int32ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpConstBool, t.FieldType(1)) + v1.AuxInt = boolToAuxInt(false) + v.AddArg2(v0, v1) + return true + } + break + } + return false +} func rewriteValuegeneric_OpMul64(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -18971,6 +19042,47 @@ func rewriteValuegeneric_OpMul64F(v *Value) bool { } return false } +func rewriteValuegeneric_OpMul64uover(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + // match: (Mul64uover (Const64 [1]) x) + // result: (MakeTuple x (ConstBool [false])) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 1 { + continue + } + x := v_1 + v.reset(OpMakeTuple) + v0 := b.NewValue0(v.Pos, OpConstBool, t.FieldType(1)) + v0.AuxInt = boolToAuxInt(false) + v.AddArg2(x, v0) + return true + } + break + } + // match: (Mul64uover (Const64 [0]) x) + // result: (MakeTuple (Const64 [0]) (ConstBool [false])) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpConst64 || auxIntToInt64(v_0.AuxInt) != 0 { + continue + } + v.reset(OpMakeTuple) + v0 := b.NewValue0(v.Pos, OpConst64, t.FieldType(0)) + v0.AuxInt = int64ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpConstBool, t.FieldType(1)) + v1.AuxInt = boolToAuxInt(false) + v.AddArg2(v0, v1) + return true + } + break + } + return false +} func rewriteValuegeneric_OpMul8(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -29095,194 +29207,30 @@ func rewriteValuegeneric_OpRsh8x8(v *Value) bool { } func rewriteValuegeneric_OpSelect0(v *Value) bool { v_0 := v.Args[0] - // match: (Select0 (Div128u (Const64 [0]) lo y)) - // result: (Div64u lo y) - for { - if v_0.Op != OpDiv128u { - break - } - y := v_0.Args[2] - v_0_0 := v_0.Args[0] - if v_0_0.Op != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 0 { - break - } - lo := v_0.Args[1] - v.reset(OpDiv64u) - v.AddArg2(lo, y) - return true - } - // match: (Select0 (Mul32uover (Const32 [1]) x)) - // result: x - for { - if v_0.Op != OpMul32uover { - 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 != OpConst32 || auxIntToInt32(v_0_0.AuxInt) != 1 { - continue - } - x := v_0_1 - v.copyOf(x) - return true - } - break - } - // match: (Select0 (Mul64uover (Const64 [1]) x)) + // match: (Select0 (MakeTuple x y)) // result: x for { - if v_0.Op != OpMul64uover { - 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 != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 1 { - continue - } - x := v_0_1 - v.copyOf(x) - return true - } - break - } - // match: (Select0 (Mul64uover (Const64 [0]) x)) - // result: (Const64 [0]) - for { - if v_0.Op != OpMul64uover { + if v_0.Op != OpMakeTuple { 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 != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 0 { - continue - } - v.reset(OpConst64) - v.AuxInt = int64ToAuxInt(0) - return true - } - break - } - // match: (Select0 (Mul32uover (Const32 [0]) x)) - // result: (Const32 [0]) - for { - if v_0.Op != OpMul32uover { - 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 != OpConst32 || auxIntToInt32(v_0_0.AuxInt) != 0 { - continue - } - v.reset(OpConst32) - v.AuxInt = int32ToAuxInt(0) - return true - } - break + x := v_0.Args[0] + v.copyOf(x) + return true } return false } func rewriteValuegeneric_OpSelect1(v *Value) bool { v_0 := v.Args[0] - // match: (Select1 (Div128u (Const64 [0]) lo y)) - // result: (Mod64u lo y) + // match: (Select1 (MakeTuple x y)) + // result: y for { - if v_0.Op != OpDiv128u { - break - } - y := v_0.Args[2] - v_0_0 := v_0.Args[0] - if v_0_0.Op != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 0 { + if v_0.Op != OpMakeTuple { break } - lo := v_0.Args[1] - v.reset(OpMod64u) - v.AddArg2(lo, y) + y := v_0.Args[1] + v.copyOf(y) return true } - // match: (Select1 (Mul32uover (Const32 [1]) x)) - // result: (ConstBool [false]) - for { - if v_0.Op != OpMul32uover { - 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 != OpConst32 || auxIntToInt32(v_0_0.AuxInt) != 1 { - continue - } - v.reset(OpConstBool) - v.AuxInt = boolToAuxInt(false) - return true - } - break - } - // match: (Select1 (Mul64uover (Const64 [1]) x)) - // result: (ConstBool [false]) - for { - if v_0.Op != OpMul64uover { - 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 != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 1 { - continue - } - v.reset(OpConstBool) - v.AuxInt = boolToAuxInt(false) - return true - } - break - } - // match: (Select1 (Mul64uover (Const64 [0]) x)) - // result: (ConstBool [false]) - for { - if v_0.Op != OpMul64uover { - 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 != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 0 { - continue - } - v.reset(OpConstBool) - v.AuxInt = boolToAuxInt(false) - return true - } - break - } - // match: (Select1 (Mul32uover (Const32 [0]) x)) - // result: (ConstBool [false]) - for { - if v_0.Op != OpMul32uover { - 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 != OpConst32 || auxIntToInt32(v_0_0.AuxInt) != 0 { - continue - } - v.reset(OpConstBool) - v.AuxInt = boolToAuxInt(false) - return true - } - break - } return false } func rewriteValuegeneric_OpSelectN(v *Value) bool { -- 2.50.0