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).

Built and tested on powerpc64-linux, -m32,-m64 and -mlra,-mno-lra.  Also
tested the new test on powerpc64le-linux (where the test is skipped).
Is this okay for trunk?


Segher


2016-02-24  Segher Boessenkool  <seg...@kernel.crashing.org>

        PR target/69946
        * config/rs6000/rs6000.c (rs6000_insn_for_shift_mask): Print rlwinm
        shift amount using %h.

gcc/testsuite/
        * pr69946.c: New file.

---
 gcc/config/rs6000/rs6000.c                 |  4 ++--
 gcc/testsuite/gcc.target/powerpc/pr69946.c | 38 ++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr69946.c

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 92cc9ee..d5abb98 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -17439,8 +17439,8 @@ rs6000_insn_for_shift_mask (machine_mode mode, rtx 
*operands, bool dot)
       operands[3] = GEN_INT (31 - nb);
       operands[4] = GEN_INT (31 - ne);
       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/gcc.target/powerpc/pr69946.c 
b/gcc/testsuite/gcc.target/powerpc/pr69946.c
new file mode 100644
index 0000000..d5f8bf2
--- /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 } } */
-- 
1.9.3

Reply via email to