From 51932c326f1278a5ab48dac7d7c27799d595b135 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Thu, 15 Feb 2018 14:49:03 -0500 Subject: [PATCH] cmd/compile: improve absorb shifts optimization for arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current absorb shifts optimization can generate dead Value nodes which increase use count of other live nodes. It will impact other optimizations (such as combined loads) which are enabled based on specific use count. This patch fixes the issue by decreasing the use count of nodes referenced by dead Value nodes generated by absorb shifts optimization. Performance impacts on go1 benchmarks (data collected on A57@2GHzx8): name old time/op new time/op delta BinaryTree17-8 6.28s ± 2% 6.24s ± 1% ~ (p=0.065 n=10+9) Fannkuch11-8 6.32s ± 0% 6.33s ± 0% +0.17% (p=0.000 n=10+10) FmtFprintfEmpty-8 98.9ns ± 0% 99.2ns ± 0% +0.34% (p=0.000 n=9+7) FmtFprintfString-8 183ns ± 1% 182ns ± 1% -1.01% (p=0.005 n=9+10) FmtFprintfInt-8 199ns ± 1% 202ns ± 1% +1.41% (p=0.000 n=10+9) FmtFprintfIntInt-8 272ns ± 1% 276ns ± 3% +1.36% (p=0.015 n=10+10) FmtFprintfPrefixedInt-8 367ns ± 1% 369ns ± 1% +0.68% (p=0.042 n=10+10) FmtFprintfFloat-8 491ns ± 1% 493ns ± 1% ~ (p=0.064 n=10+10) FmtManyArgs-8 1.31µs ± 1% 1.32µs ± 1% +0.39% (p=0.042 n=8+9) GobDecode-8 17.0ms ± 2% 16.2ms ± 2% -4.74% (p=0.000 n=10+10) GobEncode-8 13.7ms ± 2% 13.4ms ± 1% -2.40% (p=0.000 n=10+9) Gzip-8 844ms ± 0% 737ms ± 0% -12.70% (p=0.000 n=10+10) Gunzip-8 84.4ms ± 1% 83.9ms ± 0% -0.55% (p=0.000 n=10+8) HTTPClientServer-8 122µs ± 1% 124µs ± 1% +1.75% (p=0.000 n=10+9) JSONEncode-8 34.9ms ± 1% 32.4ms ± 0% -7.11% (p=0.000 n=10+9) JSONDecode-8 150ms ± 0% 146ms ± 1% -2.84% (p=0.000 n=7+10) Mandelbrot200-8 10.0ms ± 0% 10.0ms ± 0% ~ (p=0.529 n=10+10) GoParse-8 8.18ms ± 1% 8.03ms ± 0% -1.93% (p=0.000 n=10+10) RegexpMatchEasy0_32-8 209ns ± 0% 209ns ± 0% ~ (p=0.248 n=10+9) RegexpMatchEasy0_1K-8 789ns ± 1% 790ns ± 0% ~ (p=0.361 n=10+10) RegexpMatchEasy1_32-8 202ns ± 0% 202ns ± 1% ~ (p=0.137 n=8+10) RegexpMatchEasy1_1K-8 1.12µs ± 2% 1.12µs ± 1% ~ (p=0.810 n=10+10) RegexpMatchMedium_32-8 298ns ± 0% 298ns ± 0% ~ (p=0.443 n=10+9) RegexpMatchMedium_1K-8 83.0µs ± 5% 78.6µs ± 0% -5.37% (p=0.000 n=10+10) RegexpMatchHard_32-8 4.32µs ± 0% 4.26µs ± 0% -1.47% (p=0.000 n=10+10) RegexpMatchHard_1K-8 132µs ± 4% 126µs ± 0% -4.41% (p=0.000 n=10+9) Revcomp-8 1.11s ± 0% 1.11s ± 0% +0.14% (p=0.017 n=10+9) Template-8 155ms ± 1% 155ms ± 1% ~ (p=0.796 n=10+10) TimeParse-8 774ns ± 1% 785ns ± 1% +1.41% (p=0.001 n=10+10) TimeFormat-8 788ns ± 1% 806ns ± 1% +2.24% (p=0.000 n=10+9) name old speed new speed delta GobDecode-8 45.2MB/s ± 2% 47.5MB/s ± 2% +4.96% (p=0.000 n=10+10) GobEncode-8 56.0MB/s ± 2% 57.4MB/s ± 1% +2.44% (p=0.000 n=10+9) Gzip-8 23.0MB/s ± 0% 26.3MB/s ± 0% +14.55% (p=0.000 n=10+10) Gunzip-8 230MB/s ± 1% 231MB/s ± 0% +0.55% (p=0.000 n=10+8) JSONEncode-8 55.6MB/s ± 1% 59.9MB/s ± 0% +7.65% (p=0.000 n=10+9) JSONDecode-8 12.9MB/s ± 0% 13.3MB/s ± 1% +2.94% (p=0.000 n=7+10) GoParse-8 7.08MB/s ± 1% 7.22MB/s ± 0% +1.95% (p=0.000 n=10+10) RegexpMatchEasy0_32-8 153MB/s ± 0% 153MB/s ± 0% -0.16% (p=0.023 n=10+10) RegexpMatchEasy0_1K-8 1.30GB/s ± 1% 1.30GB/s ± 0% ~ (p=0.393 n=10+10) RegexpMatchEasy1_32-8 158MB/s ± 0% 158MB/s ± 0% ~ (p=0.684 n=10+10) RegexpMatchEasy1_1K-8 915MB/s ± 2% 918MB/s ± 1% ~ (p=0.796 n=10+10) RegexpMatchMedium_32-8 3.35MB/s ± 0% 3.35MB/s ± 0% ~ (p=1.000 n=10+9) RegexpMatchMedium_1K-8 12.3MB/s ± 5% 13.0MB/s ± 0% +5.56% (p=0.000 n=10+10) RegexpMatchHard_32-8 7.40MB/s ± 0% 7.51MB/s ± 0% +1.50% (p=0.000 n=10+10) RegexpMatchHard_1K-8 7.75MB/s ± 4% 8.10MB/s ± 0% +4.52% (p=0.000 n=10+8) Revcomp-8 229MB/s ± 0% 228MB/s ± 0% -0.14% (p=0.017 n=10+9) Template-8 12.5MB/s ± 1% 12.5MB/s ± 1% ~ (p=0.780 n=10+10) Change-Id: I103389f168eac79f6af44e8fef93acc2a7a4ac96 Reviewed-on: https://go-review.googlesource.com/88415 Run-TryBot: Cherry Zhang TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/gc/asm_test.go | 76 +- src/cmd/compile/internal/ssa/gen/ARM64.rules | 48 +- src/cmd/compile/internal/ssa/rewrite.go | 11 + src/cmd/compile/internal/ssa/rewriteARM64.go | 756 +++++++++++-------- 4 files changed, 542 insertions(+), 349 deletions(-) diff --git a/src/cmd/compile/internal/gc/asm_test.go b/src/cmd/compile/internal/gc/asm_test.go index 9b62d9f6b1..f1ab3f5a8d 100644 --- a/src/cmd/compile/internal/gc/asm_test.go +++ b/src/cmd/compile/internal/gc/asm_test.go @@ -248,7 +248,7 @@ var allAsmTests = []*asmTests{ { arch: "arm64", os: "linux", - imports: []string{"math/bits"}, + imports: []string{"encoding/binary", "math/bits"}, tests: linuxARM64Tests, }, { @@ -2751,6 +2751,80 @@ var linuxARM64Tests = []*asmTest{ `, pos: []string{"TBZ"}, }, + // Load-combining tests. + { + fn: ` + func $(b []byte) uint64 { + return binary.LittleEndian.Uint64(b) + } + `, + pos: []string{"\tMOVD\t\\(R[0-9]+\\)"}, + }, + { + fn: ` + func $(b []byte, i int) uint64 { + return binary.LittleEndian.Uint64(b[i:]) + } + `, + pos: []string{"\tMOVD\t\\(R[0-9]+\\)"}, + }, + { + fn: ` + func $(b []byte) uint32 { + return binary.LittleEndian.Uint32(b) + } + `, + pos: []string{"\tMOVWU\t\\(R[0-9]+\\)"}, + }, + { + fn: ` + func $(b []byte, i int) uint32 { + return binary.LittleEndian.Uint32(b[i:]) + } + `, + pos: []string{"\tMOVWU\t\\(R[0-9]+\\)"}, + }, + { + fn: ` + func $(b []byte) uint64 { + return binary.BigEndian.Uint64(b) + } + `, + pos: []string{"\tREV\t"}, + }, + { + fn: ` + func $(b []byte, i int) uint64 { + return binary.BigEndian.Uint64(b[i:]) + } + `, + pos: []string{"\tREV\t"}, + }, + { + fn: ` + func $(b []byte) uint32 { + return binary.BigEndian.Uint32(b) + } + `, + pos: []string{"\tREVW\t"}, + }, + { + fn: ` + func $(b []byte, i int) uint32 { + return binary.BigEndian.Uint32(b[i:]) + } + `, + pos: []string{"\tREVW\t"}, + }, + { + fn: ` + func $(s []byte) uint16 { + return uint16(s[0]) | uint16(s[1]) << 8 + } + `, + pos: []string{"\tMOVHU\t\\(R[0-9]+\\)"}, + neg: []string{"ORR\tR[0-9]+<<8\t"}, + }, } var linuxMIPSTests = []*asmTest{ diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 48ca634438..f9af4c6da8 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1078,30 +1078,30 @@ (CSELULT0 _ (FlagGT_UGT)) -> (MOVDconst [0]) // absorb shifts into ops -(ADD x (SLLconst [c] y)) -> (ADDshiftLL x y [c]) -(ADD x (SRLconst [c] y)) -> (ADDshiftRL x y [c]) -(ADD x (SRAconst [c] y)) -> (ADDshiftRA x y [c]) -(SUB x (SLLconst [c] y)) -> (SUBshiftLL x y [c]) -(SUB x (SRLconst [c] y)) -> (SUBshiftRL x y [c]) -(SUB x (SRAconst [c] y)) -> (SUBshiftRA x y [c]) -(AND x (SLLconst [c] y)) -> (ANDshiftLL x y [c]) -(AND x (SRLconst [c] y)) -> (ANDshiftRL x y [c]) -(AND x (SRAconst [c] y)) -> (ANDshiftRA x y [c]) -(OR x (SLLconst [c] y)) -> (ORshiftLL x y [c]) // useful for combined load -(OR x (SRLconst [c] y)) -> (ORshiftRL x y [c]) -(OR x (SRAconst [c] y)) -> (ORshiftRA x y [c]) -(XOR x (SLLconst [c] y)) -> (XORshiftLL x y [c]) -(XOR x (SRLconst [c] y)) -> (XORshiftRL x y [c]) -(XOR x (SRAconst [c] y)) -> (XORshiftRA x y [c]) -(BIC x (SLLconst [c] y)) -> (BICshiftLL x y [c]) -(BIC x (SRLconst [c] y)) -> (BICshiftRL x y [c]) -(BIC x (SRAconst [c] y)) -> (BICshiftRA x y [c]) -(CMP x (SLLconst [c] y)) -> (CMPshiftLL x y [c]) -(CMP (SLLconst [c] y) x) -> (InvertFlags (CMPshiftLL x y [c])) -(CMP x (SRLconst [c] y)) -> (CMPshiftRL x y [c]) -(CMP (SRLconst [c] y) x) -> (InvertFlags (CMPshiftRL x y [c])) -(CMP x (SRAconst [c] y)) -> (CMPshiftRA x y [c]) -(CMP (SRAconst [c] y) x) -> (InvertFlags (CMPshiftRA x y [c])) +(ADD x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (ADDshiftLL x0 y [c]) +(ADD x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (ADDshiftRL x0 y [c]) +(ADD x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (ADDshiftRA x0 y [c]) +(SUB x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (SUBshiftLL x0 y [c]) +(SUB x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (SUBshiftRL x0 y [c]) +(SUB x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (SUBshiftRA x0 y [c]) +(AND x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (ANDshiftLL x0 y [c]) +(AND x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (ANDshiftRL x0 y [c]) +(AND x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (ANDshiftRA x0 y [c]) +(OR x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (ORshiftLL x0 y [c]) // useful for combined load +(OR x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (ORshiftRL x0 y [c]) +(OR x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (ORshiftRA x0 y [c]) +(XOR x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (XORshiftLL x0 y [c]) +(XOR x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (XORshiftRL x0 y [c]) +(XOR x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (XORshiftRA x0 y [c]) +(BIC x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (BICshiftLL x0 y [c]) +(BIC x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (BICshiftRL x0 y [c]) +(BIC x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (BICshiftRA x0 y [c]) +(CMP x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (CMPshiftLL x0 y [c]) +(CMP x0:(SLLconst [c] y) x1) && clobberIfDead(x0) -> (InvertFlags (CMPshiftLL x1 y [c])) +(CMP x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (CMPshiftRL x0 y [c]) +(CMP x0:(SRLconst [c] y) x1) && clobberIfDead(x0) -> (InvertFlags (CMPshiftRL x1 y [c])) +(CMP x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (CMPshiftRA x0 y [c]) +(CMP x0:(SRAconst [c] y) x1) && clobberIfDead(x0) -> (InvertFlags (CMPshiftRA x1 y [c])) // prefer *const ops to *shift ops (ADDshiftLL (MOVDconst [c]) x [d]) -> (ADDconst [c] (SLLconst x [d])) diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index c617841ee8..e595962f74 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -505,6 +505,17 @@ func clobber(v *Value) bool { return true } +// clobberIfDead resets v when use count is 1. Returns true. +// clobberIfDead is used by rewrite rules to decrement +// use counts of v's args when v is dead and never used. +func clobberIfDead(v *Value) bool { + if v.Uses == 1 { + v.reset(OpInvalid) + } + // Note: leave v.Block intact. The Block field is used after clobberIfDead. + return true +} + // noteRule is an easy way to track if a rule is matched when writing // new ones. Make the rule of interest also conditional on // noteRule("note to self: rule of interest matched") diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 4e91217517..953e06e06e 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -805,111 +805,129 @@ func rewriteValueARM64_OpARM64ADD_0(v *Value) bool { v.AddArg(y) return true } - // match: (ADD x (SLLconst [c] y)) - // cond: - // result: (ADDshiftLL x y [c]) + // match: (ADD x0 x1:(SLLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ADDshiftLL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SLLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64ADDshiftLL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (ADD (SLLconst [c] y) x) - // cond: - // result: (ADDshiftLL x y [c]) + // match: (ADD x1:(SLLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (ADDshiftLL x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SLLconst { + x1 := v.Args[0] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64ADDshiftLL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (ADD x (SRLconst [c] y)) - // cond: - // result: (ADDshiftRL x y [c]) + // match: (ADD x0 x1:(SRLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ADDshiftRL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64ADDshiftRL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (ADD (SRLconst [c] y) x) - // cond: - // result: (ADDshiftRL x y [c]) + // match: (ADD x1:(SRLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (ADDshiftRL x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SRLconst { + x1 := v.Args[0] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64ADDshiftRL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (ADD x (SRAconst [c] y)) - // cond: - // result: (ADDshiftRA x y [c]) + // match: (ADD x0 x1:(SRAconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ADDshiftRA x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRAconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64ADDshiftRA) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (ADD (SRAconst [c] y) x) - // cond: - // result: (ADDshiftRA x y [c]) + // match: (ADD x1:(SRAconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (ADDshiftRA x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SRAconst { + x1 := v.Args[0] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64ADDshiftRA) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } @@ -1304,114 +1322,132 @@ func rewriteValueARM64_OpARM64AND_0(v *Value) bool { v.AddArg(y) return true } - // match: (AND x (SLLconst [c] y)) - // cond: - // result: (ANDshiftLL x y [c]) + // match: (AND x0 x1:(SLLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ANDshiftLL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SLLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64ANDshiftLL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (AND (SLLconst [c] y) x) - // cond: - // result: (ANDshiftLL x y [c]) + // match: (AND x1:(SLLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (ANDshiftLL x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SLLconst { + x1 := v.Args[0] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64ANDshiftLL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (AND x (SRLconst [c] y)) - // cond: - // result: (ANDshiftRL x y [c]) + // match: (AND x0 x1:(SRLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ANDshiftRL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64ANDshiftRL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (AND (SRLconst [c] y) x) - // cond: - // result: (ANDshiftRL x y [c]) + // match: (AND x1:(SRLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (ANDshiftRL x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SRLconst { + x1 := v.Args[0] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64ANDshiftRL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (AND x (SRAconst [c] y)) - // cond: - // result: (ANDshiftRA x y [c]) + // match: (AND x0 x1:(SRAconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ANDshiftRA x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRAconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64ANDshiftRA) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } return false } func rewriteValueARM64_OpARM64AND_10(v *Value) bool { - // match: (AND (SRAconst [c] y) x) - // cond: - // result: (ANDshiftRA x y [c]) + // match: (AND x1:(SRAconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (ANDshiftRA x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SRAconst { + x1 := v.Args[0] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64ANDshiftRA) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } @@ -1699,57 +1735,66 @@ func rewriteValueARM64_OpARM64BIC_0(v *Value) bool { v.AuxInt = 0 return true } - // match: (BIC x (SLLconst [c] y)) - // cond: - // result: (BICshiftLL x y [c]) + // match: (BIC x0 x1:(SLLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (BICshiftLL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SLLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64BICshiftLL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (BIC x (SRLconst [c] y)) - // cond: - // result: (BICshiftRL x y [c]) + // match: (BIC x0 x1:(SRLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (BICshiftRL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64BICshiftRL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (BIC x (SRAconst [c] y)) - // cond: - // result: (BICshiftRA x y [c]) + // match: (BIC x0 x1:(SRAconst [c] y)) + // cond: clobberIfDead(x1) + // result: (BICshiftRA x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRAconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64BICshiftRA) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } @@ -1959,116 +2004,134 @@ func rewriteValueARM64_OpARM64CMP_0(v *Value) bool { v.AddArg(v0) return true } - // match: (CMP x (SLLconst [c] y)) - // cond: - // result: (CMPshiftLL x y [c]) + // match: (CMP x0 x1:(SLLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (CMPshiftLL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SLLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64CMPshiftLL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (CMP (SLLconst [c] y) x) - // cond: - // result: (InvertFlags (CMPshiftLL x y [c])) + // match: (CMP x0:(SLLconst [c] y) x1) + // cond: clobberIfDead(x0) + // result: (InvertFlags (CMPshiftLL x1 y [c])) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SLLconst { + x0 := v.Args[0] + if x0.Op != OpARM64SLLconst { + break + } + c := x0.AuxInt + y := x0.Args[0] + x1 := v.Args[1] + if !(clobberIfDead(x0)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64InvertFlags) v0 := b.NewValue0(v.Pos, OpARM64CMPshiftLL, types.TypeFlags) v0.AuxInt = c - v0.AddArg(x) + v0.AddArg(x1) v0.AddArg(y) v.AddArg(v0) return true } - // match: (CMP x (SRLconst [c] y)) - // cond: - // result: (CMPshiftRL x y [c]) + // match: (CMP x0 x1:(SRLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (CMPshiftRL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64CMPshiftRL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (CMP (SRLconst [c] y) x) - // cond: - // result: (InvertFlags (CMPshiftRL x y [c])) + // match: (CMP x0:(SRLconst [c] y) x1) + // cond: clobberIfDead(x0) + // result: (InvertFlags (CMPshiftRL x1 y [c])) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SRLconst { + x0 := v.Args[0] + if x0.Op != OpARM64SRLconst { + break + } + c := x0.AuxInt + y := x0.Args[0] + x1 := v.Args[1] + if !(clobberIfDead(x0)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64InvertFlags) v0 := b.NewValue0(v.Pos, OpARM64CMPshiftRL, types.TypeFlags) v0.AuxInt = c - v0.AddArg(x) + v0.AddArg(x1) v0.AddArg(y) v.AddArg(v0) return true } - // match: (CMP x (SRAconst [c] y)) - // cond: - // result: (CMPshiftRA x y [c]) + // match: (CMP x0 x1:(SRAconst [c] y)) + // cond: clobberIfDead(x1) + // result: (CMPshiftRA x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRAconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64CMPshiftRA) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (CMP (SRAconst [c] y) x) - // cond: - // result: (InvertFlags (CMPshiftRA x y [c])) + // match: (CMP x0:(SRAconst [c] y) x1) + // cond: clobberIfDead(x0) + // result: (InvertFlags (CMPshiftRA x1 y [c])) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SRAconst { + x0 := v.Args[0] + if x0.Op != OpARM64SRAconst { + break + } + c := x0.AuxInt + y := x0.Args[0] + x1 := v.Args[1] + if !(clobberIfDead(x0)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64InvertFlags) v0 := b.NewValue0(v.Pos, OpARM64CMPshiftRA, types.TypeFlags) v0.AuxInt = c - v0.AddArg(x) + v0.AddArg(x1) v0.AddArg(y) v.AddArg(v0) return true @@ -6930,111 +6993,129 @@ func rewriteValueARM64_OpARM64OR_0(v *Value) bool { v.AddArg(x) return true } - // match: (OR x (SLLconst [c] y)) - // cond: - // result: (ORshiftLL x y [c]) + // match: (OR x0 x1:(SLLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ORshiftLL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SLLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64ORshiftLL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (OR (SLLconst [c] y) x) - // cond: - // result: (ORshiftLL x y [c]) + // match: (OR x1:(SLLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (ORshiftLL x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SLLconst { + x1 := v.Args[0] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64ORshiftLL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (OR x (SRLconst [c] y)) - // cond: - // result: (ORshiftRL x y [c]) + // match: (OR x0 x1:(SRLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ORshiftRL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64ORshiftRL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (OR (SRLconst [c] y) x) - // cond: - // result: (ORshiftRL x y [c]) + // match: (OR x1:(SRLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (ORshiftRL x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SRLconst { + x1 := v.Args[0] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64ORshiftRL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (OR x (SRAconst [c] y)) - // cond: - // result: (ORshiftRA x y [c]) + // match: (OR x0 x1:(SRAconst [c] y)) + // cond: clobberIfDead(x1) + // result: (ORshiftRA x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRAconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64ORshiftRA) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (OR (SRAconst [c] y) x) - // cond: - // result: (ORshiftRA x y [c]) + // match: (OR x1:(SRAconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (ORshiftRA x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SRAconst { + x1 := v.Args[0] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64ORshiftRA) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } @@ -9628,57 +9709,66 @@ func rewriteValueARM64_OpARM64SUB_0(v *Value) bool { v.AddArg(v0) return true } - // match: (SUB x (SLLconst [c] y)) - // cond: - // result: (SUBshiftLL x y [c]) + // match: (SUB x0 x1:(SLLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (SUBshiftLL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SLLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64SUBshiftLL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (SUB x (SRLconst [c] y)) - // cond: - // result: (SUBshiftRL x y [c]) + // match: (SUB x0 x1:(SRLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (SUBshiftRL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64SUBshiftRL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (SUB x (SRAconst [c] y)) - // cond: - // result: (SUBshiftRA x y [c]) + // match: (SUB x0 x1:(SRAconst [c] y)) + // cond: clobberIfDead(x1) + // result: (SUBshiftRA x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRAconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64SUBshiftRA) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } @@ -10152,111 +10242,129 @@ func rewriteValueARM64_OpARM64XOR_0(v *Value) bool { v.AuxInt = 0 return true } - // match: (XOR x (SLLconst [c] y)) - // cond: - // result: (XORshiftLL x y [c]) + // match: (XOR x0 x1:(SLLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (XORshiftLL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SLLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64XORshiftLL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (XOR (SLLconst [c] y) x) - // cond: - // result: (XORshiftLL x y [c]) + // match: (XOR x1:(SLLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (XORshiftLL x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SLLconst { + x1 := v.Args[0] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64XORshiftLL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (XOR x (SRLconst [c] y)) - // cond: - // result: (XORshiftRL x y [c]) + // match: (XOR x0 x1:(SRLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (XORshiftRL x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRLconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64XORshiftRL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (XOR (SRLconst [c] y) x) - // cond: - // result: (XORshiftRL x y [c]) + // match: (XOR x1:(SRLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (XORshiftRL x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SRLconst { + x1 := v.Args[0] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64XORshiftRL) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (XOR x (SRAconst [c] y)) - // cond: - // result: (XORshiftRA x y [c]) + // match: (XOR x0 x1:(SRAconst [c] y)) + // cond: clobberIfDead(x1) + // result: (XORshiftRA x0 y [c]) for { _ = v.Args[1] - x := v.Args[0] - v_1 := v.Args[1] - if v_1.Op != OpARM64SRAconst { + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { break } - c := v_1.AuxInt - y := v_1.Args[0] v.reset(OpARM64XORshiftRA) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true } - // match: (XOR (SRAconst [c] y) x) - // cond: - // result: (XORshiftRA x y [c]) + // match: (XOR x1:(SRAconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (XORshiftRA x0 y [c]) for { _ = v.Args[1] - v_0 := v.Args[0] - if v_0.Op != OpARM64SRAconst { + x1 := v.Args[0] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { break } - c := v_0.AuxInt - y := v_0.Args[0] - x := v.Args[1] v.reset(OpARM64XORshiftRA) v.AuxInt = c - v.AddArg(x) + v.AddArg(x0) v.AddArg(y) return true }