From 1846dd5a318f1abd293c9cd54c868b7e288f1d26 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Thu, 24 Oct 2024 09:08:47 -0500 Subject: [PATCH] cmd/compile/internal/ssa: fix PPC64 shift codegen regression CL 621357 introduced new generic lowering rules which caused several shift related codegen test failures. Add new rules to fix the test regressions, and cleanup tests which are changed but not regressed. Some CLRLSLDI tests are removed as they are no test CLRLSLDI rules. Fixes #70003 Change-Id: I1ecc5a7e63ab709a4a0cebf11fa078d5cf164034 Reviewed-on: https://go-review.googlesource.com/c/go/+/622236 Reviewed-by: Keith Randall Reviewed-by: Cherry Mui Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI --- src/cmd/compile/internal/ssa/_gen/PPC64.rules | 5 ++ src/cmd/compile/internal/ssa/rewrite.go | 30 +++++++ src/cmd/compile/internal/ssa/rewritePPC64.go | 84 +++++++++++++++++++ test/codegen/shift.go | 8 +- 4 files changed, 120 insertions(+), 7 deletions(-) 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] } -- 2.48.1