We couldn't generate ROR (preferred alias of EXTR when both source
registers are the same) for AArch64, when rotating by an immediate,
... until now!

This patch includes the pattern and a test.

Full regression testing for Linux and bare-metal passed.

OK for trunk stage-1?

Thanks,
Ian


2013-03-14  Ian Bolton  <ian.bol...@arm.com>

gcc/
        * config/aarch64/aarch64.md (*ror<mode>3_insn): New pattern.
        (*rorsi3_insn_uxtw): Likewise.

testsuite/
        * gcc.target/aarch64/ror.c: New test.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index ef1c0f3..367c0e3 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -2731,6 +2731,34 @@
    (set_attr "mode" "SI")]
 )
 
+(define_insn "*ror<mode>3_insn"
+  [(set (match_operand:GPI 0 "register_operand" "=r")
+       (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
+                   (match_operand 2 "const_int_operand" "n")))]
+  "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
+{
+  operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
+  return "ror\\t%<w>0, %<w>1, %3";
+}
+  [(set_attr "v8type" "shift")
+   (set_attr "mode" "<MODE>")]
+)
+
+;; zero_extend version of the above
+(define_insn "*rorsi3_insn_uxtw"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+        (rotate:SI (match_operand:SI 1 "register_operand" "r")
+                   (match_operand 2 "const_int_operand" "n"))))]
+  "UINTVAL (operands[2]) < 32"
+{
+  operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
+  return "ror\\t%w0, %w1, %3";
+}
+  [(set_attr "v8type" "shift")
+   (set_attr "mode" "SI")]
+)
+
 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
   [(set (match_operand:GPI 0 "register_operand" "=r")
        (ANY_EXTEND:GPI
diff --git a/gcc/testsuite/gcc.target/aarch64/ror.c 
b/gcc/testsuite/gcc.target/aarch64/ror.c
new file mode 100644
index 0000000..4d266f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ror.c
@@ -0,0 +1,34 @@
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-do run } */
+
+extern void abort (void);
+
+int
+test_si (int a)
+{
+  /* { dg-final { scan-assembler "ror\tw\[0-9\]+, w\[0-9\]+, 27\n" } } */
+  return (a << 5) | ((unsigned int) a >> 27);
+}
+
+long long
+test_di (long long a)
+{
+  /* { dg-final { scan-assembler "ror\tx\[0-9\]+, x\[0-9\]+, 45\n" } } */
+  return (a << 19) | ((unsigned long long) a >> 45);
+}
+
+int
+main ()
+{
+  int v;
+  long long w;
+  v = test_si (0x0203050);
+  if (v != 0x4060a00)
+    abort();
+  w = test_di (0x0000020506010304ll);
+  if (w != 0x1028300818200000ll)
+    abort();
+  return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */

Reply via email to