diff mbox

[ARM] NEON DImode immediate constants

Message ID 4F4CFEC6.2090705@codesourcery.com
State New
Headers show

Commit Message

Andrew Stubbs Feb. 28, 2012, 4:20 p.m. UTC
Hi all,

This patch implements 64-bit immediate constant loads in NEON.

The current state is that you can load const_vector, but not const_int. 
This is clearly not ideal. The result is a constant pool entry when it's 
not necessary.

The patch disables the movdi_vfp patterns for loading DImode values, if 
the operand is const_int and NEON is enabled, and extends the neon_mov 
pattern to include DImode const_int, as well as the const_vector 
operands. I've modified neon_valid_immediate only enough to accept 
const_int input - the logic remains untouched.

OK for 4.8?

Andrew
diff mbox

Patch

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

	gcc/
	* config/arm/arm.c (neon_valid_immediate): Allow const_int.
	* config/arm/constraints.md (Dn): Allow const_int.
	* config/arm/neon.md (neon_mov<mode>): Use VDX to allow DImode.
	* config/arm/predicates.md (imm_for_neon_mov_operand): Allow const_int.
	* config/arm/vfp.md (movdi_vfp): Disable for const_int when neon
	is enabled.
	(movdi_vfp_cortexa8): Likewise.

---
 gcc/config/arm/arm.c          |   20 +++++++++++++++++---
 gcc/config/arm/constraints.md |    6 +++---
 gcc/config/arm/neon.md        |    4 ++--
 gcc/config/arm/predicates.md  |    2 +-
 gcc/config/arm/vfp.md         |    6 ++++--
 5 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 0bded8d..ea2a256 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -8873,11 +8873,25 @@  neon_valid_immediate (rtx op, enum machine_mode mode, int inverse,
       break;					\
     }
 
-  unsigned int i, elsize = 0, idx = 0, n_elts = CONST_VECTOR_NUNITS (op);
-  unsigned int innersize = GET_MODE_SIZE (GET_MODE_INNER (mode));
+  unsigned int i, elsize = 0, idx = 0, n_elts;
+  unsigned int innersize;
   unsigned char bytes[16];
   int immtype = -1, matches;
   unsigned int invmask = inverse ? 0xff : 0;
+  bool vector = GET_CODE (op) == CONST_VECTOR;
+
+  if (vector)
+    {
+      n_elts = CONST_VECTOR_NUNITS (op);
+      innersize = GET_MODE_SIZE (GET_MODE_INNER (mode));
+    }
+  else
+    {
+      n_elts = 1;
+      if (mode == VOIDmode)
+	mode = DImode;
+      innersize = GET_MODE_SIZE (mode);
+    }
 
   /* Vectors of float constants.  */
   if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
@@ -8913,7 +8927,7 @@  neon_valid_immediate (rtx op, enum machine_mode mode, int inverse,
   /* Splat vector constant out into a byte vector.  */
   for (i = 0; i < n_elts; i++)
     {
-      rtx el = CONST_VECTOR_ELT (op, i);
+      rtx el = vector ? CONST_VECTOR_ELT (op, i) : op;
       unsigned HOST_WIDE_INT elpart;
       unsigned int part, parts;
 
diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md
index 7d0269a..68979c1 100644
--- a/gcc/config/arm/constraints.md
+++ b/gcc/config/arm/constraints.md
@@ -255,9 +255,9 @@ 
 
 (define_constraint "Dn"
  "@internal
-  In ARM/Thumb-2 state a const_vector which can be loaded with a Neon vmov
-  immediate instruction."
- (and (match_code "const_vector")
+  In ARM/Thumb-2 state a const_vector or const_int which can be loaded with a
+  Neon vmov immediate instruction."
+ (and (match_code "const_vector,const_int")
       (match_test "TARGET_32BIT
 		   && imm_for_neon_mov_operand (op, GET_MODE (op))")))
 
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index d7caa37..757be01 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -152,9 +152,9 @@ 
 (define_attr "vqh_mnem" "vadd,vmin,vmax" (const_string "vadd"))
 
 (define_insn "*neon_mov<mode>"
-  [(set (match_operand:VD 0 "nonimmediate_operand"
+  [(set (match_operand:VDX 0 "nonimmediate_operand"
 	  "=w,Uv,w, w,  ?r,?w,?r,?r, ?Us")
-	(match_operand:VD 1 "general_operand"
+	(match_operand:VDX 1 "general_operand"
 	  " w,w, Dn,Uvi, w, r, r, Usi,r"))]
   "TARGET_NEON
    && (register_operand (operands[0], <MODE>mode)
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index b535335..8a8a1f1 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -630,7 +630,7 @@ 
 })
 
 (define_predicate "imm_for_neon_mov_operand"
-  (match_code "const_vector")
+  (match_code "const_vector,const_int")
 {
   return neon_immediate_valid_for_move (op, mode, NULL, NULL);
 })
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index 6530570..2cc4104 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -138,7 +138,8 @@ 
        (match_operand:DI 1 "di_operand"              "r,rDa,Db,Dc,mi,mi,r,r,w,w,Uvi,w"))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune != cortexa8
    && (   register_operand (operands[0], DImode)
-       || register_operand (operands[1], DImode))"
+       || register_operand (operands[1], DImode))
+   && (!TARGET_NEON || !CONST_INT_P (operands[1]))"
   "*
   switch (which_alternative)
     {
@@ -187,7 +188,8 @@ 
        (match_operand:DI 1 "di_operand"              "r,rDa,Db,Dc,mi,mi,r,r,w,w,Uvi,w"))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune == cortexa8
     && (   register_operand (operands[0], DImode)
-        || register_operand (operands[1], DImode))"
+        || register_operand (operands[1], DImode))
+    && (!TARGET_NEON || !CONST_INT_P (operands[1]))"
   "*
   switch (which_alternative)
     {