patch: vector initializers

Aldy Hernandez aldyh@redhat.com
Sun Feb 10 20:27:00 GMT 2002


hi guys!

finally, the last piece of the altivec puzzle.  this patch allows the
use of vector initializers, ala:

	vector int foo = (vector int) { 1, 2, 3, 4 };

stan wrote most of the code, but didn't have time to fix a few ICEs
related to vector initializers.  i fixed the remaining problems.

here is the entire patch.

(this is really cool.  thanks stan.)

ok, pending tests which are currently running?

2002-02-07  Stan Shebs  <shebs@apple.com>

	* c-typeck.c (digest_init): Handle vectors.
	(really_start_incremental_init): Same.
	(pop_init_level): Same.
	(process_init_element): Same.

	* varasm.c (output_constant): Same.

	* expr.c (clear_storage): Same.
	(store_constructor): Same.

	* gcc.dg/altivec-3.c: New.

2002-02-07  Aldy Hernandez  <aldyh@redhat.com>

	* expr.c (expand_expr): Do not put vectors in a pseudo, leave them
	in memory.

	* stmt.c (expand_decl): Do not put explicit vector variables into
	registers.

Index: c-typeck.c
===================================================================
RCS file: /cvs/uberbaum/gcc/c-typeck.c,v
retrieving revision 1.175
diff -c -p -r1.175 c-typeck.c
*** c-typeck.c	2002/02/06 20:40:16	1.175
--- c-typeck.c	2002/02/11 03:42:29
*************** digest_init (type, init, require_constan
*** 4825,4830 ****
--- 4825,4832 ----
  		     TYPE_MAIN_VARIANT (type))
  	  || (code == ARRAY_TYPE
  	      && comptypes (TREE_TYPE (inside_init), type))
+ 	  || (code == VECTOR_TYPE
+ 	      && comptypes (TREE_TYPE (inside_init), type))
  	  || (code == POINTER_TYPE
  	      && (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
  		  || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE)
*************** really_start_incremental_init (type)
*** 5336,5341 ****
--- 5338,5351 ----
  
        constructor_unfilled_index = constructor_index;
      }
+   else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
+     {
+       /* Vectors are like simple fixed-size arrays.  */
+       constructor_max_index =
+ 	build_int_2 (TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0);
+       constructor_index = convert (bitsizetype, integer_zero_node);
+       constructor_unfilled_index = constructor_index;
+     }
    else
      {
        /* Handle the case of int x = {5}; */
*************** pop_init_level (implicit)
*** 5618,5624 ****
      ;
    else if (TREE_CODE (constructor_type) != RECORD_TYPE
  	   && TREE_CODE (constructor_type) != UNION_TYPE
! 	   && TREE_CODE (constructor_type) != ARRAY_TYPE)
      {
        /* A nonincremental scalar initializer--just return
  	 the element, after verifying there is just one.  */
--- 5628,5635 ----
      ;
    else if (TREE_CODE (constructor_type) != RECORD_TYPE
  	   && TREE_CODE (constructor_type) != UNION_TYPE
! 	   && TREE_CODE (constructor_type) != ARRAY_TYPE
! 	   && TREE_CODE (constructor_type) != VECTOR_TYPE)
      {
        /* A nonincremental scalar initializer--just return
  	 the element, after verifying there is just one.  */
*************** process_init_element (value)
*** 6817,6822 ****
--- 6828,6858 ----
  	      output_init_element (value, elttype, constructor_index, 1);
  	      RESTORE_SPELLING_DEPTH (constructor_depth);
  	    }
+ 
+ 	  constructor_index
+ 	    = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
+ 
+ 	  if (! value)
+ 	    /* If we are doing the bookkeeping for an element that was
+ 	       directly output as a constructor, we must update
+ 	       constructor_unfilled_index.  */
+ 	    constructor_unfilled_index = constructor_index;
+ 	}
+       else if (TREE_CODE (constructor_type) == VECTOR_TYPE)
+ 	{
+ 	  tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+ 
+          /* Do a basic check of initializer size.  Note that vectors
+             always have a fixed size derived from their type.  */
+ 	  if (tree_int_cst_lt (constructor_max_index, constructor_index))
+ 	    {
+ 	      pedwarn_init ("excess elements in vector initializer");
+ 	      break;
+ 	    }
+ 
+ 	  /* Now output the actual element.  */
+ 	  if (value)
+ 	    output_init_element (value, elttype, constructor_index, 1);
  
  	  constructor_index
  	    = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
Index: varasm.c
===================================================================
RCS file: /cvs/uberbaum/gcc/varasm.c,v
retrieving revision 1.247
diff -c -p -r1.247 varasm.c
*** varasm.c	2002/02/08 22:20:15	1.247
--- varasm.c	2002/02/11 03:42:31
*************** output_constant (exp, size, align)
*** 4519,4524 ****
--- 4519,4525 ----
        break;
  
      case ARRAY_TYPE:
+     case VECTOR_TYPE:
        if (TREE_CODE (exp) == CONSTRUCTOR)
  	{
  	  output_constructor (exp, size, align);
Index: expr.c
===================================================================
RCS file: /cvs/uberbaum/gcc/expr.c,v
retrieving revision 1.416
diff -c -p -r1.416 expr.c
*** expr.c	2002/02/08 22:20:14	1.416
--- expr.c	2002/02/11 03:42:35
*************** clear_storage (object, size)
*** 2562,2568 ****
  
    /* If OBJECT is not BLKmode and SIZE is the same size as its mode,
       just move a zero.  Otherwise, do this a piece at a time.  */
!   if (GET_MODE (object) != BLKmode
        && GET_CODE (size) == CONST_INT
        && GET_MODE_SIZE (GET_MODE (object)) == (unsigned int) INTVAL (size))
      emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
--- 2562,2569 ----
  
    /* If OBJECT is not BLKmode and SIZE is the same size as its mode,
       just move a zero.  Otherwise, do this a piece at a time.  */
!   if ((GET_MODE (object) != BLKmode
!        && !VECTOR_MODE_P (GET_MODE (object)))
        && GET_CODE (size) == CONST_INT
        && GET_MODE_SIZE (GET_MODE (object)) == (unsigned int) INTVAL (size))
      emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
*************** store_constructor (exp, target, cleared,
*** 4528,4547 ****
  				   get_alias_set (TREE_TYPE (field)));
  	}
      }
!   else if (TREE_CODE (type) == ARRAY_TYPE)
      {
        tree elt;
        int i;
        int need_to_clear;
        tree domain = TYPE_DOMAIN (type);
        tree elttype = TREE_TYPE (type);
!       int const_bounds_p = (TYPE_MIN_VALUE (domain)
! 			    && TYPE_MAX_VALUE (domain)
! 			    && host_integerp (TYPE_MIN_VALUE (domain), 0)
! 			    && host_integerp (TYPE_MAX_VALUE (domain), 0));
        HOST_WIDE_INT minelt = 0;
        HOST_WIDE_INT maxelt = 0;
  
        /* If we have constant bounds for the range of the type, get them.  */
        if (const_bounds_p)
  	{
--- 4529,4562 ----
  				   get_alias_set (TREE_TYPE (field)));
  	}
      }
