This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[ARM/hard_vfp_4_4_branch] Fix VFP ABI for generic vectors without NEON


This patch, against ARM/hard_vfp_4_4_branch, fixes problems with the
handling of generic vectors with the VFP ABI but without NEON.

If -mfloat-abi=hard is used with -mfpu=neon, generic GCC vectors
created with the vector_size attribute get vector modes (if NEON has
suitable modes) and are handled like NEON vectors, being passed and
returned in VFP/NEON registers in accordance with the VFP ABI.

If -mfloat-abi=hard is used without -mfpu=neon, without this patch,
generic GCC vectors may or may not get vector modes.  The only vector
modes they may get are V2SImode, V4HImode and V8QImode, which the ARM
back end declares it supports in that case (probably for historical
reasons because they are the iWMMXt vector modes).  Other vectors will
get DImode, TImode or BLKmode.  Vectors getting vector modes will be
handled by the VFP ABI code as vectors; it will attempts to pass them
in VFP registers, resulting in ICEs because the relevant move patterns
are only enabled for NEON; TImode moves can also result in ICEs, again
because the move patterns are only enabled for NEON.  Vectors not
getting vector modes will not be handled as vectors, leading to
undesirable ABI incompatibilities between code built with and without
-mfpu=neon; we concluded in previous off-list discussion that it was
best for generic vectors to be handled (for ABI purposes) like NEON
vectors of the same size whether or not NEON is enabled.

This patch fixes these problems.  The VFP ABI code now handles all
64-bit and 128-bit vectors without regard to whether they got vector
modes.  The back end no longer claims to support the iWMMXt modes if
neither iWMMXt nor NEON is enabled, and the argument passing / return
code splits up TImode vectors as needed into DImode pieces that the
VFP move patterns know how to handle.

