mirror of
https://github.com/golang/go
synced 2024-10-02 22:25:08 +00:00
cmd/compile/ssa: fix (MOVWZreg (RLWINM)) folding on PPC64
RLIWNM does not clear the upper 32 bits of the target register if the mask wraps around (e.g 0xF000000F). Don't elide MOVWZreg for such masks. All other usage clears the upper 32 bits. Fixes #67844. Change-Id: I11b89f1da9ae077624369bfe2bf25e9b7c9b79bc Reviewed-on: https://go-review.googlesource.com/c/go/+/590896 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Keith Randall <khr@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
e709992afd
commit
d5e5b14305
|
@ -646,7 +646,7 @@
|
||||||
(MOVBZreg (SRWconst x [s])) && mergePPC64AndSrwi(0xFF,s) != 0 => (RLWINM [mergePPC64AndSrwi(0xFF,s)] x)
|
(MOVBZreg (SRWconst x [s])) && mergePPC64AndSrwi(0xFF,s) != 0 => (RLWINM [mergePPC64AndSrwi(0xFF,s)] x)
|
||||||
(MOVBZreg (RLWINM [r] y)) && mergePPC64AndRlwinm(0xFF,r) != 0 => (RLWINM [mergePPC64AndRlwinm(0xFF,r)] y)
|
(MOVBZreg (RLWINM [r] y)) && mergePPC64AndRlwinm(0xFF,r) != 0 => (RLWINM [mergePPC64AndRlwinm(0xFF,r)] y)
|
||||||
(MOVHZreg (RLWINM [r] y)) && mergePPC64AndRlwinm(0xFFFF,r) != 0 => (RLWINM [mergePPC64AndRlwinm(0xFFFF,r)] y)
|
(MOVHZreg (RLWINM [r] y)) && mergePPC64AndRlwinm(0xFFFF,r) != 0 => (RLWINM [mergePPC64AndRlwinm(0xFFFF,r)] y)
|
||||||
(MOVWZreg (RLWINM [r] y)) && mergePPC64AndRlwinm(0xFFFFFFFF,r) != 0 => (RLWINM [mergePPC64AndRlwinm(0xFFFFFFFF,r)] y)
|
(MOVWZreg (RLWINM [r] y)) && mergePPC64MovwzregRlwinm(r) != 0 => (RLWINM [mergePPC64MovwzregRlwinm(r)] y)
|
||||||
(ANDconst [m] (RLWINM [r] y)) && mergePPC64AndRlwinm(uint32(m),r) != 0 => (RLWINM [mergePPC64AndRlwinm(uint32(m),r)] y)
|
(ANDconst [m] (RLWINM [r] y)) && mergePPC64AndRlwinm(uint32(m),r) != 0 => (RLWINM [mergePPC64AndRlwinm(uint32(m),r)] y)
|
||||||
(SLDconst [s] (RLWINM [r] y)) && mergePPC64SldiRlwinm(s,r) != 0 => (RLWINM [mergePPC64SldiRlwinm(s,r)] y)
|
(SLDconst [s] (RLWINM [r] y)) && mergePPC64SldiRlwinm(s,r) != 0 => (RLWINM [mergePPC64SldiRlwinm(s,r)] y)
|
||||||
(RLWINM [r] (MOVHZreg u)) && mergePPC64RlwinmAnd(r,0xFFFF) != 0 => (RLWINM [mergePPC64RlwinmAnd(r,0xFFFF)] u)
|
(RLWINM [r] (MOVHZreg u)) && mergePPC64RlwinmAnd(r,0xFFFF) != 0 => (RLWINM [mergePPC64RlwinmAnd(r,0xFFFF)] u)
|
||||||
|
|
|
@ -1666,6 +1666,16 @@ func mergePPC64AndRlwinm(mask uint32, rlw int64) int64 {
|
||||||
return encodePPC64RotateMask(r, int64(mask_out), 32)
|
return encodePPC64RotateMask(r, int64(mask_out), 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test if RLWINM opcode rlw clears the upper 32 bits of the
|
||||||
|
// result. Return rlw if it does, 0 otherwise.
|
||||||
|
func mergePPC64MovwzregRlwinm(rlw int64) int64 {
|
||||||
|
_, mb, me, _ := DecodePPC64RotateMask(rlw)
|
||||||
|
if mb > me {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return rlw
|
||||||
|
}
|
||||||
|
|
||||||
// Test if AND feeding into an ANDconst can be merged. Return the encoded RLWINM constant,
|
// Test if AND feeding into an ANDconst can be merged. Return the encoded RLWINM constant,
|
||||||
// or 0 if they cannot be merged.
|
// or 0 if they cannot be merged.
|
||||||
func mergePPC64RlwinmAnd(rlw int64, mask uint32) int64 {
|
func mergePPC64RlwinmAnd(rlw int64, mask uint32) int64 {
|
||||||
|
|
|
@ -10102,19 +10102,19 @@ func rewriteValuePPC64_OpPPC64MOVWZreg(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVWZreg (RLWINM [r] y))
|
// match: (MOVWZreg (RLWINM [r] y))
|
||||||
// cond: mergePPC64AndRlwinm(0xFFFFFFFF,r) != 0
|
// cond: mergePPC64MovwzregRlwinm(r) != 0
|
||||||
// result: (RLWINM [mergePPC64AndRlwinm(0xFFFFFFFF,r)] y)
|
// result: (RLWINM [mergePPC64MovwzregRlwinm(r)] y)
|
||||||
for {
|
for {
|
||||||
if v_0.Op != OpPPC64RLWINM {
|
if v_0.Op != OpPPC64RLWINM {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
r := auxIntToInt64(v_0.AuxInt)
|
r := auxIntToInt64(v_0.AuxInt)
|
||||||
y := v_0.Args[0]
|
y := v_0.Args[0]
|
||||||
if !(mergePPC64AndRlwinm(0xFFFFFFFF, r) != 0) {
|
if !(mergePPC64MovwzregRlwinm(r) != 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpPPC64RLWINM)
|
v.reset(OpPPC64RLWINM)
|
||||||
v.AuxInt = int64ToAuxInt(mergePPC64AndRlwinm(0xFFFFFFFF, r))
|
v.AuxInt = int64ToAuxInt(mergePPC64MovwzregRlwinm(r))
|
||||||
v.AddArg(y)
|
v.AddArg(y)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -394,7 +394,7 @@ func zeroextendAndMask8to64(a int8, b int16) (x, y uint64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify rotate and mask instructions, and further simplified instructions for small types
|
// Verify rotate and mask instructions, and further simplified instructions for small types
|
||||||
func bitRotateAndMask(io64 [4]uint64, io32 [4]uint32, io16 [4]uint16, io8 [4]uint8) {
|
func bitRotateAndMask(io64 [8]uint64, io32 [4]uint32, io16 [4]uint16, io8 [4]uint8) {
|
||||||
// ppc64x: "RLDICR\t[$]0, R[0-9]*, [$]47, R"
|
// ppc64x: "RLDICR\t[$]0, R[0-9]*, [$]47, R"
|
||||||
io64[0] = io64[0] & 0xFFFFFFFFFFFF0000
|
io64[0] = io64[0] & 0xFFFFFFFFFFFF0000
|
||||||
// ppc64x: "RLDICL\t[$]0, R[0-9]*, [$]16, R"
|
// ppc64x: "RLDICL\t[$]0, R[0-9]*, [$]16, R"
|
||||||
|
@ -404,6 +404,9 @@ func bitRotateAndMask(io64 [4]uint64, io32 [4]uint32, io16 [4]uint16, io8 [4]uin
|
||||||
// ppc64x: -"SRD", -"AND", "RLDICL\t[$]36, R[0-9]*, [$]28, R"
|
// ppc64x: -"SRD", -"AND", "RLDICL\t[$]36, R[0-9]*, [$]28, R"
|
||||||
io64[3] = (io64[3] >> 28) & 0x0000FFFFFFFFFFFF
|
io64[3] = (io64[3] >> 28) & 0x0000FFFFFFFFFFFF
|
||||||
|
|
||||||
|
// ppc64x: "MOVWZ", "RLWNM\t[$]1, R[0-9]*, [$]28, [$]3, R"
|
||||||
|
io64[4] = uint64(bits.RotateLeft32(io32[0], 1) & 0xF000000F)
|
||||||
|
|
||||||
// ppc64x: "RLWNM\t[$]0, R[0-9]*, [$]4, [$]19, R"
|
// ppc64x: "RLWNM\t[$]0, R[0-9]*, [$]4, [$]19, R"
|
||||||
io32[0] = io32[0] & 0x0FFFF000
|
io32[0] = io32[0] & 0x0FFFF000
|
||||||
// ppc64x: "RLWNM\t[$]0, R[0-9]*, [$]20, [$]3, R"
|
// ppc64x: "RLWNM\t[$]0, R[0-9]*, [$]20, [$]3, R"
|
||||||
|
|
Loading…
Reference in a new issue