!   else if (TREE_CODE (type) == ARRAY_TYPE
! 	   || TREE_CODE (type) == VECTOR_TYPE)
      {
        tree elt;
        int i;
        int need_to_clear;
        tree domain = TYPE_DOMAIN (type);
        tree elttype = TREE_TYPE (type);
!       int const_bounds_p;
        HOST_WIDE_INT minelt = 0;
        HOST_WIDE_INT maxelt = 0;
  
+       /* Vectors are like arrays, but the domain is stored via an array
+ 	 type indirectly.  */
+       if (TREE_CODE (type) == VECTOR_TYPE)
+ 	{
+ 	  /* Note that although TYPE_DEBUG_REPRESENTATION_TYPE uses
+ 	     the same field as TYPE_DOMAIN, we are not guaranteed that
+ 	     it always will.  */
+ 	  domain = TYPE_DEBUG_REPRESENTATION_TYPE (type);
+ 	  domain = TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (domain)));
+ 	}
+ 
+       const_bounds_p = (TYPE_MIN_VALUE (domain)
+ 			&& TYPE_MAX_VALUE (domain)
+ 			&& host_integerp (TYPE_MIN_VALUE (domain), 0)
+ 			&& host_integerp (TYPE_MAX_VALUE (domain), 0));
+ 
        /* If we have constant bounds for the range of the type, get them.  */
        if (const_bounds_p)
  	{
*************** store_constructor (exp, target, cleared,
*** 4665,4670 ****
--- 4680,4686 ----
  
  		      if (GET_CODE (target) == MEM
  			  && !MEM_KEEP_ALIAS_SET_P (target)
+ 			  && TREE_CODE (type) == ARRAY_TYPE
  			  && TYPE_NONALIASED_COMPONENT (type))
  			{
  			  target = copy_rtx (target);
*************** store_constructor (exp, target, cleared,
*** 4762,4767 ****
--- 4778,4784 ----
  		bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
  
  	      if (GET_CODE (target) == MEM && !MEM_KEEP_ALIAS_SET_P (target)
+ 		  && TREE_CODE (type) == ARRAY_TYPE
  		  && TYPE_NONALIASED_COMPONENT (type))
  		{
  		  target = copy_rtx (target);
*************** expand_expr (exp, target, tmode, modifie
*** 6573,6581 ****
        else
  	{
  	  /* Handle calls that pass values in multiple non-contiguous
! 	     locations.  The Irix 6 ABI has examples of this.  */
! 	  if (target == 0 || ! safe_from_p (target, exp, 1)
! 	      || GET_CODE (target) == PARALLEL)
  	    target
  	      = assign_temp (build_qualified_type (type,
  						   (TYPE_QUALS (type)
--- 6590,6601 ----
        else
  	{
  	  /* Handle calls that pass values in multiple non-contiguous
! 	     locations.  The Irix 6 ABI has examples of this.
! 
! 	  Leave vectors as is, else we'll try to SUBREG them later on.  */
! 	  if (!VECTOR_MODE_P (mode)
! 	      && (target == 0 || ! safe_from_p (target, exp, 1)
! 		  || GET_CODE (target) == PARALLEL))
  	    target
  	      = assign_temp (build_qualified_type (type,
  						   (TYPE_QUALS (type)
Index: stmt.c
===================================================================
RCS file: /cvs/uberbaum/gcc/stmt.c,v
retrieving revision 1.246
diff -c -p -r1.246 stmt.c
*** stmt.c	2002/02/07 01:38:39	1.246
--- stmt.c	2002/02/11 03:42:38
*************** expand_decl (decl)
*** 3908,3913 ****
--- 3908,3914 ----
        SET_DECL_RTL (decl, x);
      }
    else if (DECL_MODE (decl) != BLKmode
+ 	   && !VECTOR_MODE_P (DECL_MODE (decl))
  	   /* If -ffloat-store, don't put explicit float vars
  	      into regs.  */
  	   && !(flag_float_store
Index: testsuite/gcc.dg/altivec-3.c
===================================================================
RCS file: altivec-3.c
diff -N altivec-3.c
*** /dev/null	Tue May  5 13:32:27 1998
--- altivec-3.c	Sun Feb 10 19:42:38 2002
***************
*** 0 ****
--- 1,69 ----
+ /* { dg-do run { target powerpc-*-*altivec powerpc-*-*-*altivec } } */
+ /* { dg-options "-maltivec" } */
+ 
+ typedef int int4 __attribute__ ((mode(V4SI)));
+ typedef float float4 __attribute__ ((mode(V4SF)));
+ 
+ int4 a1 = (int4) { 100, 200, 300, 400 };
+ int4 a2 = (int4) { 500, 600, 700, 800 };
+ 
+ float4 f1 = (float4) { 1.0, 2.0, 3.0, 4.0 };  
+ float4 f2 = (float4) { 5.0, 6.0, 7.0, 8.0 };
+ 
+ int i3[4] __attribute__((aligned(16)));
+ int j3[4] __attribute__((aligned(16)));
+ float h3[4] __attribute__((aligned(16)));
+ float g3[4] __attribute__((aligned(16)));
+ 
+ #define vec_store(dst, src) \
+   __builtin_altivec_st_internal_4si ((int *) dst, (int4) src)
+ 
+ #define vec_add_int4(x, y) \
+   __builtin_altivec_vaddsws (x, y)
+ 
+ #define vec_add_float4(x, y) \
+   __builtin_altivec_vaddfp (x, y)
+ 
+ #define my_abs(x) (x > 0.0F ? x : -x)
+ 
+ void
+ compare_int4 (int *a, int *b)
+ {
+   int i;
+ 
+   for (i = 0; i < 4; ++i)
+     if (a[i] != b[i])
+       abort ();
+ }
+ 
+ void
+ compare_float4 (float *a, float *b)
+ {
+   int i;
+ 
+   for (i = 0; i < 4; ++i)
+     if (my_abs(a[i] - b[i]) >= 1.0e-6)
+       abort ();
+ }
+ 
+ main ()
+ {
+   int loc1 = 600, loc2 = 800;
+   int4 a3 = (int4) { loc1, loc2, 1000, 1200 };
+   int4 itmp;
+   double locf = 12.0;
+   float4 f3 = (float4) { 6.0, 8.0, 10.0, 12.0 };
+   float4 ftmp;
+ 
+   vec_store (i3, a3);
+   itmp = vec_add_int4 (a1, a2);
+   vec_store (j3, itmp);
+   compare_int4 (i3, j3);
+ 
+   vec_store (g3, f3);
+   ftmp = vec_add_float4 (f1, f2);
+   vec_store (h3, ftmp);
+   compare_float4 (g3, h3);
+ 
+   exit (0);
+ }



More information about the Gcc-patches mailing list