(The compiler already has a sorry ("iWMMXt and hardware floating
point"), so we don't need to worry about the VFP and iWMMXt
combination, though I don't think anything in this patch should break
that combination further.)

Tested with no regressions with cross to arm-none-eabi; this also
fixes ICEs on g++.dg-struct-layout-1/t026,
gcc.c-torture/execute/simd-6.c, gcc.dg/compat/vector-1.  OK to commit
to the branch?

2009-05-12  Joseph Myers  <joseph@codesourcery.com>

	* config/arm/arm.c (aapcs_vfp_sub_candidate): Use V2SImode and
	V4SImode as representatives of all 64-bit and 128-bit vector
	types.  Allow vector types without vector modes.
	(aapcs_vfp_is_call_or_return_candidate): Handle vector types
	without vector modes like BLKmode.
	(aapcs_vfp_allocate): Handle TImode for non-TARGET_NEON like
	BLKmode.  Avoid unsupported vector modes or TImode moves for
	non-TARGET_NEON.
	(aapcs_vfp_allocate_return_reg): Likewise.
	(arm_vector_mode_supported_p): Only support V2SImode, V4HImode and
	V8QImode if TARGET_NEON || TARGET_IWMMXT.

Index: config/arm/arm.c
===================================================================
--- config/arm/arm.c	(revision 147428)
+++ config/arm/arm.c	(working copy)
@@ -3271,6 +3271,7 @@ static int
 aapcs_vfp_sub_candidate (const_tree type, enum machine_mode *modep)
 {
   enum machine_mode mode;
+  HOST_WIDE_INT size;
 
   switch (TREE_CODE (type))
     {
@@ -3301,10 +3302,21 @@ aapcs_vfp_sub_candidate (const_tree type
       break;
 
     case VECTOR_TYPE:
-      mode = TYPE_MODE (type);
-      if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT
-	  && GET_MODE_CLASS (mode) != MODE_VECTOR_FLOAT)
-	return -1;
+      /* Use V2SImode and V4SImode as representatives of all 64-bit
+	 and 128-bit vector types, whether or not those modes are
+	 supported with the present options.  */
+      size = int_size_in_bytes (type);
+      switch (size)
+	{
+	case 8:
+	  mode = V2SImode;
+	  break;
+	case 16:
+	  mode = V4SImode;
+	  break;
+	default:
+	  return -1;
+	}
 
       if (*modep == VOIDmode)
 	*modep = mode;
@@ -3312,9 +3324,7 @@ aapcs_vfp_sub_candidate (const_tree type
       /* Vector modes are considered to be opaque: two vectors are
 	 equivalent for the purposes of being homogeneous aggregates
 	 if they are the same size.  */
-      if ((GET_MODE_CLASS (*modep) == MODE_VECTOR_INT
-	   || GET_MODE_CLASS (*modep) == MODE_VECTOR_FLOAT)
-	  && GET_MODE_SIZE (*modep) == GET_MODE_SIZE (mode))
+      if (*modep == mode)
 	return 1;
 
       break;
@@ -3438,7 +3448,7 @@ aapcs_vfp_is_call_or_return_candidate (e
       *base_mode = (mode == DCmode ? DFmode : SFmode);
       return true;
     }
-  else if (mode == BLKmode && type)
+  else if (type && (mode == BLKmode || TREE_CODE (type) == VECTOR_TYPE))
     {
       enum machine_mode aggregate_mode = VOIDmode;
       int ag_count = aapcs_vfp_sub_candidate (type, &aggregate_mode);
@@ -3492,18 +3502,33 @@ aapcs_vfp_allocate (CUMULATIVE_ARGS *pcu
     if (((pcum->aapcs_vfp_regs_free >> regno) & mask) == mask)
       {
 	pcum->aapcs_vfp_reg_alloc = mask << regno;
-	if (mode == BLKmode)
+	if (mode == BLKmode || (mode == TImode && !TARGET_NEON))
 	  {
 	    int i;
-	    rtx par = gen_rtx_PARALLEL (BLKmode,
-					rtvec_alloc (pcum->aapcs_vfp_rcount));
-	    for (i = 0; i < pcum->aapcs_vfp_rcount; i++)
+	    int rcount = pcum->aapcs_vfp_rcount;
+	    int rshift = shift;
+	    enum machine_mode rmode = pcum->aapcs_vfp_rmode;
+	    rtx par;
+	    if (!TARGET_NEON)
 	      {
-		rtx tmp = gen_rtx_REG (pcum->aapcs_vfp_rmode, 
-				       FIRST_VFP_REGNUM + regno + i * shift);
+		/* Avoid using unsupported vector modes.  */
+		if (rmode == V2SImode)
+		  rmode = DImode;
+		else if (rmode == V4SImode)
+		  {
+		    rmode = DImode;
+		    rcount *= 2;
+		    rshift /= 2;
+		  }
+	      }
+	    par = gen_rtx_PARALLEL (mode, rtvec_alloc (rcount));
+	    for (i = 0; i < rcount; i++)
+	      {
+		rtx tmp = gen_rtx_REG (rmode, 
+				       FIRST_VFP_REGNUM + regno + i * rshift);
 		tmp = gen_rtx_EXPR_LIST
 		  (VOIDmode, tmp, 
-		   GEN_INT (i * GET_MODE_SIZE (pcum->aapcs_vfp_rmode)));
+		   GEN_INT (i * GET_MODE_SIZE (rmode)));
 		XVECEXP (par, 0, i) = tmp;
 	      }
 
@@ -3525,7 +3550,7 @@ aapcs_vfp_allocate_return_reg (enum arm_
 	|| (pcs_variant == ARM_PCS_AAPCS_LOCAL
 	    && TARGET_32BIT && TARGET_VFP && TARGET_HARD_FLOAT)))
     return false;
-  if (mode == BLKmode)
+  if (mode == BLKmode || (mode == TImode && !TARGET_NEON))
     {
       int count;
       int ag_mode;
@@ -3535,8 +3560,18 @@ aapcs_vfp_allocate_return_reg (enum arm_
       
       aapcs_vfp_is_call_or_return_candidate (mode, type, &ag_mode, &count);
 
+      if (!TARGET_NEON)
+	{
+	  if (ag_mode == V2SImode)
+	    ag_mode = DImode;
+	  else if (ag_mode == V4SImode)
+	    {
+	      ag_mode = DImode;
+	      count *= 2;
+	    }
+	}
       shift = GET_MODE_SIZE(ag_mode) / GET_MODE_SIZE(SFmode);
-      par = gen_rtx_PARALLEL (BLKmode, rtvec_alloc (count));
+      par = gen_rtx_PARALLEL (mode, rtvec_alloc (count));
       for (i = 0; i < count; i++)
 	{
 	  rtx tmp = gen_rtx_REG (ag_mode, FIRST_VFP_REGNUM + i * shift);
@@ -19918,9 +19953,10 @@ arm_vector_mode_supported_p (enum machin
       || mode == V16QImode || mode == V4SFmode || mode == V2DImode))
     return true;
 
-  if ((mode == V2SImode)
-      || (mode == V4HImode)
-      || (mode == V8QImode))
+  if ((TARGET_NEON || TARGET_IWMMXT)
+      && ((mode == V2SImode)
+	  || (mode == V4HImode)
+	  || (mode == V8QImode)))
     return true;
 
   return false;

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]