diff options
Diffstat (limited to 'src/cmd/compile/internal/ssa/rewrite.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/rewrite.go | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 9961b540b7..f9566368c0 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1589,7 +1589,7 @@ func mergePPC64AndSrwi(m, s int64) int64 { return encodePPC64RotateMask((32-s)&31, mask, 32) } -// Test if a shift right feeding into a CLRLSLDI can be merged into RLWINM. +// Test if a word shift right feeding into a CLRLSLDI can be merged into RLWINM. // Return the encoded RLWINM constant, or 0 if they cannot be merged. func mergePPC64ClrlsldiSrw(sld, srw int64) int64 { mask_1 := uint64(0xFFFFFFFF >> uint(srw)) @@ -1609,6 +1609,31 @@ func mergePPC64ClrlsldiSrw(sld, srw int64) int64 { return encodePPC64RotateMask(int64(r_3), int64(mask_3), 32) } +// Test if a doubleword shift right feeding into a CLRLSLDI can be merged into RLWINM. +// Return the encoded RLWINM constant, or 0 if they cannot be merged. +func mergePPC64ClrlsldiSrd(sld, srd int64) int64 { + mask_1 := uint64(0xFFFFFFFFFFFFFFFF) >> uint(srd) + // for CLRLSLDI, it's more convenient to think of it as a mask left bits then rotate left. + mask_2 := uint64(0xFFFFFFFFFFFFFFFF) >> uint(GetPPC64Shiftmb(int64(sld))) + + // Rewrite mask to apply after the final left shift. + mask_3 := (mask_1 & mask_2) << uint(GetPPC64Shiftsh(sld)) + + r_1 := 64 - srd + r_2 := GetPPC64Shiftsh(sld) + r_3 := (r_1 + r_2) & 63 // This can wrap. + + if uint64(uint32(mask_3)) != mask_3 || mask_3 == 0 { + return 0 + } + // This combine only works when selecting and shifting the lower 32 bits. + v1 := bits.RotateLeft64(0xFFFFFFFF00000000, int(r_3)) + if v1&mask_3 != 0 { + return 0 + } + return encodePPC64RotateMask(int64(r_3-32), int64(mask_3), 32) +} + // Test if a RLWINM feeding into a CLRLSLDI can be merged into RLWINM. Return // the encoded RLWINM constant, or 0 if they cannot be merged. func mergePPC64ClrlsldiRlwinm(sld int32, rlw int64) int64 { @@ -1628,6 +1653,56 @@ func mergePPC64ClrlsldiRlwinm(sld int32, rlw int64) int64 { return encodePPC64RotateMask(r_3, int64(mask_3), 32) } +// Test if RLWINM feeding into an ANDconst can be merged. Return the encoded RLWINM constant, +// or 0 if they cannot be merged. +func mergePPC64AndRlwinm(mask uint32, rlw int64) int64 { + r, _, _, mask_rlw := DecodePPC64RotateMask(rlw) + mask_out := (mask_rlw & uint64(mask)) + + // Verify the result is still a valid bitmask of <= 32 bits. + if !isPPC64WordRotateMask(int64(mask_out)) { + return 0 + } + return encodePPC64RotateMask(r, int64(mask_out), 32) +} + +// Test if AND feeding into an ANDconst can be merged. Return the encoded RLWINM constant, +// or 0 if they cannot be merged. +func mergePPC64RlwinmAnd(rlw int64, mask uint32) int64 { + r, _, _, mask_rlw := DecodePPC64RotateMask(rlw) + + // Rotate the input mask, combine with the rlwnm mask, and test if it is still a valid rlwinm mask. + r_mask := bits.RotateLeft32(mask, int(r)) + + mask_out := (mask_rlw & uint64(r_mask)) + + // Verify the result is still a valid bitmask of <= 32 bits. + if !isPPC64WordRotateMask(int64(mask_out)) { + return 0 + } + return encodePPC64RotateMask(r, int64(mask_out), 32) +} + +// Test if RLWINM feeding into SRDconst can be merged. Return the encoded RLIWNM constant, +// or 0 if they cannot be merged. +func mergePPC64SldiRlwinm(sldi, rlw int64) int64 { + r_1, mb, me, mask_1 := DecodePPC64RotateMask(rlw) + if mb > me || mb < sldi { + // Wrapping masks cannot be merged as the upper 32 bits are effectively undefined in this case. + // Likewise, if mb is less than the shift amount, it cannot be merged. + return 0 + } + // combine the masks, and adjust for the final left shift. + mask_3 := mask_1 << sldi + r_3 := (r_1 + sldi) & 31 // This can wrap. + + // Verify the result is still a valid bitmask of <= 32 bits. + if uint64(uint32(mask_3)) != mask_3 { + return 0 + } + return encodePPC64RotateMask(r_3, int64(mask_3), 32) +} + // Compute the encoded RLWINM constant from combining (SLDconst [sld] (SRWconst [srw] x)), // or return 0 if they cannot be combined. func mergePPC64SldiSrw(sld, srw int64) int64 { |