aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/compile/internal/ssa/_gen/PPC64.rules1
-rw-r--r--src/cmd/compile/internal/ssa/rewrite.go27
-rw-r--r--src/cmd/compile/internal/ssa/rewritePPC64.go18
-rw-r--r--test/codegen/shift.go21
4 files changed, 66 insertions, 1 deletions
diff --git a/src/cmd/compile/internal/ssa/_gen/PPC64.rules b/src/cmd/compile/internal/ssa/_gen/PPC64.rules
index 7518119147..f0cb23ba9f 100644
--- a/src/cmd/compile/internal/ssa/_gen/PPC64.rules
+++ b/src/cmd/compile/internal/ssa/_gen/PPC64.rules
@@ -158,6 +158,7 @@
// Merge shift right + shift left and clear left (e.g for a table lookup)
(CLRLSLDI [c] (SRWconst [s] x)) && mergePPC64ClrlsldiSrw(int64(c),s) != 0 => (RLWINM [mergePPC64ClrlsldiSrw(int64(c),s)] x)
+(CLRLSLDI [c] (SRDconst [s] x)) && mergePPC64ClrlsldiSrd(int64(c),s) != 0 => (RLWINM [mergePPC64ClrlsldiSrd(int64(c),s)] x)
(SLDconst [l] (SRWconst [r] x)) && mergePPC64SldiSrw(l,r) != 0 => (RLWINM [mergePPC64SldiSrw(l,r)] x)
// The following reduction shows up frequently too. e.g b[(x>>14)&0xFF]
(CLRLSLDI [c] i:(RLWINM [s] x)) && mergePPC64ClrlsldiRlwinm(c,s) != 0 => (RLWINM [mergePPC64ClrlsldiRlwinm(c,s)] x)
diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go
index 9961b540b7..4e4d99af0b 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 {
diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go
index 4ac5eec073..266ac14c38 100644
--- a/src/cmd/compile/internal/ssa/rewritePPC64.go
+++ b/src/cmd/compile/internal/ssa/rewritePPC64.go
@@ -4628,6 +4628,24 @@ func rewriteValuePPC64_OpPPC64CLRLSLDI(v *Value) bool {
v.AddArg(x)
return true
}
+ // match: (CLRLSLDI [c] (SRDconst [s] x))
+ // cond: mergePPC64ClrlsldiSrd(int64(c),s) != 0
+ // result: (RLWINM [mergePPC64ClrlsldiSrd(int64(c),s)] x)
+ for {
+ c := auxIntToInt32(v.AuxInt)
+ if v_0.Op != OpPPC64SRDconst {
+ break
+ }
+ s := auxIntToInt64(v_0.AuxInt)
+ x := v_0.Args[0]
+ if !(mergePPC64ClrlsldiSrd(int64(c), s) != 0) {
+ break
+ }
+ v.reset(OpPPC64RLWINM)
+ v.AuxInt = int64ToAuxInt(mergePPC64ClrlsldiSrd(int64(c), s))
+ v.AddArg(x)
+ return true
+ }
// match: (CLRLSLDI [c] i:(RLWINM [s] x))
// cond: mergePPC64ClrlsldiRlwinm(c,s) != 0
// result: (RLWINM [mergePPC64ClrlsldiRlwinm(c,s)] x)
diff --git a/test/codegen/shift.go b/test/codegen/shift.go
index 50d60426d0..5bd7acc063 100644
--- a/test/codegen/shift.go
+++ b/test/codegen/shift.go
@@ -453,6 +453,27 @@ func checkMergedShifts32(a [256]uint32, b [256]uint64, u uint32, v uint32) {
b[2] = b[v>>25]
}
+func checkMergedShifts64(a [256]uint32, b [256]uint64, v uint64) {
+ // ppc64x: -"CLRLSLDI", "RLWNM\t[$]10, R[0-9]+, [$]22, [$]29, R[0-9]+"
+ a[0] = a[uint8(v>>24)]
+ // ppc64x: "SRD", "CLRLSLDI", -"RLWNM"
+ a[1] = a[uint8(v>>25)]
+ // ppc64x: -"CLRLSLDI", "RLWNM\t[$]9, R[0-9]+, [$]23, [$]29, R[0-9]+"
+ a[2] = a[v>>25&0x7F]
+ // ppc64x: -"CLRLSLDI", "RLWNM\t[$]3, R[0-9]+, [$]29, [$]29, R[0-9]+"
+ a[3] = a[(v>>31)&0x01]
+ // ppc64x: "SRD", "CLRLSLDI", -"RLWNM"
+ a[4] = a[(v>>30)&0x07]
+ // ppc64x: "SRD", "CLRLSLDI", -"RLWNM"
+ a[5] = a[(v>>32)&0x01]
+ // ppc64x: "SRD", "CLRLSLDI", -"RLWNM"
+ a[5] = a[(v>>34)&0x03]
+ // ppc64x: -"CLRLSLDI", "RLWNM\t[$]12, R[0-9]+, [$]21, [$]28, R[0-9]+"
+ b[0] = b[uint8(v>>23)]
+ // ppc64x: -"CLRLSLDI", "RLWNM\t[$]15, R[0-9]+, [$]21, [$]28, R[0-9]+"
+ b[1] = b[(v>>20)&0xFF]
+}
+
// 128 bit shifts
func check128bitShifts(x, y uint64, bits uint) (uint64, uint64) {