We couldn't generate EXTR for AArch64 ... 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 (*extr<mode>5_insn): New pattern.
        (*extrsi5_insn_uxtw): Likewise.

testsuite/
        * gcc.target/aarch64/extr.c: New test.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 73d86a7..ef1c0f3 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -2703,6 +2703,34 @@
    (set_attr "mode" "<MODE>")]
 )
 
+(define_insn "*extr<mode>5_insn"
+  [(set (match_operand:GPI 0 "register_operand" "=r")
+       (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
+                            (match_operand 3 "const_int_operand" "n"))
+                (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
+                              (match_operand 4 "const_int_operand" "n"))))]
+  "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
+   (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE 
(<MODE>mode))"
+  "extr\\t%<w>0, %<w>1, %<w>2, %4"
+  [(set_attr "v8type" "shift")
+   (set_attr "mode" "<MODE>")]
+)
+
+;; zero_extend version of the above
+(define_insn "*extrsi5_insn_uxtw"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+        (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+                           (match_operand 3 "const_int_operand" "n"))
+                (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
+                             (match_operand 4 "const_int_operand" "n")))))]
+  "UINTVAL (operands[3]) < 32 &&
+   (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
+  "extr\\t%w0, %w1, %w2, %4"
+  [(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/extr.c 
b/gcc/testsuite/gcc.target/aarch64/extr.c
new file mode 100644
index 0000000..a78dd8d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/extr.c
@@ -0,0 +1,34 @@
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-do run } */
+
+extern void abort (void);
+
+int
+test_si (int a, int b)
+{
+  /* { dg-final { scan-assembler "extr\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, 27\n" 
} } */
+  return (a << 5) | ((unsigned int) b >> 27);
+}
+
+long long
+test_di (long long a, long long b)
+{
+  /* { dg-final { scan-assembler "extr\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, 45\n" 
} } */
+  return (a << 19) | ((unsigned long long) b >> 45);
+}
+
+int
+main ()
+{
+  int v;
+  long long w;
+  v = test_si (0x00000004, 0x30000000);
+  if (v != 0x00000086)
+    abort();
+  w = test_di (0x0001040040040004ll, 0x0070050066666666ll);
+  if (w != 0x2002002000200380ll)
+    abort();
+  return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */

Reply via email to