diff --git a/src/cmd/compile/internal/ssa/_gen/PPC64.rules b/src/cmd/compile/internal/ssa/_gen/PPC64.rules index ebd152f578..8bec4895f5 100644 --- a/src/cmd/compile/internal/ssa/_gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/_gen/PPC64.rules @@ -150,14 +150,19 @@ (ANDconst [m] (SRWconst x [s])) && mergePPC64RShiftMask(m,s,32) == 0 => (MOVDconst [0]) (ANDconst [m] (SRWconst x [s])) && mergePPC64AndSrwi(m,s) != 0 => (RLWINM [mergePPC64AndSrwi(m,s)] x) +(ANDconst [m] (SRDconst x [s])) && mergePPC64AndSrdi(m,s) != 0 => (RLWINM [mergePPC64AndSrdi(m,s)] x) (AND (MOVDconst [m]) (SRWconst x [s])) && mergePPC64RShiftMask(m,s,32) == 0 => (MOVDconst [0]) (AND (MOVDconst [m]) (SRWconst x [s])) && mergePPC64AndSrwi(m,s) != 0 => (RLWINM [mergePPC64AndSrwi(m,s)] x) +(AND (MOVDconst [m]) (SRDconst x [s])) && mergePPC64AndSrdi(m,s) != 0 => (RLWINM [mergePPC64AndSrdi(m,s)] x) (SRWconst (ANDconst [m] x) [s]) && mergePPC64RShiftMask(m>>uint(s),s,32) == 0 => (MOVDconst [0]) (SRWconst (ANDconst [m] x) [s]) && mergePPC64AndSrwi(m>>uint(s),s) != 0 => (RLWINM [mergePPC64AndSrwi(m>>uint(s),s)] x) (SRWconst (AND (MOVDconst [m]) x) [s]) && mergePPC64RShiftMask(m>>uint(s),s,32) == 0 => (MOVDconst [0]) (SRWconst (AND (MOVDconst [m]) x) [s]) && mergePPC64AndSrwi(m>>uint(s),s) != 0 => (RLWINM [mergePPC64AndSrwi(m>>uint(s),s)] x) +(ANDconst [m] (SLDconst x [s])) && mergePPC64AndSldi(m,s) != 0 => (RLWINM [mergePPC64AndSldi(m,s)] x) +(AND (MOVDconst [m]) (SLDconst x [s])) && mergePPC64AndSldi(m,s) != 0 => (RLWINM [mergePPC64AndSldi(m,s)] x) + // 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) diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 45eb48ad63..5630bfd729 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1580,6 +1580,36 @@ func mergePPC64AndSrwi(m, s int64) int64 { return encodePPC64RotateMask((32-s)&31, mask, 32) } +// Combine (ANDconst [m] (SRDconst [s])) into (RLWINM [y]) or return 0 +func mergePPC64AndSrdi(m, s int64) int64 { + mask := mergePPC64RShiftMask(m, s, 64) + + // Verify the rotate and mask result only uses the lower 32 bits. + rv := bits.RotateLeft64(0xFFFFFFFF00000000, -int(s)) + if rv&uint64(mask) != 0 { + return 0 + } + if !isPPC64WordRotateMask(mask) { + return 0 + } + return encodePPC64RotateMask((32-s)&31, mask, 32) +} + +// Combine (ANDconst [m] (SLDconst [s])) into (RLWINM [y]) or return 0 +func mergePPC64AndSldi(m, s int64) int64 { + mask := -1 << s & m + + // Verify the rotate and mask result only uses the lower 32 bits. + rv := bits.RotateLeft64(0xFFFFFFFF00000000, int(s)) + if rv&uint64(mask) != 0 { + return 0 + } + if !isPPC64WordRotateMask(mask) { + return 0 + } + return encodePPC64RotateMask(s&31, mask, 32) +} + // 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 { diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index 5f8f2a2c99..9c082c31bf 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -4292,6 +4292,54 @@ func rewriteValuePPC64_OpPPC64AND(v *Value) bool { } break } + // match: (AND (MOVDconst [m]) (SRDconst x [s])) + // cond: mergePPC64AndSrdi(m,s) != 0 + // result: (RLWINM [mergePPC64AndSrdi(m,s)] x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpPPC64MOVDconst { + continue + } + m := auxIntToInt64(v_0.AuxInt) + if v_1.Op != OpPPC64SRDconst { + continue + } + s := auxIntToInt64(v_1.AuxInt) + x := v_1.Args[0] + if !(mergePPC64AndSrdi(m, s) != 0) { + continue + } + v.reset(OpPPC64RLWINM) + v.AuxInt = int64ToAuxInt(mergePPC64AndSrdi(m, s)) + v.AddArg(x) + return true + } + break + } + // match: (AND (MOVDconst [m]) (SLDconst x [s])) + // cond: mergePPC64AndSldi(m,s) != 0 + // result: (RLWINM [mergePPC64AndSldi(m,s)] x) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpPPC64MOVDconst { + continue + } + m := auxIntToInt64(v_0.AuxInt) + if v_1.Op != OpPPC64SLDconst { + continue + } + s := auxIntToInt64(v_1.AuxInt) + x := v_1.Args[0] + if !(mergePPC64AndSldi(m, s) != 0) { + continue + } + v.reset(OpPPC64RLWINM) + v.AuxInt = int64ToAuxInt(mergePPC64AndSldi(m, s)) + v.AddArg(x) + return true + } + break + } // match: (AND x (NOR y y)) // result: (ANDN x y) for { @@ -4510,6 +4558,42 @@ func rewriteValuePPC64_OpPPC64ANDconst(v *Value) bool { v.AddArg(x) return true } + // match: (ANDconst [m] (SRDconst x [s])) + // cond: mergePPC64AndSrdi(m,s) != 0 + // result: (RLWINM [mergePPC64AndSrdi(m,s)] x) + for { + m := auxIntToInt64(v.AuxInt) + if v_0.Op != OpPPC64SRDconst { + break + } + s := auxIntToInt64(v_0.AuxInt) + x := v_0.Args[0] + if !(mergePPC64AndSrdi(m, s) != 0) { + break + } + v.reset(OpPPC64RLWINM) + v.AuxInt = int64ToAuxInt(mergePPC64AndSrdi(m, s)) + v.AddArg(x) + return true + } + // match: (ANDconst [m] (SLDconst x [s])) + // cond: mergePPC64AndSldi(m,s) != 0 + // result: (RLWINM [mergePPC64AndSldi(m,s)] x) + for { + m := auxIntToInt64(v.AuxInt) + if v_0.Op != OpPPC64SLDconst { + break + } + s := auxIntToInt64(v_0.AuxInt) + x := v_0.Args[0] + if !(mergePPC64AndSldi(m, s) != 0) { + break + } + v.reset(OpPPC64RLWINM) + v.AuxInt = int64ToAuxInt(mergePPC64AndSldi(m, s)) + v.AddArg(x) + return true + } // match: (ANDconst [c] (ANDconst [d] x)) // result: (ANDconst [c&d] x) for { diff --git a/test/codegen/shift.go b/test/codegen/shift.go index bc91c61baa..2d8cf86857 100644 --- a/test/codegen/shift.go +++ b/test/codegen/shift.go @@ -462,12 +462,6 @@ func checkMergedShifts64(a [256]uint32, b [256]uint64, c [256]byte, v uint64) { 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[6] = 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]+" @@ -476,7 +470,7 @@ func checkMergedShifts64(a [256]uint32, b [256]uint64, c [256]byte, v uint64) { b[2] = b[((uint64((uint32(v) >> 21)) & 0x3f) << 4)] // ppc64x: "RLWNM\t[$]11, R[0-9]+, [$]10, [$]15" c[0] = c[((v>>5)&0x3F)<<16] - // ppc64x: "RLWNM\t[$]0, R[0-9]+, [$]19, [$]24" + // ppc64x: "ANDCC\t[$]8064," c[1] = c[((v>>7)&0x3F)<<7] }