Patchwork [ARM] NEON DImode neg

login
register
mail settings
Submitter Andrew Stubbs
Date Feb. 28, 2012, 5:45 p.m.
Message ID <4F4D12C5.9070805@codesourcery.com>
Download mbox | patch
Permalink /patch/143517/
State New
Headers show

Comments

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

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")