diff mbox

[AArch64] Support abs standard pattern for DI mode

Message ID 000401ce71c6$15630fc0$40292f40$@bolton@arm.com
State New
Headers show

Commit Message

Ian Bolton June 25, 2013, 5:04 p.m. UTC
Hi,

I'm adding support for abs standard pattern name for DI mode,
via the ABS instruction in FP registers and the EOR/SUB combo
in GP registers.

Regression tests for Linux and bare-metal all passed.

OK for trunk?

Cheers,
Ian


2013-06-25  Ian Bolton  <ian.bolton@arm.com>

gcc/
	* config/aarch64/aarch64-simd.md (absdi2): Support abs for
	DI mode.

testsuite/
	* gcc.target/aarch64/abs_1.c: New test.
diff mbox

Patch

diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index e88e5be..3700977 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -2003,6 +2003,38 @@ 
    (set_attr "mode" "SI")]
 )
 
+(define_insn_and_split "absdi2"
+  [(set (match_operand:DI 0 "register_operand" "=r,w")
+	(abs:DI (match_operand:DI 1 "register_operand" "r,w")))
+   (clobber (match_scratch:DI 2 "=&r,X"))]
+  ""
+  "@
+   #
+   abs\\t%d0, %d1"
+  "reload_completed
+   && GP_REGNUM_P (REGNO (operands[0]))
+   && GP_REGNUM_P (REGNO (operands[1]))"
+  [(const_int 0)]
+  {
+    emit_insn (gen_rtx_SET (VOIDmode, operands[2],
+			    gen_rtx_XOR (DImode,
+					 gen_rtx_ASHIFTRT (DImode,
+							   operands[1],
+							   GEN_INT (63)),
+					 operands[1])));
+    emit_insn (gen_rtx_SET (VOIDmode,
+			    operands[0],
+			    gen_rtx_MINUS (DImode,
+					   operands[2],
+					   gen_rtx_ASHIFTRT (DImode,
+							     operands[1],
+							     GEN_INT (63)))));
+    DONE;
+  }
+  [(set_attr "v8type" "alu")
+   (set_attr "mode" "DI")]
+)
+
 (define_insn "neg<mode>2"
   [(set (match_operand:GPI 0 "register_operand" "=r")
 	(neg:GPI (match_operand:GPI 1 "register_operand" "r")))]
diff --git a/gcc/testsuite/gcc.target/aarch64/abs_1.c b/gcc/testsuite/gcc.target/aarch64/abs_1.c
new file mode 100644
index 0000000..938bc84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/abs_1.c
@@ -0,0 +1,53 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline --save-temps" } */
+
+extern long long llabs (long long);
+extern void abort (void);
+
+long long
+abs64 (long long a)
+{
+  /* { dg-final { scan-assembler "eor\t" } } */
+  /* { dg-final { scan-assembler "sub\t" } } */
+  return llabs (a);
+}
+
+long long
+abs64_in_dreg (long long a)
+{
+  /* { dg-final { scan-assembler "abs\td\[0-9\]+, d\[0-9\]+" } } */
+  register long long x asm ("d8") = a;
+  register long long y asm ("d9");
+  asm volatile ("" : : "w" (x));
+  y = llabs (x);
+  asm volatile ("" : : "w" (y));
+  return y;
+}
+
+int
+main (void)
+{
+  volatile long long ll0 = 0LL, ll1 = 1LL, llm1 = -1LL;
+
+  if (abs64 (ll0) != 0LL)
+    abort ();
+
+  if (abs64 (ll1) != 1LL)
+    abort ();
+
+  if (abs64 (llm1) != 1LL)
+    abort ();
+
+  if (abs64_in_dreg (ll0) != 0LL)
+    abort ();
+
+  if (abs64_in_dreg (ll1) != 1LL)
+    abort ();
+
+  if (abs64_in_dreg (llm1) != 1LL)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */