diff mbox

[AArch64] Support EXTR in backend

Message ID 000001ce20c9$6957f350$3c07d9f0$@bolton@arm.com
State New
Headers show

Commit Message

Ian Bolton March 14, 2013, 3:34 p.m. UTC
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.bolton@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.

Comments

Marcus Shawcroft March 15, 2013, 2:34 p.m. UTC | #1
On 14/03/13 15:34, Ian Bolton wrote:
> 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.bolton@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.
>

OK for stage-1.

/Marcus
diff mbox

Patch

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 } } */