And now with the patch. :(
On 14/04/12 13:48, Andrew Stubbs wrote:
On 12/04/12 16:48, Richard Earnshaw wrote:
If negation in Neon needs a scratch register, it seems to me to be
somewhat odd that we're disparaging the ARM version.
Also, wouldn't it be sensible to support a variant that was
early-clobber on operand 0, but loaded immediate zero into that value
first:
vmov Dd, #0
vsub Dd, Dd, Dm
That way you'll never need more than two registers, whereas today you
want three.
This patch implements the changes you suggested.
I've done a full bootstrap and test and found no regressions.
OK?
Andrew
P.S. This patch can't actually be committed until my "NEON DImode
immediate constants" patch is approved and committed. (Without that the
load #0 needs a constant pool, and loading constants this late has a bug
at -O0.)
2012-04-12 Andrew Stubbs <a...@codesourcery.com>
gcc/
* config/arm/arm.md (negdi2): Use gen_negdi2_neon.
* config/arm/neon.md (negdi2_neon): New insn.
Also add splitters for core and NEON registers.
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 3c88568..8c8b02d 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -922,6 +922,45 @@
(const_string "neon_int_3")))]
)
+(define_insn "negdi2_neon"
+ [(set (match_operand:DI 0 "s_register_operand" "=&w, w,r,&r")
+ (neg:DI (match_operand:DI 1 "s_register_operand" " w, w,0, r")))
+ (clobber (match_scratch:DI 2 "= X,&w,X, X"))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_NEON"
+ "#"
+ [(set_attr "length" "8")]
+)
+
+; Split negdi2_neon for vfp registers
+(define_split
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (neg:DI (match_operand:DI 1 "s_register_operand" "")))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
+ [(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))])]
+ {
+ if (!REG_P (operands[2]))
+ operands[2] = operands[0];
+ }
+)
+
+; Split negdi2_neon for core registers
+(define_split
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (neg:DI (match_operand:DI 1 "s_register_operand" "")))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_32BIT && reload_completed
+ && arm_general_register_operand (operands[0], DImode)"
+ [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+)
+
(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")