From: Ben Shi Date: Thu, 27 Sep 2018 06:21:14 +0000 (+0000) Subject: cmd/compile: optimize arm64's code with more shifted operations X-Git-Tag: go1.12beta1~976 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=5aeecc4530657ab366122424b3ad78de83bc19ff;p=gostls13.git cmd/compile: optimize arm64's code with more shifted operations This CL optimizes arm64's NEG/MVN/TST/CMN with a shifted operand. 1. The total size of pkg/android_arm64 decreases about 0.2KB, excluding cmd/compile/ . 2. The go1 benchmark shows no regression, excluding noise. name old time/op new time/op delta BinaryTree17-4 16.4s ± 1% 16.4s ± 1% ~ (p=0.914 n=29+29) Fannkuch11-4 8.72s ± 0% 8.72s ± 0% ~ (p=0.274 n=30+29) FmtFprintfEmpty-4 174ns ± 0% 174ns ± 0% ~ (all equal) FmtFprintfString-4 370ns ± 0% 370ns ± 0% ~ (all equal) FmtFprintfInt-4 419ns ± 0% 419ns ± 0% ~ (all equal) FmtFprintfIntInt-4 672ns ± 1% 675ns ± 2% ~ (p=0.217 n=28+30) FmtFprintfPrefixedInt-4 806ns ± 0% 806ns ± 0% ~ (p=0.402 n=30+28) FmtFprintfFloat-4 1.09µs ± 0% 1.09µs ± 0% +0.02% (p=0.011 n=22+27) FmtManyArgs-4 2.67µs ± 0% 2.68µs ± 0% ~ (p=0.279 n=29+30) GobDecode-4 33.1ms ± 1% 33.1ms ± 0% ~ (p=0.052 n=28+29) GobEncode-4 29.6ms ± 0% 29.6ms ± 0% +0.08% (p=0.013 n=28+29) Gzip-4 1.38s ± 2% 1.39s ± 2% ~ (p=0.071 n=29+29) Gunzip-4 139ms ± 0% 139ms ± 0% ~ (p=0.265 n=29+29) HTTPClientServer-4 789µs ± 4% 785µs ± 4% ~ (p=0.206 n=29+28) JSONEncode-4 49.7ms ± 0% 49.6ms ± 0% -0.24% (p=0.000 n=30+30) JSONDecode-4 266ms ± 1% 267ms ± 1% +0.34% (p=0.000 n=30+30) Mandelbrot200-4 16.6ms ± 0% 16.6ms ± 0% ~ (p=0.835 n=28+30) GoParse-4 15.9ms ± 0% 15.8ms ± 0% -0.29% (p=0.000 n=27+30) RegexpMatchEasy0_32-4 380ns ± 0% 381ns ± 0% +0.18% (p=0.000 n=30+30) RegexpMatchEasy0_1K-4 1.18µs ± 0% 1.19µs ± 0% +0.23% (p=0.000 n=30+30) RegexpMatchEasy1_32-4 357ns ± 0% 358ns ± 0% +0.28% (p=0.000 n=29+29) RegexpMatchEasy1_1K-4 2.04µs ± 0% 2.04µs ± 0% +0.06% (p=0.006 n=30+30) RegexpMatchMedium_32-4 589ns ± 0% 590ns ± 0% +0.24% (p=0.000 n=28+30) RegexpMatchMedium_1K-4 162µs ± 0% 162µs ± 0% -0.01% (p=0.027 n=26+29) RegexpMatchHard_32-4 9.58µs ± 0% 9.58µs ± 0% ~ (p=0.935 n=30+30) RegexpMatchHard_1K-4 287µs ± 0% 287µs ± 0% ~ (p=0.387 n=29+30) Revcomp-4 2.50s ± 0% 2.50s ± 0% -0.10% (p=0.020 n=28+28) Template-4 310ms ± 0% 310ms ± 1% ~ (p=0.406 n=30+30) TimeParse-4 1.68µs ± 0% 1.68µs ± 0% +0.03% (p=0.014 n=30+17) TimeFormat-4 1.65µs ± 0% 1.66µs ± 0% +0.32% (p=0.000 n=27+29) [Geo mean] 247µs 247µs +0.05% name old speed new speed delta GobDecode-4 23.2MB/s ± 0% 23.2MB/s ± 0% -0.08% (p=0.032 n=27+29) GobEncode-4 26.0MB/s ± 0% 25.9MB/s ± 0% -0.10% (p=0.011 n=29+29) Gzip-4 14.1MB/s ± 2% 14.0MB/s ± 2% ~ (p=0.081 n=29+29) Gunzip-4 139MB/s ± 0% 139MB/s ± 0% ~ (p=0.290 n=29+29) JSONEncode-4 39.0MB/s ± 0% 39.1MB/s ± 0% +0.25% (p=0.000 n=29+30) JSONDecode-4 7.30MB/s ± 1% 7.28MB/s ± 1% -0.33% (p=0.000 n=30+30) GoParse-4 3.65MB/s ± 0% 3.66MB/s ± 0% +0.29% (p=0.000 n=27+30) RegexpMatchEasy0_32-4 84.1MB/s ± 0% 84.0MB/s ± 0% -0.17% (p=0.000 n=30+28) RegexpMatchEasy0_1K-4 864MB/s ± 0% 862MB/s ± 0% -0.24% (p=0.000 n=30+30) RegexpMatchEasy1_32-4 89.5MB/s ± 0% 89.3MB/s ± 0% -0.18% (p=0.000 n=28+24) RegexpMatchEasy1_1K-4 502MB/s ± 0% 502MB/s ± 0% -0.05% (p=0.008 n=30+29) RegexpMatchMedium_32-4 1.70MB/s ± 0% 1.69MB/s ± 0% -0.59% (p=0.000 n=29+30) RegexpMatchMedium_1K-4 6.31MB/s ± 0% 6.31MB/s ± 0% +0.05% (p=0.005 n=30+26) RegexpMatchHard_32-4 3.34MB/s ± 0% 3.34MB/s ± 0% ~ (all equal) RegexpMatchHard_1K-4 3.57MB/s ± 0% 3.57MB/s ± 0% ~ (all equal) Revcomp-4 102MB/s ± 0% 102MB/s ± 0% +0.10% (p=0.022 n=28+28) Template-4 6.26MB/s ± 0% 6.26MB/s ± 1% ~ (p=0.768 n=30+30) [Geo mean] 24.2MB/s 24.1MB/s -0.08% Change-Id: I494f9db7f8a568a00e9c74ae25086a58b2221683 Reviewed-on: https://go-review.googlesource.com/137976 Run-TryBot: Ben Shi TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index 482442cd22..87703dd80d 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -255,6 +255,12 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { p.Reg = v.Args[1].Reg() p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() + case ssa.OpARM64MVNshiftLL, ssa.OpARM64NEGshiftLL: + genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_LL, v.AuxInt) + case ssa.OpARM64MVNshiftRL, ssa.OpARM64NEGshiftRL: + genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_LR, v.AuxInt) + case ssa.OpARM64MVNshiftRA, ssa.OpARM64NEGshiftRA: + genshift(s, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm64.SHIFT_AR, v.AuxInt) case ssa.OpARM64ADDshiftLL, ssa.OpARM64SUBshiftLL, ssa.OpARM64ANDshiftLL, @@ -317,11 +323,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { p.From.Type = obj.TYPE_CONST p.From.Offset = v.AuxInt p.Reg = v.Args[0].Reg() - case ssa.OpARM64CMPshiftLL: + case ssa.OpARM64CMPshiftLL, ssa.OpARM64CMNshiftLL, ssa.OpARM64TSTshiftLL: genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_LL, v.AuxInt) - case ssa.OpARM64CMPshiftRL: + case ssa.OpARM64CMPshiftRL, ssa.OpARM64CMNshiftRL, ssa.OpARM64TSTshiftRL: genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_LR, v.AuxInt) - case ssa.OpARM64CMPshiftRA: + case ssa.OpARM64CMPshiftRA, ssa.OpARM64CMNshiftRA, ssa.OpARM64TSTshiftRA: genshift(s, v.Op.Asm(), v.Args[0].Reg(), v.Args[1].Reg(), 0, arm64.SHIFT_AR, v.AuxInt) case ssa.OpARM64MOVDaddr: p := s.Prog(arm64.AMOVD) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 3fce018d45..659081ec8b 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1605,6 +1605,12 @@ (CSEL0 {arm64Negate(bool.Op)} x flagArg(bool)) // absorb shifts into ops +(NEG x:(SLLconst [c] y)) && clobberIfDead(x) -> (NEGshiftLL [c] y) +(NEG x:(SRLconst [c] y)) && clobberIfDead(x) -> (NEGshiftRL [c] y) +(NEG x:(SRAconst [c] y)) && clobberIfDead(x) -> (NEGshiftRA [c] y) +(MVN x:(SLLconst [c] y)) && clobberIfDead(x) -> (MVNshiftLL [c] y) +(MVN x:(SRLconst [c] y)) && clobberIfDead(x) -> (MVNshiftRL [c] y) +(MVN x:(SRAconst [c] y)) && clobberIfDead(x) -> (MVNshiftRA [c] y) (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]) @@ -1635,6 +1641,12 @@ (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])) +(CMN x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (CMNshiftLL x0 y [c]) +(CMN x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (CMNshiftRL x0 y [c]) +(CMN x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (CMNshiftRA x0 y [c]) +(TST x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (TSTshiftLL x0 y [c]) +(TST x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (TSTshiftRL x0 y [c]) +(TST x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (TSTshiftRA x0 y [c]) // prefer *const ops to *shift ops (ADDshiftLL (MOVDconst [c]) x [d]) -> (ADDconst [c] (SLLconst x [d])) @@ -1652,8 +1664,20 @@ (CMPshiftLL (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SLLconst x [d]))) (CMPshiftRL (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRLconst x [d]))) (CMPshiftRA (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRAconst x [d]))) +(CMNshiftLL (MOVDconst [c]) x [d]) -> (CMNconst [c] (SLLconst x [d])) +(CMNshiftRL (MOVDconst [c]) x [d]) -> (CMNconst [c] (SRLconst x [d])) +(CMNshiftRA (MOVDconst [c]) x [d]) -> (CMNconst [c] (SRAconst x [d])) +(TSTshiftLL (MOVDconst [c]) x [d]) -> (TSTconst [c] (SLLconst x [d])) +(TSTshiftRL (MOVDconst [c]) x [d]) -> (TSTconst [c] (SRLconst x [d])) +(TSTshiftRA (MOVDconst [c]) x [d]) -> (TSTconst [c] (SRAconst x [d])) // constant folding in *shift ops +(MVNshiftLL (MOVDconst [c]) [d]) -> (MOVDconst [^int64(uint64(c)< (MOVDconst [^int64(uint64(c)>>uint64(d))]) +(MVNshiftRA (MOVDconst [c]) [d]) -> (MOVDconst [^(c>>uint64(d))]) +(NEGshiftLL (MOVDconst [c]) [d]) -> (MOVDconst [-int64(uint64(c)< (MOVDconst [-int64(uint64(c)>>uint64(d))]) +(NEGshiftRA (MOVDconst [c]) [d]) -> (MOVDconst [-(c>>uint64(d))]) (ADDshiftLL x (MOVDconst [c]) [d]) -> (ADDconst x [int64(uint64(c)< (ADDconst x [int64(uint64(c)>>uint64(d))]) (ADDshiftRA x (MOVDconst [c]) [d]) -> (ADDconst x [c>>uint64(d)]) @@ -1681,6 +1705,12 @@ (CMPshiftLL x (MOVDconst [c]) [d]) -> (CMPconst x [int64(uint64(c)< (CMPconst x [int64(uint64(c)>>uint64(d))]) (CMPshiftRA x (MOVDconst [c]) [d]) -> (CMPconst x [c>>uint64(d)]) +(CMNshiftLL x (MOVDconst [c]) [d]) -> (CMNconst x [int64(uint64(c)< (CMNconst x [int64(uint64(c)>>uint64(d))]) +(CMNshiftRA x (MOVDconst [c]) [d]) -> (CMNconst x [c>>uint64(d)]) +(TSTshiftLL x (MOVDconst [c]) [d]) -> (TSTconst x [int64(uint64(c)< (TSTconst x [int64(uint64(c)>>uint64(d))]) +(TSTshiftRA x (MOVDconst [c]) [d]) -> (TSTconst x [c>>uint64(d)]) // simplification with *shift ops (SUBshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVDconst [0]) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index 4381c081b7..fc0a41527b 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -273,6 +273,12 @@ func init() { {name: "FCMPD", argLength: 2, reg: fp2flags, asm: "FCMPD", typ: "Flags"}, // arg0 compare to arg1, float64 // shifted ops + {name: "MVNshiftLL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"}, // ^(arg0<>auxInt), unsigned shift + {name: "MVNshiftRA", argLength: 1, reg: gp11, asm: "MVN", aux: "Int64"}, // ^(arg0>>auxInt), signed shift + {name: "NEGshiftLL", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"}, // -(arg0<>auxInt), unsigned shift + {name: "NEGshiftRA", argLength: 1, reg: gp11, asm: "NEG", aux: "Int64"}, // -(arg0>>auxInt), signed shift {name: "ADDshiftLL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"}, // arg0 + arg1<>auxInt, unsigned shift {name: "ADDshiftRA", argLength: 2, reg: gp21, asm: "ADD", aux: "Int64"}, // arg0 + arg1>>auxInt, signed shift @@ -300,6 +306,12 @@ func init() { {name: "CMPshiftLL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to arg1<>auxInt, unsigned shift {name: "CMPshiftRA", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int64", typ: "Flags"}, // arg0 compare to arg1>>auxInt, signed shift + {name: "CMNshiftLL", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // (arg0 + arg1<>auxInt) compare to 0, unsigned shift + {name: "CMNshiftRA", argLength: 2, reg: gp2flags, asm: "CMN", aux: "Int64", typ: "Flags"}, // (arg0 + arg1>>auxInt) compare to 0, signed shift + {name: "TSTshiftLL", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // (arg0 & arg1<>auxInt) compare to 0, unsigned shift + {name: "TSTshiftRA", argLength: 2, reg: gp2flags, asm: "TST", aux: "Int64", typ: "Flags"}, // (arg0 & arg1>>auxInt) compare to 0, signed shift // bitfield ops // for all bitfield ops lsb is auxInt>>8, width is auxInt&0xff diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index fe63633750..5f5345ad5c 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1172,6 +1172,12 @@ const ( OpARM64TSTWconst OpARM64FCMPS OpARM64FCMPD + OpARM64MVNshiftLL + OpARM64MVNshiftRL + OpARM64MVNshiftRA + OpARM64NEGshiftLL + OpARM64NEGshiftRL + OpARM64NEGshiftRA OpARM64ADDshiftLL OpARM64ADDshiftRL OpARM64ADDshiftRA @@ -1199,6 +1205,12 @@ const ( OpARM64CMPshiftLL OpARM64CMPshiftRL OpARM64CMPshiftRA + OpARM64CMNshiftLL + OpARM64CMNshiftRL + OpARM64CMNshiftRA + OpARM64TSTshiftLL + OpARM64TSTshiftRL + OpARM64TSTshiftRA OpARM64BFI OpARM64BFXIL OpARM64SBFIZ @@ -15553,6 +15565,90 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "MVNshiftLL", + auxType: auxInt64, + argLen: 1, + asm: arm64.AMVN, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, + { + name: "MVNshiftRL", + auxType: auxInt64, + argLen: 1, + asm: arm64.AMVN, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, + { + name: "MVNshiftRA", + auxType: auxInt64, + argLen: 1, + asm: arm64.AMVN, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, + { + name: "NEGshiftLL", + auxType: auxInt64, + argLen: 1, + asm: arm64.ANEG, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, + { + name: "NEGshiftRL", + auxType: auxInt64, + argLen: 1, + asm: arm64.ANEG, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, + { + name: "NEGshiftRA", + auxType: auxInt64, + argLen: 1, + asm: arm64.ANEG, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, { name: "ADDshiftLL", auxType: auxInt64, @@ -15949,6 +16045,78 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "CMNshiftLL", + auxType: auxInt64, + argLen: 2, + asm: arm64.ACMN, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + }, + }, + { + name: "CMNshiftRL", + auxType: auxInt64, + argLen: 2, + asm: arm64.ACMN, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + }, + }, + { + name: "CMNshiftRA", + auxType: auxInt64, + argLen: 2, + asm: arm64.ACMN, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + }, + }, + { + name: "TSTshiftLL", + auxType: auxInt64, + argLen: 2, + asm: arm64.ATST, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + }, + }, + { + name: "TSTshiftRL", + auxType: auxInt64, + argLen: 2, + asm: arm64.ATST, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + }, + }, + { + name: "TSTshiftRA", + auxType: auxInt64, + argLen: 2, + asm: arm64.ATST, + reg: regInfo{ + inputs: []inputInfo{ + {0, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + }, + }, + }, { name: "BFI", auxType: auxInt64, diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index f07ab42090..95011eab48 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -51,6 +51,12 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64CMNWconst_0(v) case OpARM64CMNconst: return rewriteValueARM64_OpARM64CMNconst_0(v) + case OpARM64CMNshiftLL: + return rewriteValueARM64_OpARM64CMNshiftLL_0(v) + case OpARM64CMNshiftRA: + return rewriteValueARM64_OpARM64CMNshiftRA_0(v) + case OpARM64CMNshiftRL: + return rewriteValueARM64_OpARM64CMNshiftRL_0(v) case OpARM64CMP: return rewriteValueARM64_OpARM64CMP_0(v) case OpARM64CMPW: @@ -259,8 +265,20 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64MULW_0(v) || rewriteValueARM64_OpARM64MULW_10(v) || rewriteValueARM64_OpARM64MULW_20(v) case OpARM64MVN: return rewriteValueARM64_OpARM64MVN_0(v) + case OpARM64MVNshiftLL: + return rewriteValueARM64_OpARM64MVNshiftLL_0(v) + case OpARM64MVNshiftRA: + return rewriteValueARM64_OpARM64MVNshiftRA_0(v) + case OpARM64MVNshiftRL: + return rewriteValueARM64_OpARM64MVNshiftRL_0(v) case OpARM64NEG: return rewriteValueARM64_OpARM64NEG_0(v) + case OpARM64NEGshiftLL: + return rewriteValueARM64_OpARM64NEGshiftLL_0(v) + case OpARM64NEGshiftRA: + return rewriteValueARM64_OpARM64NEGshiftRA_0(v) + case OpARM64NEGshiftRL: + return rewriteValueARM64_OpARM64NEGshiftRL_0(v) case OpARM64NotEqual: return rewriteValueARM64_OpARM64NotEqual_0(v) case OpARM64OR: @@ -317,6 +335,12 @@ func rewriteValueARM64(v *Value) bool { return rewriteValueARM64_OpARM64TSTWconst_0(v) case OpARM64TSTconst: return rewriteValueARM64_OpARM64TSTconst_0(v) + case OpARM64TSTshiftLL: + return rewriteValueARM64_OpARM64TSTshiftLL_0(v) + case OpARM64TSTshiftRA: + return rewriteValueARM64_OpARM64TSTshiftRA_0(v) + case OpARM64TSTshiftRL: + return rewriteValueARM64_OpARM64TSTshiftRL_0(v) case OpARM64UBFIZ: return rewriteValueARM64_OpARM64UBFIZ_0(v) case OpARM64UBFX: @@ -3340,6 +3364,132 @@ func rewriteValueARM64_OpARM64CMN_0(v *Value) bool { v.AddArg(x) return true } + // match: (CMN x0 x1:(SLLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (CMNshiftLL x0 y [c]) + for { + _ = v.Args[1] + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64CMNshiftLL) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } + // match: (CMN x1:(SLLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (CMNshiftLL x0 y [c]) + for { + _ = v.Args[1] + x1 := v.Args[0] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64CMNshiftLL) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } + // match: (CMN x0 x1:(SRLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (CMNshiftRL x0 y [c]) + for { + _ = v.Args[1] + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64CMNshiftRL) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } + // match: (CMN x1:(SRLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (CMNshiftRL x0 y [c]) + for { + _ = v.Args[1] + x1 := v.Args[0] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64CMNshiftRL) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } + // match: (CMN x0 x1:(SRAconst [c] y)) + // cond: clobberIfDead(x1) + // result: (CMNshiftRA x0 y [c]) + for { + _ = v.Args[1] + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64CMNshiftRA) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } + // match: (CMN x1:(SRAconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (CMNshiftRA x0 y [c]) + for { + _ = v.Args[1] + x1 := v.Args[0] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64CMNshiftRA) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } return false } func rewriteValueARM64_OpARM64CMNW_0(v *Value) bool { @@ -3543,6 +3693,132 @@ func rewriteValueARM64_OpARM64CMNconst_0(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64CMNshiftLL_0(v *Value) bool { + b := v.Block + _ = b + // match: (CMNshiftLL (MOVDconst [c]) x [d]) + // cond: + // result: (CMNconst [c] (SLLconst x [d])) + for { + d := v.AuxInt + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpARM64MOVDconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(OpARM64CMNconst) + v.AuxInt = c + v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) + v0.AuxInt = d + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (CMNshiftLL x (MOVDconst [c]) [d]) + // cond: + // result: (CMNconst x [int64(uint64(c)< x [d])) + for { + d := v.AuxInt + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpARM64MOVDconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(OpARM64CMNconst) + v.AuxInt = c + v0 := b.NewValue0(v.Pos, OpARM64SRAconst, x.Type) + v0.AuxInt = d + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (CMNshiftRA x (MOVDconst [c]) [d]) + // cond: + // result: (CMNconst x [c>>uint64(d)]) + for { + d := v.AuxInt + _ = v.Args[1] + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpARM64MOVDconst { + break + } + c := v_1.AuxInt + v.reset(OpARM64CMNconst) + v.AuxInt = c >> uint64(d) + v.AddArg(x) + return true + } + return false +} +func rewriteValueARM64_OpARM64CMNshiftRL_0(v *Value) bool { + b := v.Block + _ = b + // match: (CMNshiftRL (MOVDconst [c]) x [d]) + // cond: + // result: (CMNconst [c] (SRLconst x [d])) + for { + d := v.AuxInt + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpARM64MOVDconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(OpARM64CMNconst) + v.AuxInt = c + v0 := b.NewValue0(v.Pos, OpARM64SRLconst, x.Type) + v0.AuxInt = d + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (CMNshiftRL x (MOVDconst [c]) [d]) + // cond: + // result: (CMNconst x [int64(uint64(c)>>uint64(d))]) + for { + d := v.AuxInt + _ = v.Args[1] + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpARM64MOVDconst { + break + } + c := v_1.AuxInt + v.reset(OpARM64CMNconst) + v.AuxInt = int64(uint64(c) >> uint64(d)) + v.AddArg(x) + return true + } + return false +} func rewriteValueARM64_OpARM64CMP_0(v *Value) bool { b := v.Block _ = b @@ -19959,47 +20235,152 @@ func rewriteValueARM64_OpARM64MVN_0(v *Value) bool { v.AuxInt = ^c return true } - return false -} -func rewriteValueARM64_OpARM64NEG_0(v *Value) bool { - // match: (NEG (MUL x y)) - // cond: - // result: (MNEG x y) + // match: (MVN x:(SLLconst [c] y)) + // cond: clobberIfDead(x) + // result: (MVNshiftLL [c] y) for { - v_0 := v.Args[0] - if v_0.Op != OpARM64MUL { + x := v.Args[0] + if x.Op != OpARM64SLLconst { break } - _ = v_0.Args[1] - x := v_0.Args[0] - y := v_0.Args[1] - v.reset(OpARM64MNEG) - v.AddArg(x) + c := x.AuxInt + y := x.Args[0] + if !(clobberIfDead(x)) { + break + } + v.reset(OpARM64MVNshiftLL) + v.AuxInt = c v.AddArg(y) return true } - // match: (NEG (MULW x y)) - // cond: - // result: (MNEGW x y) + // match: (MVN x:(SRLconst [c] y)) + // cond: clobberIfDead(x) + // result: (MVNshiftRL [c] y) for { - v_0 := v.Args[0] - if v_0.Op != OpARM64MULW { + x := v.Args[0] + if x.Op != OpARM64SRLconst { break } - _ = v_0.Args[1] - x := v_0.Args[0] - y := v_0.Args[1] - v.reset(OpARM64MNEGW) - v.AddArg(x) + c := x.AuxInt + y := x.Args[0] + if !(clobberIfDead(x)) { + break + } + v.reset(OpARM64MVNshiftRL) + v.AuxInt = c v.AddArg(y) return true } - // match: (NEG (MOVDconst [c])) - // cond: - // result: (MOVDconst [-c]) + // match: (MVN x:(SRAconst [c] y)) + // cond: clobberIfDead(x) + // result: (MVNshiftRA [c] y) for { - v_0 := v.Args[0] - if v_0.Op != OpARM64MOVDconst { + x := v.Args[0] + if x.Op != OpARM64SRAconst { + break + } + c := x.AuxInt + y := x.Args[0] + if !(clobberIfDead(x)) { + break + } + v.reset(OpARM64MVNshiftRA) + v.AuxInt = c + v.AddArg(y) + return true + } + return false +} +func rewriteValueARM64_OpARM64MVNshiftLL_0(v *Value) bool { + // match: (MVNshiftLL (MOVDconst [c]) [d]) + // cond: + // result: (MOVDconst [^int64(uint64(c)<>uint64(d))]) + for { + d := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != OpARM64MOVDconst { + break + } + c := v_0.AuxInt + v.reset(OpARM64MOVDconst) + v.AuxInt = ^(c >> uint64(d)) + return true + } + return false +} +func rewriteValueARM64_OpARM64MVNshiftRL_0(v *Value) bool { + // match: (MVNshiftRL (MOVDconst [c]) [d]) + // cond: + // result: (MOVDconst [^int64(uint64(c)>>uint64(d))]) + for { + d := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != OpARM64MOVDconst { + break + } + c := v_0.AuxInt + v.reset(OpARM64MOVDconst) + v.AuxInt = ^int64(uint64(c) >> uint64(d)) + return true + } + return false +} +func rewriteValueARM64_OpARM64NEG_0(v *Value) bool { + // match: (NEG (MUL x y)) + // cond: + // result: (MNEG x y) + for { + v_0 := v.Args[0] + if v_0.Op != OpARM64MUL { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + y := v_0.Args[1] + v.reset(OpARM64MNEG) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (NEG (MULW x y)) + // cond: + // result: (MNEGW x y) + for { + v_0 := v.Args[0] + if v_0.Op != OpARM64MULW { + break + } + _ = v_0.Args[1] + x := v_0.Args[0] + y := v_0.Args[1] + v.reset(OpARM64MNEGW) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (NEG (MOVDconst [c])) + // cond: + // result: (MOVDconst [-c]) + for { + v_0 := v.Args[0] + if v_0.Op != OpARM64MOVDconst { break } c := v_0.AuxInt @@ -20007,6 +20388,111 @@ func rewriteValueARM64_OpARM64NEG_0(v *Value) bool { v.AuxInt = -c return true } + // match: (NEG x:(SLLconst [c] y)) + // cond: clobberIfDead(x) + // result: (NEGshiftLL [c] y) + for { + x := v.Args[0] + if x.Op != OpARM64SLLconst { + break + } + c := x.AuxInt + y := x.Args[0] + if !(clobberIfDead(x)) { + break + } + v.reset(OpARM64NEGshiftLL) + v.AuxInt = c + v.AddArg(y) + return true + } + // match: (NEG x:(SRLconst [c] y)) + // cond: clobberIfDead(x) + // result: (NEGshiftRL [c] y) + for { + x := v.Args[0] + if x.Op != OpARM64SRLconst { + break + } + c := x.AuxInt + y := x.Args[0] + if !(clobberIfDead(x)) { + break + } + v.reset(OpARM64NEGshiftRL) + v.AuxInt = c + v.AddArg(y) + return true + } + // match: (NEG x:(SRAconst [c] y)) + // cond: clobberIfDead(x) + // result: (NEGshiftRA [c] y) + for { + x := v.Args[0] + if x.Op != OpARM64SRAconst { + break + } + c := x.AuxInt + y := x.Args[0] + if !(clobberIfDead(x)) { + break + } + v.reset(OpARM64NEGshiftRA) + v.AuxInt = c + v.AddArg(y) + return true + } + return false +} +func rewriteValueARM64_OpARM64NEGshiftLL_0(v *Value) bool { + // match: (NEGshiftLL (MOVDconst [c]) [d]) + // cond: + // result: (MOVDconst [-int64(uint64(c)<>uint64(d))]) + for { + d := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != OpARM64MOVDconst { + break + } + c := v_0.AuxInt + v.reset(OpARM64MOVDconst) + v.AuxInt = -(c >> uint64(d)) + return true + } + return false +} +func rewriteValueARM64_OpARM64NEGshiftRL_0(v *Value) bool { + // match: (NEGshiftRL (MOVDconst [c]) [d]) + // cond: + // result: (MOVDconst [-int64(uint64(c)>>uint64(d))]) + for { + d := v.AuxInt + v_0 := v.Args[0] + if v_0.Op != OpARM64MOVDconst { + break + } + c := v_0.AuxInt + v.reset(OpARM64MOVDconst) + v.AuxInt = -int64(uint64(c) >> uint64(d)) + return true + } return false } func rewriteValueARM64_OpARM64NotEqual_0(v *Value) bool { @@ -29431,6 +29917,132 @@ func rewriteValueARM64_OpARM64TST_0(v *Value) bool { v.AddArg(x) return true } + // match: (TST x0 x1:(SLLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (TSTshiftLL x0 y [c]) + for { + _ = v.Args[1] + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64TSTshiftLL) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } + // match: (TST x1:(SLLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (TSTshiftLL x0 y [c]) + for { + _ = v.Args[1] + x1 := v.Args[0] + if x1.Op != OpARM64SLLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64TSTshiftLL) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } + // match: (TST x0 x1:(SRLconst [c] y)) + // cond: clobberIfDead(x1) + // result: (TSTshiftRL x0 y [c]) + for { + _ = v.Args[1] + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64TSTshiftRL) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } + // match: (TST x1:(SRLconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (TSTshiftRL x0 y [c]) + for { + _ = v.Args[1] + x1 := v.Args[0] + if x1.Op != OpARM64SRLconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64TSTshiftRL) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } + // match: (TST x0 x1:(SRAconst [c] y)) + // cond: clobberIfDead(x1) + // result: (TSTshiftRA x0 y [c]) + for { + _ = v.Args[1] + x0 := v.Args[0] + x1 := v.Args[1] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64TSTshiftRA) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } + // match: (TST x1:(SRAconst [c] y) x0) + // cond: clobberIfDead(x1) + // result: (TSTshiftRA x0 y [c]) + for { + _ = v.Args[1] + x1 := v.Args[0] + if x1.Op != OpARM64SRAconst { + break + } + c := x1.AuxInt + y := x1.Args[0] + x0 := v.Args[1] + if !(clobberIfDead(x1)) { + break + } + v.reset(OpARM64TSTshiftRA) + v.AuxInt = c + v.AddArg(x0) + v.AddArg(y) + return true + } return false } func rewriteValueARM64_OpARM64TSTW_0(v *Value) bool { @@ -29570,6 +30182,132 @@ func rewriteValueARM64_OpARM64TSTconst_0(v *Value) bool { } return false } +func rewriteValueARM64_OpARM64TSTshiftLL_0(v *Value) bool { + b := v.Block + _ = b + // match: (TSTshiftLL (MOVDconst [c]) x [d]) + // cond: + // result: (TSTconst [c] (SLLconst x [d])) + for { + d := v.AuxInt + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpARM64MOVDconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(OpARM64TSTconst) + v.AuxInt = c + v0 := b.NewValue0(v.Pos, OpARM64SLLconst, x.Type) + v0.AuxInt = d + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (TSTshiftLL x (MOVDconst [c]) [d]) + // cond: + // result: (TSTconst x [int64(uint64(c)< x [d])) + for { + d := v.AuxInt + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpARM64MOVDconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(OpARM64TSTconst) + v.AuxInt = c + v0 := b.NewValue0(v.Pos, OpARM64SRAconst, x.Type) + v0.AuxInt = d + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (TSTshiftRA x (MOVDconst [c]) [d]) + // cond: + // result: (TSTconst x [c>>uint64(d)]) + for { + d := v.AuxInt + _ = v.Args[1] + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpARM64MOVDconst { + break + } + c := v_1.AuxInt + v.reset(OpARM64TSTconst) + v.AuxInt = c >> uint64(d) + v.AddArg(x) + return true + } + return false +} +func rewriteValueARM64_OpARM64TSTshiftRL_0(v *Value) bool { + b := v.Block + _ = b + // match: (TSTshiftRL (MOVDconst [c]) x [d]) + // cond: + // result: (TSTconst [c] (SRLconst x [d])) + for { + d := v.AuxInt + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpARM64MOVDconst { + break + } + c := v_0.AuxInt + x := v.Args[1] + v.reset(OpARM64TSTconst) + v.AuxInt = c + v0 := b.NewValue0(v.Pos, OpARM64SRLconst, x.Type) + v0.AuxInt = d + v0.AddArg(x) + v.AddArg(v0) + return true + } + // match: (TSTshiftRL x (MOVDconst [c]) [d]) + // cond: + // result: (TSTconst x [int64(uint64(c)>>uint64(d))]) + for { + d := v.AuxInt + _ = v.Args[1] + x := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpARM64MOVDconst { + break + } + c := v_1.AuxInt + v.reset(OpARM64TSTconst) + v.AuxInt = int64(uint64(c) >> uint64(d)) + v.AddArg(x) + return true + } + return false +} func rewriteValueARM64_OpARM64UBFIZ_0(v *Value) bool { // match: (UBFIZ [bfc] (SLLconst [sc] x)) // cond: sc < getARM64BFwidth(bfc) diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index 05a28695d4..8e2a210948 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -44,7 +44,7 @@ func Pow2Muls(n1, n2 int) (int, int) { // amd64:"SHLQ\t[$]6",-"IMULQ" // 386:"SHLL\t[$]6",-"IMULL" // arm:"SLL\t[$]6",-"MUL" - // arm64:"LSL\t[$]6",-"MUL" + // arm64:`NEG\sR[0-9]+<<6,\sR[0-9]+`,-`LSL`,-`MUL` b := -64 * n2 return a, b diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go index d5bade97cc..072393f3a6 100644 --- a/test/codegen/comparisons.go +++ b/test/codegen/comparisons.go @@ -183,6 +183,10 @@ func CmpToZero(a, b, d int32, e, f int64) int32 { // arm:`AND`,-`TST` // 386:`ANDL` c6 := a&d >= 0 + // arm64:`TST\sR[0-9]+<<3,\sR[0-9]+` + c7 := e&(f<<3) < 0 + // arm64:`CMN\sR[0-9]+<<3,\sR[0-9]+` + c8 := e+(f<<3) < 0 if c0 { return 1 } else if c1 { @@ -197,6 +201,10 @@ func CmpToZero(a, b, d int32, e, f int64) int32 { return b + d } else if c6 { return a & d + } else if c7 { + return 7 + } else if c8 { + return 8 } else { return 0 }