[ARM] NEON DImode neg

Submitted by Andrew Stubbs on Feb. 28, 2012, 5:45 p.m.

Details

Message ID 4F4D12C5.9070805@codesourcery.com
State New
Headers show

Commit Message

Andrew Stubbs Feb. 28, 2012, 5:45 p.m.
Hi all,

This patch adds a DImode negate pattern for NEON.

Unfortunately, the NEON vneg instruction only supports vectors, not 
singletons, so there's no direct way to do it in DImode, and the 
compiler ends up moving the value back to core registers, negating it, 
and returning to NEON afterwards:

         fmrrd   r2, r3, d16     @ int
         negs    r2, r2
         sbc     r3, r3, r3, lsl #1
         fmdrr   d16, r2, r3     @ int

The new patch does it entirely in NEON:

         vmov.i32        d17, #0  @ di
         vsub.i64        d16, d17, d16

(Note that this is the result when combined with my recent patch for 
NEON DImode immediates. Without that you get a constant pool load.)

OK for 4.8?

Andrew

Patch hide | download patch | download mbox

2012-02-28  Andrew Stubbs  <ams@codesourcery.com>

	gcc/
	* config/arm/arm.md (negdi2): Use gen_negdi2_neon.
	* config/arm/neon.md (negdi2_neon): New insn_and_split.

---
 gcc/config/arm/arm.md  |    8 +++++++-
 gcc/config/arm/neon.md |   14 ++++++++++++++
 2 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 751997f..f1dbbf7 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -4048,7 +4048,13 @@ 
 	 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
     (clobber (reg:CC CC_REGNUM))])]
   "TARGET_EITHER"
-  ""
+  {
+    if (TARGET_NEON)
+      {
+        emit_insn (gen_negdi2_neon (operands[0], operands[1]));
+	DONE;
+      }
+  }
 )
 
 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 757be01..d2cb3ee 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -922,6 +922,20 @@ 
                     (const_string "neon_int_3")))]
 )
 
+(define_insn_and_split "negdi2_neon"
+  [(set (match_operand:DI 0 "s_register_operand" "=w")
+        (neg:DI (match_operand:DI 1 "s_register_operand" "w")))
+   (clobber (match_scratch:DI 2 "=w"))]
+  "TARGET_NEON"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 2) (const_int 0))
+   (parallel [(set (match_dup 0) (minus:DI (match_dup 2) (match_dup 1)))
+	      (clobber (reg:CC CC_REGNUM))])]
+  ""
+  [(set_attr "length" "8")]
+)
+
 (define_insn "*umin<mode>3_neon"
   [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
 	(umin:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")