mirror of https://github.com/golang/go.git
cmd/compile: merge zero/sign extensions with UBFX/SBFX on arm64
The UBFX and SBFX already zero/sign extend the result. Further zero/sign extensions are thus unnecessary as long as they leave the top bits unaltered. This patch absorbs zero/sign extensions into UBFX/SBFX. Add the related test cases. Change-Id: I7c4516c8b52d677f77bf3aaedab87c4a28056ec0 Reviewed-on: https://go-review.googlesource.com/c/go/+/265039 Trust: fannie zhang <Fannie.Zhang@arm.com> Trust: Keith Randall <khr@golang.org> Run-TryBot: fannie zhang <Fannie.Zhang@arm.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
7619a4528d
commit
43b05173a2
|
|
@ -1834,6 +1834,10 @@
|
||||||
(SRAconst [rc] (MOVWreg x)) && rc < 32 => (SBFX [armBFAuxInt(rc, 32-rc)] x)
|
(SRAconst [rc] (MOVWreg x)) && rc < 32 => (SBFX [armBFAuxInt(rc, 32-rc)] x)
|
||||||
(SRAconst [rc] (MOVHreg x)) && rc < 16 => (SBFX [armBFAuxInt(rc, 16-rc)] x)
|
(SRAconst [rc] (MOVHreg x)) && rc < 16 => (SBFX [armBFAuxInt(rc, 16-rc)] x)
|
||||||
(SRAconst [rc] (MOVBreg x)) && rc < 8 => (SBFX [armBFAuxInt(rc, 8-rc)] x)
|
(SRAconst [rc] (MOVBreg x)) && rc < 8 => (SBFX [armBFAuxInt(rc, 8-rc)] x)
|
||||||
|
// merge sbfx and sign-extension into sbfx
|
||||||
|
(MOVWreg (SBFX [bfc] x)) && bfc.getARM64BFwidth() <= 32 => (SBFX [bfc] x)
|
||||||
|
(MOVHreg (SBFX [bfc] x)) && bfc.getARM64BFwidth() <= 16 => (SBFX [bfc] x)
|
||||||
|
(MOVBreg (SBFX [bfc] x)) && bfc.getARM64BFwidth() <= 8 => (SBFX [bfc] x)
|
||||||
|
|
||||||
// sbfiz/sbfx combinations: merge shifts into bitfield ops
|
// sbfiz/sbfx combinations: merge shifts into bitfield ops
|
||||||
(SRAconst [sc] (SBFIZ [bfc] x)) && sc < bfc.getARM64BFlsb()
|
(SRAconst [sc] (SBFIZ [bfc] x)) && sc < bfc.getARM64BFlsb()
|
||||||
|
|
@ -1880,6 +1884,11 @@
|
||||||
// (x << lc) >> rc
|
// (x << lc) >> rc
|
||||||
(SRLconst [rc] (SLLconst [lc] x)) && lc < rc => (UBFX [armBFAuxInt(rc-lc, 64-rc)] x)
|
(SRLconst [rc] (SLLconst [lc] x)) && lc < rc => (UBFX [armBFAuxInt(rc-lc, 64-rc)] x)
|
||||||
|
|
||||||
|
// merge ubfx and zerso-extension into ubfx
|
||||||
|
(MOVWUreg (UBFX [bfc] x)) && bfc.getARM64BFwidth() <= 32 => (UBFX [bfc] x)
|
||||||
|
(MOVHUreg (UBFX [bfc] x)) && bfc.getARM64BFwidth() <= 16 => (UBFX [bfc] x)
|
||||||
|
(MOVBUreg (UBFX [bfc] x)) && bfc.getARM64BFwidth() <= 8 => (UBFX [bfc] x)
|
||||||
|
|
||||||
// ubfiz/ubfx combinations: merge shifts into bitfield ops
|
// ubfiz/ubfx combinations: merge shifts into bitfield ops
|
||||||
(SRLconst [sc] (UBFX [bfc] x)) && sc < bfc.getARM64BFwidth()
|
(SRLconst [sc] (UBFX [bfc] x)) && sc < bfc.getARM64BFwidth()
|
||||||
=> (UBFX [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth()-sc)] x)
|
=> (UBFX [armBFAuxInt(bfc.getARM64BFlsb()+sc, bfc.getARM64BFwidth()-sc)] x)
|
||||||
|
|
|
||||||
|
|
@ -7187,6 +7187,23 @@ func rewriteValueARM64_OpARM64MOVBUreg(v *Value) bool {
|
||||||
v.AddArg(x)
|
v.AddArg(x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (MOVBUreg (UBFX [bfc] x))
|
||||||
|
// cond: bfc.getARM64BFwidth() <= 8
|
||||||
|
// result: (UBFX [bfc] x)
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64UBFX {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
bfc := auxIntToArm64BitField(v_0.AuxInt)
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if !(bfc.getARM64BFwidth() <= 8) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64UBFX)
|
||||||
|
v.AuxInt = arm64BitFieldToAuxInt(bfc)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpARM64MOVBload(v *Value) bool {
|
func rewriteValueARM64_OpARM64MOVBload(v *Value) bool {
|
||||||
|
|
@ -7401,6 +7418,23 @@ func rewriteValueARM64_OpARM64MOVBreg(v *Value) bool {
|
||||||
v.AddArg(x)
|
v.AddArg(x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (MOVBreg (SBFX [bfc] x))
|
||||||
|
// cond: bfc.getARM64BFwidth() <= 8
|
||||||
|
// result: (SBFX [bfc] x)
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64SBFX {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
bfc := auxIntToArm64BitField(v_0.AuxInt)
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if !(bfc.getARM64BFwidth() <= 8) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64SBFX)
|
||||||
|
v.AuxInt = arm64BitFieldToAuxInt(bfc)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpARM64MOVBstore(v *Value) bool {
|
func rewriteValueARM64_OpARM64MOVBstore(v *Value) bool {
|
||||||
|
|
@ -10699,6 +10733,23 @@ func rewriteValueARM64_OpARM64MOVHUreg(v *Value) bool {
|
||||||
v.AddArg(x)
|
v.AddArg(x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (MOVHUreg (UBFX [bfc] x))
|
||||||
|
// cond: bfc.getARM64BFwidth() <= 16
|
||||||
|
// result: (UBFX [bfc] x)
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64UBFX {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
bfc := auxIntToArm64BitField(v_0.AuxInt)
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if !(bfc.getARM64BFwidth() <= 16) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64UBFX)
|
||||||
|
v.AuxInt = arm64BitFieldToAuxInt(bfc)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpARM64MOVHload(v *Value) bool {
|
func rewriteValueARM64_OpARM64MOVHload(v *Value) bool {
|
||||||
|
|
@ -11096,6 +11147,23 @@ func rewriteValueARM64_OpARM64MOVHreg(v *Value) bool {
|
||||||
v.AddArg(x)
|
v.AddArg(x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (MOVHreg (SBFX [bfc] x))
|
||||||
|
// cond: bfc.getARM64BFwidth() <= 16
|
||||||
|
// result: (SBFX [bfc] x)
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64SBFX {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
bfc := auxIntToArm64BitField(v_0.AuxInt)
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if !(bfc.getARM64BFwidth() <= 16) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64SBFX)
|
||||||
|
v.AuxInt = arm64BitFieldToAuxInt(bfc)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpARM64MOVHstore(v *Value) bool {
|
func rewriteValueARM64_OpARM64MOVHstore(v *Value) bool {
|
||||||
|
|
@ -12811,6 +12879,23 @@ func rewriteValueARM64_OpARM64MOVWUreg(v *Value) bool {
|
||||||
v.AddArg(x)
|
v.AddArg(x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (MOVWUreg (UBFX [bfc] x))
|
||||||
|
// cond: bfc.getARM64BFwidth() <= 32
|
||||||
|
// result: (UBFX [bfc] x)
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64UBFX {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
bfc := auxIntToArm64BitField(v_0.AuxInt)
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if !(bfc.getARM64BFwidth() <= 32) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64UBFX)
|
||||||
|
v.AuxInt = arm64BitFieldToAuxInt(bfc)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpARM64MOVWload(v *Value) bool {
|
func rewriteValueARM64_OpARM64MOVWload(v *Value) bool {
|
||||||
|
|
@ -13266,6 +13351,23 @@ func rewriteValueARM64_OpARM64MOVWreg(v *Value) bool {
|
||||||
v.AddArg(x)
|
v.AddArg(x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (MOVWreg (SBFX [bfc] x))
|
||||||
|
// cond: bfc.getARM64BFwidth() <= 32
|
||||||
|
// result: (SBFX [bfc] x)
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpARM64SBFX {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
bfc := auxIntToArm64BitField(v_0.AuxInt)
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if !(bfc.getARM64BFwidth() <= 32) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpARM64SBFX)
|
||||||
|
v.AuxInt = arm64BitFieldToAuxInt(bfc)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueARM64_OpARM64MOVWstore(v *Value) bool {
|
func rewriteValueARM64_OpARM64MOVWstore(v *Value) bool {
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,12 @@ func sbfx6(x int32) int32 {
|
||||||
return (x << 3) >> 4 // arm64:"SBFX\t[$]1, R[0-9]+, [$]28",-"LSL",-"ASR"
|
return (x << 3) >> 4 // arm64:"SBFX\t[$]1, R[0-9]+, [$]28",-"LSL",-"ASR"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// merge sbfx and sign-extension into sbfx.
|
||||||
|
func sbfx7(x int32) int64 {
|
||||||
|
c := x + 5
|
||||||
|
return int64(c >> 20) // arm64"SBFX\t[$]20, R[0-9]+, [$]12",-"MOVW\tR[0-9]+, R[0-9]+"
|
||||||
|
}
|
||||||
|
|
||||||
// ubfiz
|
// ubfiz
|
||||||
func ubfiz1(x uint64) uint64 {
|
func ubfiz1(x uint64) uint64 {
|
||||||
// arm64:"UBFIZ\t[$]3, R[0-9]+, [$]12",-"LSL",-"AND"
|
// arm64:"UBFIZ\t[$]3, R[0-9]+, [$]12",-"LSL",-"AND"
|
||||||
|
|
@ -237,6 +243,16 @@ func ubfx11(x uint64) uint64 {
|
||||||
return ((x & 0xfffff) << 3) >> 4
|
return ((x & 0xfffff) << 3) >> 4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// merge ubfx and zero-extension into ubfx.
|
||||||
|
func ubfx12(x uint64) bool {
|
||||||
|
midr := x + 10
|
||||||
|
part_num := uint16((midr >> 4) & 0xfff)
|
||||||
|
if part_num == 0xd0c { // arm64:"UBFX\t[$]4, R[0-9]+, [$]12",-"MOVHU\tR[0-9]+, R[0-9]+"
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Check that we don't emit comparisons for constant shifts.
|
// Check that we don't emit comparisons for constant shifts.
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func shift_no_cmp(x int) int {
|
func shift_no_cmp(x int) int {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue