From 7b69ddc171938b8321a535dd79b8ca2ba56ac72d Mon Sep 17 00:00:00 2001 From: fanzha02 Date: Mon, 6 Sep 2021 11:15:30 +0800 Subject: [PATCH] cmd/compile: merge sign extension and shift into SBFIZ This patch adds some rules to rewrite "(LeftShift (SignExtend x) lc)" expression as "SBFIZ". Add the test cases. Change-Id: I294c4ba09712eeb02c7a952447bb006780f1e60d Reviewed-on: https://go-review.googlesource.com/c/go/+/267602 Trust: fannie zhang Trust: Cherry Mui Run-TryBot: fannie zhang TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/gen/ARM64.rules | 4 ++ src/cmd/compile/internal/ssa/rewriteARM64.go | 39 ++++++++++++++++++++ test/codegen/bitfield.go | 12 ++++++ 3 files changed, 55 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 3b8f8fa457..b44c8b826b 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1827,6 +1827,10 @@ (MOVWreg (SLLconst [lc] x)) && lc < 32 => (SBFIZ [armBFAuxInt(lc, 32-lc)] x) (MOVHreg (SLLconst [lc] x)) && lc < 16 => (SBFIZ [armBFAuxInt(lc, 16-lc)] x) (MOVBreg (SLLconst [lc] x)) && lc < 8 => (SBFIZ [armBFAuxInt(lc, 8-lc)] x) +// int64(x) << lc +(SLLconst [lc] (MOVWreg x)) => (SBFIZ [armBFAuxInt(lc, min(32, 64-lc))] x) +(SLLconst [lc] (MOVHreg x)) => (SBFIZ [armBFAuxInt(lc, min(16, 64-lc))] x) +(SLLconst [lc] (MOVBreg x)) => (SBFIZ [armBFAuxInt(lc, min(8, 64-lc))] x) // sbfx // (x << lc) >> rc diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 0d5265e011..f9175e92fd 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -20087,6 +20087,45 @@ func rewriteValueARM64_OpARM64SLLconst(v *Value) bool { v.AddArg(x) return true } + // match: (SLLconst [lc] (MOVWreg x)) + // result: (SBFIZ [armBFAuxInt(lc, min(32, 64-lc))] x) + for { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVWreg { + break + } + x := v_0.Args[0] + v.reset(OpARM64SBFIZ) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(32, 64-lc))) + v.AddArg(x) + return true + } + // match: (SLLconst [lc] (MOVHreg x)) + // result: (SBFIZ [armBFAuxInt(lc, min(16, 64-lc))] x) + for { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVHreg { + break + } + x := v_0.Args[0] + v.reset(OpARM64SBFIZ) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(16, 64-lc))) + v.AddArg(x) + return true + } + // match: (SLLconst [lc] (MOVBreg x)) + // result: (SBFIZ [armBFAuxInt(lc, min(8, 64-lc))] x) + for { + lc := auxIntToInt64(v.AuxInt) + if v_0.Op != OpARM64MOVBreg { + break + } + x := v_0.Args[0] + v.reset(OpARM64SBFIZ) + v.AuxInt = arm64BitFieldToAuxInt(armBFAuxInt(lc, min(8, 64-lc))) + v.AddArg(x) + return true + } // match: (SLLconst [sc] (ANDconst [ac] x)) // cond: isARM64BFMask(sc, ac, 0) // result: (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x) diff --git a/test/codegen/bitfield.go b/test/codegen/bitfield.go index 6c66e3ab6d..d4ffbad85d 100644 --- a/test/codegen/bitfield.go +++ b/test/codegen/bitfield.go @@ -99,6 +99,18 @@ func sbfiz5(x int32) int32 { return (x << 4) >> 3 } +func sbfiz5(x int32) int64 { + return int64(x+1) << 40 // arm64:"SBFIZ\t[$]40, R[0-9]+, [$]24",-"LSL" +} + +func sbfiz6(x int16) int64 { + return int64(x+1) << 3 // arm64:"SBFIZ\t[$]3, R[0-9]+, [$]16",-"LSL" +} + +func sbfiz7(x int8) int64 { + return int64(x+1) << 62 // arm64:"SBFIZ\t[$]62, R[0-9]+, [$]2",-"LSL" +} + // sbfx func sbfx1(x int64) int64 { return (x << 3) >> 4 // arm64:"SBFX\t[$]1, R[0-9]+, [$]60",-"LSL",-"ASR" -- 2.50.0