aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSegher Boessenkool <segher@kernel.crashing.org>2016-02-26 19:49:18 +0100
committerSegher Boessenkool <segher@gcc.gnu.org>2016-02-26 19:49:18 +0100
commitd1f2bea53f8990253f655cfa22815046efb2ed87 (patch)
treea2ab31b8e1412e6c8eac442b1a4af5a6c6090a3e
parent4a4f9d2bf86ef5f48d45ad39802d34dc349f6509 (diff)
downloadgcc-d1f2bea53f8990253f655cfa22815046efb2ed87.zip
gcc-d1f2bea53f8990253f655cfa22815046efb2ed87.tar.gz
gcc-d1f2bea53f8990253f655cfa22815046efb2ed87.tar.bz2
powerpc: Handle DImode rotatert implemented with rlwinm (PR69946)
Some DImode rotate-right-and-mask can be implemented best with a rlwinm instruction: those that could be a lshiftrt instead of a rotatert, while the mask is not right-aligned. Why the rotate in the testcase is not optimised to a plain shift is another question, but we need to handle it here anyway. We compute the shift amount for a 64-bit rotate. This is 32 too high in this case; if we print using %h that is masked out (and this doesn't silently let through invalid instructions, everything is checked by rs6000_is_valid_shift_mask which is much more thorough). PR target/69946 * config/rs6000/rs6000.c (rs6000_insn_for_shift_mask): Print rlwinm shift amount using %h. Add comment. gcc/testsuite/ * gcc.target/powerpc/pr69946.c: New file. From-SVN: r233755
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/rs6000/rs6000.c7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr69946.c38
4 files changed, 54 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6344092..89f483c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2016-02-26 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/69946
+ * config/rs6000/rs6000.c (rs6000_insn_for_shift_mask): Print rlwinm
+ shift amount using %h. Add comment.
+
2016-02-26 Richard Biener <rguenther@suse.de>
Jeff Law <law@redhat.com>
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index eed50f4..c7bad3f 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -17438,9 +17438,12 @@ rs6000_insn_for_shift_mask (machine_mode mode, rtx *operands, bool dot)
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
operands[3] = GEN_INT (31 - nb);
operands[4] = GEN_INT (31 - ne);
+ /* This insn can also be a 64-bit rotate with mask that really makes
+ it just a shift right (with mask); the %h below are to adjust for
+ that situation (shift count is >= 32 in that case). */
if (dot)
- return "rlw%I2nm. %0,%1,%2,%3,%4";
- return "rlw%I2nm %0,%1,%2,%3,%4";
+ return "rlw%I2nm. %0,%1,%h2,%3,%4";
+ return "rlw%I2nm %0,%1,%h2,%3,%4";
}
gcc_unreachable ();
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 316720b..69289cc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-02-26 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/69946
+ * gcc.target/powerpc/pr69946.c: New file.
+
2016-02-26 Richard Biener <rguenther@suse.de>
Jeff Law <law@redhat.com>
diff --git a/gcc/testsuite/gcc.target/powerpc/pr69946.c b/gcc/testsuite/gcc.target/powerpc/pr69946.c
new file mode 100644
index 0000000..eb0c365
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr69946.c
@@ -0,0 +1,38 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc_elfv2 } } */
+/* { dg-options "-O2" } */
+
+/* This generates a rotate:DI by 44, with mask 0xf00, which is implemented
+ using a rlwinm instruction. We used to write 44 for the shift count
+ there; it should be 12. */
+
+struct A
+{
+ int a : 4;
+ int : 2;
+ int b : 2;
+ int : 2;
+ int c : 2;
+ int d : 1;
+ int e;
+};
+struct B
+{
+ int a : 4;
+} *a;
+void bar (struct A);
+
+void
+foo (void)
+{
+ struct B b = a[0];
+ struct A c;
+ c.a = b.a;
+ c.b = 1;
+ c.c = 1;
+ c.d = 0;
+ bar (c);
+}
+
+/* { dg-final { scan-assembler-not {(?n)rlwinm.*,44,20,23} } } */
+/* { dg-final { scan-assembler-times {(?n)rlwinm.*,12,20,23} 1 } } */