[PATCH] Change VECTOR_CST representation from TREE_LIST to TREE_VEC-like

Richard Guenther rguenther@suse.de
Thu Mar 15 12:20:00 GMT 2012


This removes the use of TREE_LISTs for VECTOR_CSTs and instead employs
a similar way of storing elements as TREE_VECs.  I copied the
macro interface bits of the CONSTRUCTOR accesses and did a 1:1 transform
at most places to not let refactoring errors creep in (well, where 
possible).  I'm not sure if it's worth omitting the explicit length
field in favor of using that of the type - at least we are getting
consistency (no implicit zero elements) here for free.

Bootstrap and regtest on x86_64-unknown-linux-gnu running.  I cannot
test sparc apart from compiling a cc1, which works.

Ok for the c-common and sparc bits?  Any other comments?

Thanks,
Richard.

2012-03-15  Richard Guenther  <rguenther@suse.de>

	* tree.h (TREE_VECTOR_CST_ELTS): Remove.
	(VECTOR_CST_NELTS, VECTOR_CST_ELTS, VECTOR_CST_ELT): New defines.
	(struct tree_vector): Remove elements member, add variable size
	elts array member.
	(build_vector_stat): Declare.
	(build_vector): Define in terms of build_vector_stat.
	* tree.c (build_vector): Rename to ...
	(build_vector_stat): ... this.  Take array of trees as parameter.
	(build_vector_from_ctor): Adjust.
	(integer_zerop, integer_onep, integer_all_onesp, iterative_hash_expr,
	initializer_zerop): Adjust.
	* cfgexpand.c (expand_debug_expr): Likewise.
	* expr.c (categorize_ctor_elements_1, expand_expr_real_1,
	const_vector_from_tree): Likewise.
	* fold-const.c (const_binop, operand_equal_p, native_encode_vector,
	native_interpret_vector, fold_unary_loc, vec_cst_ctor_to_array,
	fold_vec_perm, fold_binary_loc, fold_ternary_loc): Likewise.
	* tree-streamer-in.c (streamer_alloc_tree): Handle TS_VECTOR.
	(lto_input_ts_vector_tree_pointers): Adjust.
	* tree-streamer-out.c (streamer_write_tree_header): Handle TS_VECTOR.
	(write_ts_vector_tree_pointers): Adjust.
	* varasm.c (const_hash_1, compare_constant, copy_constant,
	output_constant): Adjust.
	* gimple-fold.c (gimple_fold_stmt_to_constant_1): Adjust.
	* print-tree.c (print_node): Adjust.
	* tree-pretty-print.c (dump_generic_node): Adjust.
	* tree-vect-generic.c (uniform_vector_p, vector_element,
	lower_vec_perm): Adjust.
	* tree-vect-loop.c (get_initial_def_for_reduction): Adjust.
	* tree-vect-slp.c (vect_get_constant_vectors,
	vect_transform_slp_perm_load): Adjust.
	* tree-vect-stmts.c (vect_gen_perm_mask): Adjust.
	* expmed.c (make_tree): Adjust.

	* config/i386/i386.c (ix86_expand_builtin): Adjust.
	* config/sparc/sparc.c (sparc_handle_vis_mul8x16): Adjust interface
	and implementation.
	(sparc_fold_builtin): Adjust.

	c-family/
	* c-pretty-print.c (pp_c_initializer_list): Adjust.

Index: gcc/tree.h
===================================================================
*** gcc/tree.h.orig	2012-03-15 11:14:26.000000000 +0100
--- gcc/tree.h	2012-03-15 12:37:35.000000000 +0100
*************** struct GTY(()) tree_complex {
*** 1534,1544 ****
  };
  
  /* In a VECTOR_CST node.  */
! #define TREE_VECTOR_CST_ELTS(NODE) (VECTOR_CST_CHECK (NODE)->vector.elements)
  
  struct GTY(()) tree_vector {
    struct tree_typed typed;
!   tree elements;
  };
  
  #include "symtab.h"
--- 1534,1546 ----
  };
  
  /* In a VECTOR_CST node.  */
! #define VECTOR_CST_NELTS(NODE) (TYPE_VECTOR_SUBPARTS (TREE_TYPE (NODE)))
! #define VECTOR_CST_ELTS(NODE) (VECTOR_CST_CHECK (NODE)->vector.elts)
! #define VECTOR_CST_ELT(NODE,IDX) (VECTOR_CST_CHECK (NODE)->vector.elts[IDX])
  
  struct GTY(()) tree_vector {
    struct tree_typed typed;
!   tree GTY ((length ("TYPE_VECTOR_SUBPARTS (TREE_TYPE ((tree)&%h))"))) elts[1];
  };
  
  #include "symtab.h"
*************** build_int_cstu (tree type, unsigned HOST
*** 4337,4343 ****
  extern tree build_int_cst (tree, HOST_WIDE_INT);
  extern tree build_int_cst_type (tree, HOST_WIDE_INT);
  extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
! extern tree build_vector (tree, tree);
  extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
  extern tree build_vector_from_val (tree, tree);
  extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
--- 4339,4346 ----
  extern tree build_int_cst (tree, HOST_WIDE_INT);
  extern tree build_int_cst_type (tree, HOST_WIDE_INT);
  extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
! extern tree build_vector_stat (tree, tree * MEM_STAT_DECL);
! #define build_vector(t,v) build_vector_stat (t, v MEM_STAT_INFO)
  extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
  extern tree build_vector_from_val (tree, tree);
  extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
Index: gcc/tree.c
===================================================================
*** gcc/tree.c.orig	2012-03-15 11:14:26.000000000 +0100
--- gcc/tree.c	2012-03-15 12:36:45.000000000 +0100
*************** cst_and_fits_in_hwi (const_tree x)
*** 1315,1335 ****
     are in a list pointed to by VALS.  */
  
  tree
! build_vector (tree type, tree vals)
  {
-   tree v = make_node (VECTOR_CST);
    int over = 0;
-   tree link;
    unsigned cnt = 0;
  
!   TREE_VECTOR_CST_ELTS (v) = vals;
    TREE_TYPE (v) = type;
  
    /* Iterate through elements and check for overflow.  */
!   for (link = vals; link; link = TREE_CHAIN (link))
      {
!       tree value = TREE_VALUE (link);
!       cnt++;
  
        /* Don't crash if we get an address constant.  */
        if (!CONSTANT_CLASS_P (value))
--- 1315,1341 ----
     are in a list pointed to by VALS.  */
  
  tree
! build_vector_stat (tree type, tree *vals MEM_STAT_DECL)
  {
    int over = 0;
    unsigned cnt = 0;
+   tree v;
+   int length = ((TYPE_VECTOR_SUBPARTS (type) - 1) * sizeof (tree)
+ 		+ sizeof (struct tree_vector));
+ 
+   record_node_allocation_statistics (VECTOR_CST, length);
+ 
+   v = ggc_alloc_zone_cleared_tree_node_stat (&tree_zone, length PASS_MEM_STAT);
  
!   TREE_SET_CODE (v, VECTOR_CST);
    TREE_TYPE (v) = type;
  
    /* Iterate through elements and check for overflow.  */
!   for (cnt = 0; cnt < TYPE_VECTOR_SUBPARTS (type); ++cnt)
      {
!       tree value = vals[cnt];
! 
!       VECTOR_CST_ELT (v, cnt) = value;
  
        /* Don't crash if we get an address constant.  */
        if (!CONSTANT_CLASS_P (value))
*************** build_vector (tree type, tree vals)
*** 1338,1345 ****
        over |= TREE_OVERFLOW (value);
      }
  
-   gcc_assert (cnt == TYPE_VECTOR_SUBPARTS (type));
- 
    TREE_OVERFLOW (v) = over;
    return v;
  }
--- 1344,1349 ----
*************** build_vector (tree type, tree vals)
*** 1350,1365 ****
  tree
  build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v)
  {
!   tree list = NULL_TREE;
    unsigned HOST_WIDE_INT idx;
    tree value;
  
    FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
!     list = tree_cons (NULL_TREE, value, list);
    for (; idx < TYPE_VECTOR_SUBPARTS (type); ++idx)
!     list = tree_cons (NULL_TREE,
! 		      build_zero_cst (TREE_TYPE (type)), list);
!   return build_vector (type, nreverse (list));
  }
  
  /* Build a vector of type VECTYPE where all the elements are SCs.  */
--- 1354,1369 ----
  tree
  build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v)
  {
!   tree *vec = XALLOCAVEC (tree, TYPE_VECTOR_SUBPARTS (type));
    unsigned HOST_WIDE_INT idx;
    tree value;
  
    FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
!     vec[idx] = value;
    for (; idx < TYPE_VECTOR_SUBPARTS (type); ++idx)
!     vec[idx] = build_zero_cst (TREE_TYPE (type));
! 
!   return build_vector (type, vec);
  }
  
  /* Build a vector of type VECTYPE where all the elements are SCs.  */
*************** integer_zerop (const_tree expr)
*** 1724,1732 ****
  	      && integer_zerop (TREE_IMAGPART (expr)));
      case VECTOR_CST:
        {
! 	tree elt;
! 	for (elt = TREE_VECTOR_CST_ELTS (expr); elt; elt = TREE_CHAIN (elt))
! 	  if (!integer_zerop (TREE_VALUE (elt)))
  	    return false;
  	return true;
        }
--- 1728,1736 ----
  	      && integer_zerop (TREE_IMAGPART (expr)));
      case VECTOR_CST:
        {
! 	unsigned i;
! 	for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
! 	  if (!integer_zerop (VECTOR_CST_ELT (expr, i)))
  	    return false;
  	return true;
        }
*************** integer_onep (const_tree expr)
*** 1753,1761 ****
  	      && integer_zerop (TREE_IMAGPART (expr)));
      case VECTOR_CST:
        {
! 	tree elt;
! 	for (elt = TREE_VECTOR_CST_ELTS (expr); elt; elt = TREE_CHAIN (elt))
! 	  if (!integer_onep (TREE_VALUE (elt)))
  	    return false;
  	return true;
        }
--- 1757,1765 ----
  	      && integer_zerop (TREE_IMAGPART (expr)));
      case VECTOR_CST:
        {
! 	unsigned i;
! 	for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
! 	  if (!integer_onep (VECTOR_CST_ELT (expr, i)))
  	    return false;
  	return true;
        }
*************** integer_all_onesp (const_tree expr)
*** 1782,1790 ****
  
    else if (TREE_CODE (expr) == VECTOR_CST)
      {
!       tree elt;
!       for (elt = TREE_VECTOR_CST_ELTS (expr); elt; elt = TREE_CHAIN (elt))
! 	if (!integer_all_onesp (TREE_VALUE (elt)))
  	  return 0;
        return 1;
      }
--- 1786,1794 ----
  
    else if (TREE_CODE (expr) == VECTOR_CST)
      {
!       unsigned i;
!       for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
! 	if (!integer_all_onesp (VECTOR_CST_ELT (expr, i)))
  	  return 0;
        return 1;
      }
*************** iterative_hash_expr (const_tree t, hashv
*** 6944,6950 ****
        val = iterative_hash_expr (TREE_REALPART (t), val);
        return iterative_hash_expr (TREE_IMAGPART (t), val);
      case VECTOR_CST:
!       return iterative_hash_expr (TREE_VECTOR_CST_ELTS (t), val);
      case SSA_NAME:
        /* We can just compare by pointer.  */
        return iterative_hash_host_wide_int (SSA_NAME_VERSION (t), val);
--- 6948,6959 ----
        val = iterative_hash_expr (TREE_REALPART (t), val);
        return iterative_hash_expr (TREE_IMAGPART (t), val);
      case VECTOR_CST:
!       {
! 	unsigned i;
! 	for (i = 0; i < VECTOR_CST_NELTS (t); ++i)
! 	  val = iterative_hash_expr (VECTOR_CST_ELT (t, i), val);
! 	return val;
!       }
      case SSA_NAME:
        /* We can just compare by pointer.  */
        return iterative_hash_host_wide_int (SSA_NAME_VERSION (t), val);
*************** initializer_zerop (const_tree init)
*** 9889,9898 ****
  	    && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init))));
  
      case VECTOR_CST:
!       for (elt = TREE_VECTOR_CST_ELTS (init); elt; elt = TREE_CHAIN (elt))
! 	if (!initializer_zerop (TREE_VALUE (elt)))
! 	  return false;
!       return true;
  
      case CONSTRUCTOR:
        {
--- 9898,9910 ----
  	    && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init))));
  
      case VECTOR_CST:
!       {
! 	unsigned i;
! 	for (i = 0; i < VECTOR_CST_NELTS (init); ++i)
! 	  if (!initializer_zerop (VECTOR_CST_ELT (init, i)))
! 	    return false;
! 	return true;
!       }
  
      case CONSTRUCTOR:
        {
Index: gcc/c-family/c-pretty-print.c
===================================================================
*** gcc/c-family/c-pretty-print.c.orig	2012-03-15 11:14:26.000000000 +0100
--- gcc/c-family/c-pretty-print.c	2012-03-15 11:16:30.000000000 +0100
*************** pp_c_initializer_list (c_pretty_printer
*** 1372,1378 ****
  
      case VECTOR_TYPE:
        if (TREE_CODE (e) == VECTOR_CST)
! 	pp_c_expression_list (pp, TREE_VECTOR_CST_ELTS (e));
        else
  	break;
        return;
--- 1372,1386 ----
  
      case VECTOR_TYPE:
        if (TREE_CODE (e) == VECTOR_CST)
! 	{
! 	  unsigned i;
! 	  for (i = 0; i < VECTOR_CST_NELTS (e); ++i)
! 	    {
! 	      if (i > 0)
! 		pp_separate_with (pp, ',');
! 	      pp_expression (pp, VECTOR_CST_ELT (e, i));
! 	    }
! 	}
        else
  	break;
        return;
Index: gcc/cfgexpand.c
===================================================================
*** gcc/cfgexpand.c.orig	2012-03-15 11:14:26.000000000 +0100
--- gcc/cfgexpand.c	2012-03-15 11:16:30.000000000 +0100
*************** expand_debug_expr (tree exp)
*** 3354,3362 ****
        return op0;
  
      case VECTOR_CST:
!       exp = build_constructor_from_list (TREE_TYPE (exp),
! 					 TREE_VECTOR_CST_ELTS (exp));
!       /* Fall through.  */
  
      case CONSTRUCTOR:
        if (TREE_CLOBBER_P (exp))
--- 3354,3375 ----
        return op0;
  
      case VECTOR_CST:
!       {
! 	unsigned i;
! 
! 	op0 = gen_rtx_CONCATN
! 	  (mode, rtvec_alloc (TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp))));
! 
! 	for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
! 	  {
! 	    op1 = expand_debug_expr (VECTOR_CST_ELT (exp, i));
! 	    if (!op1)
! 	      return NULL;
! 	    XVECEXP (op0, 0, i) = op1;
! 	  }
! 
! 	return op0;
!       }
  
      case CONSTRUCTOR:
        if (TREE_CLOBBER_P (exp))
Index: gcc/expr.c
===================================================================
*** gcc/expr.c.orig	2012-03-15 11:15:40.000000000 +0100
--- gcc/expr.c	2012-03-15 11:16:30.000000000 +0100
*************** categorize_ctor_elements_1 (const_tree c
*** 5461,5470 ****
  
  	case VECTOR_CST:
  	  {
! 	    tree v;
! 	    for (v = TREE_VECTOR_CST_ELTS (value); v; v = TREE_CHAIN (v))
  	      {
! 		if (!initializer_zerop (TREE_VALUE (v)))
  		  nz_elts += mult;
  		init_elts += mult;
  	      }
--- 5461,5471 ----
  
  	case VECTOR_CST:
  	  {
! 	    unsigned i;
! 	    for (i = 0; i < VECTOR_CST_NELTS (value); ++i)
  	      {
! 		tree v = VECTOR_CST_ELT (value, i);
! 		if (!initializer_zerop (v))
  		  nz_elts += mult;
  		init_elts += mult;
  	      }
*************** expand_expr_real_1 (tree exp, rtx target
*** 9122,9129 ****
  	      tmp = fold_unary_loc (loc, VIEW_CONVERT_EXPR, type_for_mode, exp);
  	  }
  	if (!tmp)
! 	  tmp = build_constructor_from_list (type,
! 					     TREE_VECTOR_CST_ELTS (exp));
  	return expand_expr (tmp, ignore ? const0_rtx : target,
  			    tmode, modifier);
        }
--- 9123,9136 ----
  	      tmp = fold_unary_loc (loc, VIEW_CONVERT_EXPR, type_for_mode, exp);
  	  }
  	if (!tmp)
! 	  {
! 	    VEC(constructor_elt,gc) *v;
! 	    unsigned i;
! 	    v = VEC_alloc (constructor_elt, gc, VECTOR_CST_NELTS (exp));
! 	    for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
! 	      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, VECTOR_CST_ELT (exp, i));
! 	    tmp = build_constructor (type, v);
! 	  }
  	return expand_expr (tmp, ignore ? const0_rtx : target,
  			    tmode, modifier);
        }
*************** static rtx
*** 10767,10774 ****
  const_vector_from_tree (tree exp)
  {
    rtvec v;
!   int units, i;
!   tree link, elt;
    enum machine_mode inner, mode;
  
    mode = TYPE_MODE (TREE_TYPE (exp));
--- 10774,10782 ----
  const_vector_from_tree (tree exp)
  {
    rtvec v;
!   unsigned i;
!   int units;
!   tree elt;
    enum machine_mode inner, mode;
  
    mode = TYPE_MODE (TREE_TYPE (exp));
*************** const_vector_from_tree (tree exp)
*** 10781,10790 ****
  
    v = rtvec_alloc (units);
  
!   link = TREE_VECTOR_CST_ELTS (exp);
!   for (i = 0; link; link = TREE_CHAIN (link), ++i)
      {
!       elt = TREE_VALUE (link);
  
        if (TREE_CODE (elt) == REAL_CST)
  	RTVEC_ELT (v, i) = CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (elt),
--- 10789,10797 ----
  
    v = rtvec_alloc (units);
  
!   for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
      {
!       elt = VECTOR_CST_ELT (exp, i);
  
        if (TREE_CODE (elt) == REAL_CST)
  	RTVEC_ELT (v, i) = CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (elt),
*************** const_vector_from_tree (tree exp)
*** 10797,10806 ****
  						   inner);
      }
  
-   /* Initialize remaining elements to 0.  */
-   for (; i < units; ++i)
-     RTVEC_ELT (v, i) = CONST0_RTX (inner);
- 
    return gen_rtx_CONST_VECTOR (mode, v);
  }
  
--- 10804,10809 ----
Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c.orig	2012-03-15 11:14:57.000000000 +0100
--- gcc/fold-const.c	2012-03-15 11:41:02.000000000 +0100
*************** const_binop (enum tree_code code, tree a
*** 1351,1399 ****
  	return build_complex (type, real, imag);
      }
  
!   if (TREE_CODE (arg1) == VECTOR_CST)
      {
        tree type = TREE_TYPE(arg1);
        int count = TYPE_VECTOR_SUBPARTS (type), i;
!       tree elements1, elements2, list = NULL_TREE;
! 
!       if(TREE_CODE(arg2) != VECTOR_CST)
!         return NULL_TREE;
! 
!       elements1 = TREE_VECTOR_CST_ELTS (arg1);
!       elements2 = TREE_VECTOR_CST_ELTS (arg2);
  
        for (i = 0; i < count; i++)
  	{
!           tree elem1, elem2, elem;
  
!           /* The trailing elements can be empty and should be treated as 0 */
!           if(!elements1)
!             elem1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
!           else
!             {
!               elem1 = TREE_VALUE(elements1);
!               elements1 = TREE_CHAIN (elements1);
!             }
! 
!           if(!elements2)
!             elem2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
!           else
!             {
!               elem2 = TREE_VALUE(elements2);
!               elements2 = TREE_CHAIN (elements2);
!             }
! 
!           elem = const_binop (code, elem1, elem2);
  
            /* It is possible that const_binop cannot handle the given
              code and return NULL_TREE */
!           if(elem == NULL_TREE)
              return NULL_TREE;
- 
-           list = tree_cons (NULL_TREE, elem, list);
  	}
!       return build_vector(type, nreverse(list));
      }
    return NULL_TREE;
  }
--- 1351,1377 ----
  	return build_complex (type, real, imag);
      }
  
!   if (TREE_CODE (arg1) == VECTOR_CST
!       && TREE_CODE (arg2) == VECTOR_CST)
      {
        tree type = TREE_TYPE(arg1);
        int count = TYPE_VECTOR_SUBPARTS (type), i;
!       tree *elts =  XALLOCAVEC (tree, count);
  
        for (i = 0; i < count; i++)
  	{
!           tree elem1 = VECTOR_CST_ELT (arg1, i);
! 	  tree elem2 = VECTOR_CST_ELT (arg2, i);
  
!           elts[i] = const_binop (code, elem1, elem2);
  
            /* It is possible that const_binop cannot handle the given
              code and return NULL_TREE */
!           if(elts[i] == NULL_TREE)
              return NULL_TREE;
  	}
! 
!       return build_vector (type, elts);
      }
    return NULL_TREE;
  }
*************** operand_equal_p (const_tree arg0, const_
*** 2491,2510 ****
  
        case VECTOR_CST:
  	{
! 	  tree v1, v2;
  
! 	  v1 = TREE_VECTOR_CST_ELTS (arg0);
! 	  v2 = TREE_VECTOR_CST_ELTS (arg1);
! 	  while (v1 && v2)
  	    {
! 	      if (!operand_equal_p (TREE_VALUE (v1), TREE_VALUE (v2),
! 				    flags))
  		return 0;
- 	      v1 = TREE_CHAIN (v1);
- 	      v2 = TREE_CHAIN (v2);
  	    }
! 
! 	  return v1 == v2;
  	}
  
        case COMPLEX_CST:
--- 2469,2486 ----
  
        case VECTOR_CST:
  	{
! 	  unsigned i;
  
! 	  if (VECTOR_CST_NELTS (arg0) != VECTOR_CST_NELTS (arg1))
! 	    return 0;
! 
! 	  for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)
  	    {
! 	      if (!operand_equal_p (VECTOR_CST_ELT (arg0, i),
! 				    VECTOR_CST_ELT (arg1, i), flags))
  		return 0;
  	    }
! 	  return 1;
  	}
  
        case COMPLEX_CST:
*************** native_encode_complex (const_tree expr,
*** 7307,7341 ****
  static int
  native_encode_vector (const_tree expr, unsigned char *ptr, int len)
  {
!   int i, size, offset, count;
!   tree itype, elem, elements;
  
    offset = 0;
!   elements = TREE_VECTOR_CST_ELTS (expr);
!   count = TYPE_VECTOR_SUBPARTS (TREE_TYPE (expr));
    itype = TREE_TYPE (TREE_TYPE (expr));
    size = GET_MODE_SIZE (TYPE_MODE (itype));
    for (i = 0; i < count; i++)
      {
!       if (elements)
! 	{
! 	  elem = TREE_VALUE (elements);
! 	  elements = TREE_CHAIN (elements);
! 	}
!       else
! 	elem = NULL_TREE;
! 
!       if (elem)
! 	{
! 	  if (native_encode_expr (elem, ptr+offset, len-offset) != size)
! 	    return 0;
! 	}
!       else
! 	{
! 	  if (offset + size > len)
! 	    return 0;
! 	  memset (ptr+offset, 0, size);
! 	}
        offset += size;
      }
    return offset;
--- 7283,7301 ----
  static int
  native_encode_vector (const_tree expr, unsigned char *ptr, int len)
  {
!   unsigned i, count;
!   int size, offset;
!   tree itype, elem;
  
    offset = 0;
!   count = VECTOR_CST_NELTS (expr);
    itype = TREE_TYPE (TREE_TYPE (expr));
    size = GET_MODE_SIZE (TYPE_MODE (itype));
    for (i = 0; i < count; i++)
      {
!       elem = VECTOR_CST_ELT (expr, i);
!       if (native_encode_expr (elem, ptr+offset, len-offset) != size)
! 	return 0;
        offset += size;
      }
    return offset;
*************** native_interpret_complex (tree type, con
*** 7534,7541 ****
  static tree
  native_interpret_vector (tree type, const unsigned char *ptr, int len)
  {
!   tree etype, elem, elements;
    int i, size, count;
  
    etype = TREE_TYPE (type);
    size = GET_MODE_SIZE (TYPE_MODE (etype));
--- 7494,7502 ----
  static tree
  native_interpret_vector (tree type, const unsigned char *ptr, int len)
  {
!   tree etype, elem;
    int i, size, count;
+   tree *elements;
  
    etype = TREE_TYPE (type);
    size = GET_MODE_SIZE (TYPE_MODE (etype));
*************** native_interpret_vector (tree type, cons
*** 7543,7555 ****
    if (size * count > len)
      return NULL_TREE;
  
!   elements = NULL_TREE;
    for (i = count - 1; i >= 0; i--)
      {
        elem = native_interpret_expr (etype, ptr+(i*size), size);
        if (!elem)
  	return NULL_TREE;
!       elements = tree_cons (NULL_TREE, elem, elements);
      }
    return build_vector (type, elements);
  }
--- 7504,7516 ----
    if (size * count > len)
      return NULL_TREE;
  
!   elements = XALLOCAVEC (tree, count);
    for (i = count - 1; i >= 0; i--)
      {
        elem = native_interpret_expr (etype, ptr+(i*size), size);
        if (!elem)
  	return NULL_TREE;
!       elements[i] = elem;
      }
    return build_vector (type, elements);
  }
*************** fold_unary_loc (location_t loc, enum tre
*** 8172,8196 ****
        /* Perform BIT_NOT_EXPR on each element individually.  */
        else if (TREE_CODE (arg0) == VECTOR_CST)
  	{
! 	  tree elements = TREE_VECTOR_CST_ELTS (arg0), elem, list = NULL_TREE;
! 	  int count = TYPE_VECTOR_SUBPARTS (type), i;
  
  	  for (i = 0; i < count; i++)
  	    {
! 	      if (elements)
! 		{
! 		  elem = TREE_VALUE (elements);
! 		  elem = fold_unary_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type), elem);
! 		  if (elem == NULL_TREE)
! 		    break;
! 		  elements = TREE_CHAIN (elements);
! 		}
! 	      else
! 		elem = build_int_cst (TREE_TYPE (type), -1);
! 	      list = tree_cons (NULL_TREE, elem, list);
  	    }
  	  if (i == count)
! 	    return build_vector (type, nreverse (list));
  	}
  
        return NULL_TREE;
--- 8133,8153 ----
        /* Perform BIT_NOT_EXPR on each element individually.  */
        else if (TREE_CODE (arg0) == VECTOR_CST)
  	{
! 	  tree *elements;
! 	  tree elem;
! 	  unsigned count = VECTOR_CST_NELTS (arg0), i;
  
+ 	  elements = XALLOCAVEC (tree, count);
  	  for (i = 0; i < count; i++)
  	    {
! 	      elem = VECTOR_CST_ELT (arg0, i);
! 	      elem = fold_unary_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type), elem);
! 	      if (elem == NULL_TREE)
! 		break;
! 	      elements[i] = elem;
  	    }
  	  if (i == count)
! 	    return build_vector (type, elements);
  	}
  
        return NULL_TREE;
*************** fold_unary_loc (location_t loc, enum tre
*** 8313,8319 ****
      case VEC_UNPACK_FLOAT_HI_EXPR:
        {
  	unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
! 	tree *elts, vals = NULL_TREE;
  	enum tree_code subcode;
  
  	gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2);
--- 8270,8276 ----
      case VEC_UNPACK_FLOAT_HI_EXPR:
        {
  	unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
! 	tree *elts;
  	enum tree_code subcode;
  
  	gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2);
*************** fold_unary_loc (location_t loc, enum tre
*** 8340,8348 ****
  	      return NULL_TREE;
  	  }
  
! 	for (i = 0; i < nelts; i++)
! 	  vals = tree_cons (NULL_TREE, elts[nelts - i - 1], vals);
! 	return build_vector (type, vals);
        }
  
      default:
--- 8297,8303 ----
  	      return NULL_TREE;
  	  }
  
! 	return build_vector (type, elts);
        }
  
      default:
*************** vec_cst_ctor_to_array (tree arg, tree *e
*** 9611,9623 ****
  
    if (TREE_CODE (arg) == VECTOR_CST)
      {
!       tree t;
! 
!       for (i = 0, t = TREE_VECTOR_CST_ELTS (arg);
! 	   i < nelts && t; i++, t = TREE_CHAIN (t))
! 	elts[i] = TREE_VALUE (t);
!       if (t)
! 	return false;
      }
    else if (TREE_CODE (arg) == CONSTRUCTOR)
      {
--- 9566,9573 ----
  
    if (TREE_CODE (arg) == VECTOR_CST)
      {
!       for (i = 0; i < VECTOR_CST_NELTS (arg); ++i)
! 	elts[i] = VECTOR_CST_ELT (arg, i);
      }
    else if (TREE_CODE (arg) == CONSTRUCTOR)
      {
*************** fold_vec_perm (tree type, tree arg0, tre
*** 9674,9685 ****
        return build_constructor (type, v);
      }
    else
!     {
!       tree vals = NULL_TREE;
!       for (i = 0; i < nelts; i++)
! 	vals = tree_cons (NULL_TREE, elts[3 * nelts - i - 1], vals);
!       return build_vector (type, vals);
!     }
  }
  
  /* Try to fold a pointer difference of type TYPE two address expressions of
--- 9624,9630 ----
        return build_constructor (type, v);
      }
    else
!     return build_vector (type, elts);
  }
  
  /* Try to fold a pointer difference of type TYPE two address expressions of
*************** fold_binary_loc (location_t loc,
*** 13577,13583 ****
      case VEC_PACK_FIX_TRUNC_EXPR:
        {
  	unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
! 	tree *elts, vals = NULL_TREE;
  
  	gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts / 2
  		    && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts / 2);
--- 13522,13528 ----
      case VEC_PACK_FIX_TRUNC_EXPR:
        {
  	unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
! 	tree *elts;
  
  	gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts / 2
  		    && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts / 2);
*************** fold_binary_loc (location_t loc,
*** 13598,13613 ****
  	      return NULL_TREE;
  	  }
  
! 	for (i = 0; i < nelts; i++)
! 	  vals = tree_cons (NULL_TREE, elts[nelts - i - 1], vals);
! 	return build_vector (type, vals);
        }
  
      case VEC_WIDEN_MULT_LO_EXPR:
      case VEC_WIDEN_MULT_HI_EXPR:
        {
  	unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
! 	tree *elts, vals = NULL_TREE;
  
  	gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2
  		    && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts * 2);
--- 13543,13556 ----
  	      return NULL_TREE;
  	  }
  
! 	return build_vector (type, elts);
        }
  
      case VEC_WIDEN_MULT_LO_EXPR:
      case VEC_WIDEN_MULT_HI_EXPR:
        {
  	unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
! 	tree *elts;
  
  	gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2
  		    && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts * 2);
*************** fold_binary_loc (location_t loc,
*** 13635,13643 ****
  	      return NULL_TREE;
  	  }
  
! 	for (i = 0; i < nelts; i++)
! 	  vals = tree_cons (NULL_TREE, elts[nelts - i - 1], vals);
! 	return build_vector (type, vals);
        }
  
      default:
--- 13578,13584 ----
  	      return NULL_TREE;
  	  }
  
! 	return build_vector (type, elts);
        }
  
      default:
*************** fold_ternary_loc (location_t loc, enum t
*** 13994,14006 ****
  		 < TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)))
  	    {
  	      if (TREE_CODE (arg0) == VECTOR_CST)
! 		{
! 		  tree elements = TREE_VECTOR_CST_ELTS (arg0);
! 		  while (idx-- > 0 && elements)
! 		    elements = TREE_CHAIN (elements);
! 		  if (elements)
! 		    return TREE_VALUE (elements);
! 		}
  	      else if (idx < CONSTRUCTOR_NELTS (arg0))
  		return CONSTRUCTOR_ELT (arg0, idx)->value;
  	      return build_zero_cst (type);
--- 13935,13941 ----
  		 < TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)))
  	    {
  	      if (TREE_CODE (arg0) == VECTOR_CST)
! 		return VECTOR_CST_ELT (arg0, idx);
  	      else if (idx < CONSTRUCTOR_NELTS (arg0))
  		return CONSTRUCTOR_ELT (arg0, idx)->value;
  	      return build_zero_cst (type);
*************** fold_ternary_loc (location_t loc, enum t
*** 14034,14056 ****
  	  tree t;
  	  bool need_mask_canon = false;
  
! 	  gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2)));
! 	  for (i = 0, t = TREE_VECTOR_CST_ELTS (arg2);
! 	       i < nelts && t; i++, t = TREE_CHAIN (t))
  	    {
! 	      if (TREE_CODE (TREE_VALUE (t)) != INTEGER_CST)
  		return NULL_TREE;
  
! 	      sel[i] = TREE_INT_CST_LOW (TREE_VALUE (t)) & (2 * nelts - 1);
! 	      if (TREE_INT_CST_HIGH (TREE_VALUE (t))
  		  || ((unsigned HOST_WIDE_INT)
! 		      TREE_INT_CST_LOW (TREE_VALUE (t)) != sel[i]))
  		need_mask_canon = true;
  	    }
- 	  if (t)
- 	    return NULL_TREE;
- 	  for (; i < nelts; i++)
- 	    sel[i] = 0;
  
  	  if ((TREE_CODE (arg0) == VECTOR_CST
  	       || TREE_CODE (arg0) == CONSTRUCTOR)
--- 13969,13987 ----
  	  tree t;
  	  bool need_mask_canon = false;
  
! 	  gcc_assert (nelts == VECTOR_CST_NELTS (arg2));
! 	  for (i = 0; i < nelts; i++)
  	    {
! 	      tree val = VECTOR_CST_ELT (arg2, i);
! 	      if (TREE_CODE (val) != INTEGER_CST)
  		return NULL_TREE;
  
! 	      sel[i] = TREE_INT_CST_LOW (val) & (2 * nelts - 1);
! 	      if (TREE_INT_CST_HIGH (val)
  		  || ((unsigned HOST_WIDE_INT)
! 		      TREE_INT_CST_LOW (val) != sel[i]))
  		need_mask_canon = true;
  	    }
  
  	  if ((TREE_CODE (arg0) == VECTOR_CST
  	       || TREE_CODE (arg0) == CONSTRUCTOR)
*************** fold_ternary_loc (location_t loc, enum t
*** 14064,14075 ****
  
  	  if (need_mask_canon && arg2 == op2)
  	    {
! 	      tree list = NULL_TREE, eltype = TREE_TYPE (TREE_TYPE (arg2));
  	      for (i = 0; i < nelts; i++)
! 		list = tree_cons (NULL_TREE,
! 				  build_int_cst (eltype, sel[nelts - i - 1]),
! 				  list);
! 	      t = build_vector (TREE_TYPE (arg2), list);
  	      return build3_loc (loc, VEC_PERM_EXPR, type, op0, op1, t);
  	    }
  	}
--- 13995,14005 ----
  
  	  if (need_mask_canon && arg2 == op2)
  	    {
! 	      tree *tsel = XALLOCAVEC (tree, nelts);
! 	      tree eltype = TREE_TYPE (TREE_TYPE (arg2));
  	      for (i = 0; i < nelts; i++)
! 		tsel[i] = build_int_cst (eltype, sel[nelts - i - 1]);
! 	      t = build_vector (TREE_TYPE (arg2), tsel);
  	      return build3_loc (loc, VEC_PERM_EXPR, type, op0, op1, t);
  	    }
  	}
Index: gcc/tree-streamer-in.c
===================================================================
*** gcc/tree-streamer-in.c.orig	2012-03-15 11:14:26.000000000 +0100
--- gcc/tree-streamer-in.c	2012-03-15 11:57:19.000000000 +0100
*************** streamer_alloc_tree (struct lto_input_bl
*** 473,478 ****
--- 473,486 ----
        HOST_WIDE_INT len = streamer_read_hwi (ib);
        result = make_tree_vec (len);
      }
+   else if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
+     {
+       HOST_WIDE_INT len = streamer_read_hwi (ib);
+       result = ggc_alloc_zone_cleared_tree_node_stat (&tree_zone,
+ 						      (len - 1) * sizeof (tree)
+ 						      + sizeof (struct tree_vector));
+       TREE_SET_CODE (result, VECTOR_CST);
+     }
    else if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
      {
        unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
*************** static void
*** 525,531 ****
  lto_input_ts_vector_tree_pointers (struct lto_input_block *ib,
  				   struct data_in *data_in, tree expr)
  {
!   TREE_VECTOR_CST_ELTS (expr) = streamer_read_chain (ib, data_in);
  }
  
  
--- 533,541 ----
  lto_input_ts_vector_tree_pointers (struct lto_input_block *ib,
  				   struct data_in *data_in, tree expr)
  {
!   unsigned i;
!   for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
!     VECTOR_CST_ELT (expr, i) = stream_read_tree (ib, data_in);
  }
  
  
Index: gcc/tree-streamer-out.c
===================================================================
*** gcc/tree-streamer-out.c.orig	2012-03-15 11:14:26.000000000 +0100
--- gcc/tree-streamer-out.c	2012-03-15 11:57:49.000000000 +0100
*************** write_ts_common_tree_pointers (struct ou
*** 441,447 ****
  static void
  write_ts_vector_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
  {
!   streamer_write_chain (ob, TREE_VECTOR_CST_ELTS (expr), ref_p);
  }
  
  
--- 441,451 ----
  static void
  write_ts_vector_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
  {
!   unsigned i;
!   /* Note that the number of elements for EXPR has already been emitted
!      in EXPR's header (see streamer_write_tree_header).  */
!   for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
!     stream_write_tree (ob, VECTOR_CST_ELT (expr, i), ref_p);
  }
  
  
*************** streamer_write_tree_header (struct outpu
*** 907,912 ****
--- 911,918 ----
      streamer_write_string_cst (ob, ob->main_stream, expr);
    else if (CODE_CONTAINS_STRUCT (code, TS_IDENTIFIER))
      write_identifier (ob, ob->main_stream, expr);
+   else if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
+     streamer_write_hwi (ob, VECTOR_CST_NELTS (expr));
    else if (CODE_CONTAINS_STRUCT (code, TS_VEC))
      streamer_write_hwi (ob, TREE_VEC_LENGTH (expr));
    else if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
Index: gcc/varasm.c
===================================================================
*** gcc/varasm.c.orig	2012-03-15 11:14:26.000000000 +0100
--- gcc/varasm.c	2012-03-15 12:29:56.000000000 +0100
*************** const_hash_1 (const tree exp)
*** 2706,2717 ****
  
      case VECTOR_CST:
        {
! 	tree link;
  
! 	hi = 7 + TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp));
  
! 	for (link = TREE_VECTOR_CST_ELTS (exp); link; link = TREE_CHAIN (link))
! 	    hi = hi * 563 + const_hash_1 (TREE_VALUE (link));
  
  	return hi;
        }
--- 2706,2717 ----
  
      case VECTOR_CST:
        {
! 	unsigned i;
  
! 	hi = 7 + VECTOR_CST_NELTS (exp);
  
! 	for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
! 	  hi = hi * 563 + const_hash_1 (VECTOR_CST_ELT (exp, i));
  
  	return hi;
        }
*************** compare_constant (const tree t1, const t
*** 2846,2866 ****
  
      case VECTOR_CST:
        {
!         tree link1, link2;
  
!         if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1))
! 	    != TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2)))
  	  return 0;
  
! 	link2 = TREE_VECTOR_CST_ELTS (t2);
! 	for (link1 = TREE_VECTOR_CST_ELTS (t1);
! 	     link1;
! 	     link1 = TREE_CHAIN (link1))
! 	  {
! 	    if (!compare_constant (TREE_VALUE (link1), TREE_VALUE (link2)))
! 	      return 0;
! 	    link2 = TREE_CHAIN (link2);
! 	  }
  
  	return 1;
        }
--- 2846,2860 ----
  
      case VECTOR_CST:
        {
! 	unsigned i;
  
!         if (VECTOR_CST_NELTS (t1) != VECTOR_CST_NELTS (t2))
  	  return 0;
  
! 	for (i = 0; i < VECTOR_CST_NELTS (t1); ++i)
! 	  if (!compare_constant (VECTOR_CST_ELT (t1, i),
! 				 VECTOR_CST_ELT (t2, i)))
! 	    return 0;
  
  	return 1;
        }
*************** copy_constant (tree exp)
*** 3014,3021 ****
  		     copy_constant (TREE_OPERAND (exp, 0)));
  
      case VECTOR_CST:
!       return build_vector (TREE_TYPE (exp),
! 			   copy_list (TREE_VECTOR_CST_ELTS (exp)));
  
      case CONSTRUCTOR:
        {
--- 3008,3014 ----
  		     copy_constant (TREE_OPERAND (exp, 0)));
  
      case VECTOR_CST:
!       return build_vector (TREE_TYPE (exp), VECTOR_CST_ELTS (exp));
  
      case CONSTRUCTOR:
        {
*************** output_constant (tree exp, unsigned HOST
*** 4595,4602 ****
  	case VECTOR_CST:
  	  {
  	    int elt_size;
! 	    tree link;
! 	    unsigned int nalign;
  	    enum machine_mode inner;
  
  	    inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
--- 4588,4594 ----
  	case VECTOR_CST:
  	  {
  	    int elt_size;
! 	    unsigned int i, nalign;
  	    enum machine_mode inner;
  
  	    inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
*************** output_constant (tree exp, unsigned HOST
*** 4604,4615 ****
  
  	    elt_size = GET_MODE_SIZE (inner);
  
! 	    link = TREE_VECTOR_CST_ELTS (exp);
! 	    output_constant (TREE_VALUE (link), elt_size, align);
! 	    thissize = elt_size;
! 	    while ((link = TREE_CHAIN (link)) != NULL)
  	      {
! 		output_constant (TREE_VALUE (link), elt_size, nalign);
  		thissize += elt_size;
  	      }
  	    break;
--- 4596,4606 ----
  
  	    elt_size = GET_MODE_SIZE (inner);
  
! 	    thissize = 0;
! 	    output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align);
! 	    for (i = 1; i < VECTOR_CST_NELTS (exp); ++i)
  	      {
! 		output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign);
  		thissize += elt_size;
  	      }
  	    break;
Index: gcc/config/i386/i386.c
===================================================================
*** gcc/config/i386/i386.c.orig	2012-03-15 11:15:38.000000000 +0100
--- gcc/config/i386/i386.c	2012-03-15 12:31:10.000000000 +0100
*************** rdrand_step:
*** 29653,29664 ****
  	{
  	  if (TREE_CODE (arg3) == VECTOR_CST)
  	    {
- 	      tree elt;
  	      unsigned int negative = 0;
! 	      for (elt = TREE_VECTOR_CST_ELTS (arg3);
! 		   elt; elt = TREE_CHAIN (elt))
  		{
! 		  tree cst = TREE_VALUE (elt);
  		  if (TREE_CODE (cst) == INTEGER_CST
  		      && tree_int_cst_sign_bit (cst))
  		    negative++;
--- 29653,29662 ----
  	{
  	  if (TREE_CODE (arg3) == VECTOR_CST)
  	    {
  	      unsigned int negative = 0;
! 	      for (i = 0; i < VECTOR_CST_NELTS (arg3); ++i)
  		{
! 		  tree cst = VECTOR_CST_ELT (arg3, i);
  		  if (TREE_CODE (cst) == INTEGER_CST
  		      && tree_int_cst_sign_bit (cst))
  		    negative++;
Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c.orig	2012-03-14 12:00:57.000000000 +0100
--- gcc/gimple-fold.c	2012-03-15 11:43:03.000000000 +0100
*************** gimple_fold_stmt_to_constant_1 (gimple s
*** 2467,2487 ****
  			   == TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs))))
  		{
  		  unsigned i;
! 		  tree val, list;
  
! 		  list = NULL_TREE;
  		  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
  		    {
  		      val = (*valueize) (val);
  		      if (TREE_CODE (val) == INTEGER_CST
  			  || TREE_CODE (val) == REAL_CST
  			  || TREE_CODE (val) == FIXED_CST)
! 			list = tree_cons (NULL_TREE, val, list);
  		      else
  			return NULL_TREE;
  		    }
  
! 		  return build_vector (TREE_TYPE (rhs), nreverse (list));
  		}
  
                if (kind == tcc_reference)
--- 2467,2488 ----
  			   == TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs))))
  		{
  		  unsigned i;
! 		  tree val, *vec;
  
! 		  vec = XALLOCAVEC (tree,
! 				    TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs)));
  		  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
  		    {
  		      val = (*valueize) (val);
  		      if (TREE_CODE (val) == INTEGER_CST
  			  || TREE_CODE (val) == REAL_CST
  			  || TREE_CODE (val) == FIXED_CST)
! 			vec[i] = val;
  		      else
  			return NULL_TREE;
  		    }
  
! 		  return build_vector (TREE_TYPE (rhs), vec);
  		}
  
                if (kind == tcc_reference)
Index: gcc/print-tree.c
===================================================================
*** gcc/print-tree.c.orig	2011-11-08 12:17:12.000000000 +0100
--- gcc/print-tree.c	2012-03-15 11:46:28.000000000 +0100
*************** print_node (FILE *file, const char *pref
*** 821,836 ****
  
  	case VECTOR_CST:
  	  {
- 	    tree vals = TREE_VECTOR_CST_ELTS (node);
  	    char buf[10];
! 	    tree link;
! 	    int i;
  
! 	    i = 0;
! 	    for (link = vals; link; link = TREE_CHAIN (link), ++i)
  	      {
! 		sprintf (buf, "elt%d: ", i);
! 		print_node (file, buf, TREE_VALUE (link), indent + 4);
  	      }
  	  }
  	  break;
--- 821,833 ----
  
  	case VECTOR_CST:
  	  {
  	    char buf[10];
! 	    unsigned i;
  
! 	    for (i = 0; i < VECTOR_CST_NELTS (node); ++i)
  	      {
! 		sprintf (buf, "elt%u: ", i);
! 		print_node (file, buf, VECTOR_CST_ELT (node, i), indent + 4);
  	      }
  	  }
  	  break;
Index: gcc/tree-pretty-print.c
===================================================================
*** gcc/tree-pretty-print.c.orig	2012-03-12 14:05:44.000000000 +0100
--- gcc/tree-pretty-print.c	2012-03-15 11:49:34.000000000 +0100
*************** dump_generic_node (pretty_printer *buffe
*** 1112,1124 ****
  
      case VECTOR_CST:
        {
! 	tree elt;
  	pp_string (buffer, "{ ");
! 	for (elt = TREE_VECTOR_CST_ELTS (node); elt; elt = TREE_CHAIN (elt))
  	  {
! 	    dump_generic_node (buffer, TREE_VALUE (elt), spc, flags, false);
! 	    if (TREE_CHAIN (elt))
  	      pp_string (buffer, ", ");
  	  }
  	pp_string (buffer, " }");
        }
--- 1112,1125 ----
  
      case VECTOR_CST:
        {
! 	unsigned i;
  	pp_string (buffer, "{ ");
! 	for (i = 0; i < VECTOR_CST_NELTS (node); ++i)
  	  {
! 	    if (i != 0)
  	      pp_string (buffer, ", ");
+ 	    dump_generic_node (buffer, VECTOR_CST_ELT (node, i),
+ 			       spc, flags, false);
  	  }
  	pp_string (buffer, " }");
        }
Index: gcc/tree-vect-generic.c
===================================================================
*** gcc/tree-vect-generic.c.orig	2012-03-14 14:45:52.000000000 +0100
--- gcc/tree-vect-generic.c	2012-03-15 12:03:30.000000000 +0100
*************** expand_vector_addition (gimple_stmt_iter
*** 334,340 ****
  static tree
  uniform_vector_p (tree vec)
  {
!   tree first, t, els;
    unsigned i;
  
    if (vec == NULL_TREE)
--- 334,340 ----
  static tree
  uniform_vector_p (tree vec)
  {
!   tree first, t;
    unsigned i;
  
    if (vec == NULL_TREE)
*************** uniform_vector_p (tree vec)
*** 342,353 ****
  
    if (TREE_CODE (vec) == VECTOR_CST)
      {
!       els = TREE_VECTOR_CST_ELTS (vec);
!       first = TREE_VALUE (els);
!       els = TREE_CHAIN (els);
! 
!       for (t = els; t; t = TREE_CHAIN (t))
! 	if (!operand_equal_p (first, TREE_VALUE (t), 0))
  	  return NULL_TREE;
  
        return first;
--- 342,350 ----
  
    if (TREE_CODE (vec) == VECTOR_CST)
      {
!       first = VECTOR_CST_ELT (vec, 0);
!       for (i = 1; i < VECTOR_CST_NELTS (vec); ++i)
! 	if (!operand_equal_p (first, VECTOR_CST_ELT (vec, i), 0))
  	  return NULL_TREE;
  
        return first;
*************** vector_element (gimple_stmt_iterator *gs
*** 556,569 ****
  	}
  
        if (TREE_CODE (vect) == VECTOR_CST)
!         {
! 	  unsigned i;
! 	  tree vals = TREE_VECTOR_CST_ELTS (vect);
! 	  for (i = 0; vals; vals = TREE_CHAIN (vals), ++i)
! 	    if (i == index)
! 	       return TREE_VALUE (vals);
! 	  return build_zero_cst (vect_elt_type);
!         }
        else if (TREE_CODE (vect) == CONSTRUCTOR)
          {
            unsigned i;
--- 553,559 ----
  	}
  
        if (TREE_CODE (vect) == VECTOR_CST)
! 	return VECTOR_CST_ELT (vect, index);
        else if (TREE_CODE (vect) == CONSTRUCTOR)
          {
            unsigned i;
*************** lower_vec_perm (gimple_stmt_iterator *gs
*** 640,649 ****
    if (TREE_CODE (mask) == VECTOR_CST)
      {
        unsigned char *sel_int = XALLOCAVEC (unsigned char, elements);
-       tree vals = TREE_VECTOR_CST_ELTS (mask);
  
!       for (i = 0; i < elements; ++i, vals = TREE_CHAIN (vals))
! 	sel_int[i] = TREE_INT_CST_LOW (TREE_VALUE (vals)) & (2 * elements - 1);
  
        if (can_vec_perm_p (TYPE_MODE (vect_type), false, sel_int))
  	return;
--- 630,639 ----
    if (TREE_CODE (mask) == VECTOR_CST)
      {
        unsigned char *sel_int = XALLOCAVEC (unsigned char, elements);
  
!       for (i = 0; i < elements; ++i)
! 	sel_int[i] = (TREE_INT_CST_LOW (VECTOR_CST_ELT (mask, i))
! 		      & (2 * elements - 1));
  
        if (can_vec_perm_p (TYPE_MODE (vect_type), false, sel_int))
  	return;
Index: gcc/tree-vect-loop.c
===================================================================
*** gcc/tree-vect-loop.c.orig	2012-02-20 15:15:07.000000000 +0100
--- gcc/tree-vect-loop.c	2012-03-15 12:10:54.000000000 +0100
*************** get_initial_def_for_reduction (gimple st
*** 3305,3311 ****
    enum tree_code code = gimple_assign_rhs_code (stmt);
    tree def_for_init;
    tree init_def;
!   tree t = NULL_TREE;
    int i;
    bool nested_in_vect_loop = false;
    tree init_value;
--- 3305,3311 ----
    enum tree_code code = gimple_assign_rhs_code (stmt);
    tree def_for_init;
    tree init_def;
!   tree *elts;
    int i;
    bool nested_in_vect_loop = false;
    tree init_value;
*************** get_initial_def_for_reduction (gimple st
*** 3386,3408 ****
            def_for_init = build_int_cst (scalar_type, int_init_val);
  
          /* Create a vector of '0' or '1' except the first element.  */
          for (i = nunits - 2; i >= 0; --i)
!           t = tree_cons (NULL_TREE, def_for_init, t);
  
          /* Option1: the first element is '0' or '1' as well.  */
          if (adjustment_def)
            {
!             t = tree_cons (NULL_TREE, def_for_init, t);
!             init_def = build_vector (vectype, t);
              break;
            }
  
          /* Option2: the first element is INIT_VAL.  */
!         t = tree_cons (NULL_TREE, init_value, t);
          if (TREE_CONSTANT (init_val))
!           init_def = build_vector (vectype, t);
          else
!           init_def = build_constructor_from_list (vectype, t);
  
          break;
  
--- 3386,3416 ----
            def_for_init = build_int_cst (scalar_type, int_init_val);
  
          /* Create a vector of '0' or '1' except the first element.  */
+ 	elts = XALLOCAVEC (tree, nunits);
          for (i = nunits - 2; i >= 0; --i)
! 	  elts[i + 1] = def_for_init;
  
          /* Option1: the first element is '0' or '1' as well.  */
          if (adjustment_def)
            {
! 	    elts[0] = def_for_init;
!             init_def = build_vector (vectype, elts);
              break;
            }
  
          /* Option2: the first element is INIT_VAL.  */
! 	elts[0] = init_val;
          if (TREE_CONSTANT (init_val))
!           init_def = build_vector (vectype, elts);
          else
! 	  {
! 	    VEC(constructor_elt,gc) *v;
! 	    v = VEC_alloc (constructor_elt, gc, nunits);
! 	    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_val);
! 	    for (i = 1; i < nunits; ++i)
! 	      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]);
! 	    init_def = build_constructor (vectype, v);
! 	  }
  
          break;
  
Index: gcc/tree-vect-slp.c
===================================================================
*** gcc/tree-vect-slp.c.orig	2012-03-07 12:59:39.000000000 +0100
--- gcc/tree-vect-slp.c	2012-03-15 12:20:59.000000000 +0100
*************** vect_get_constant_vectors (tree op, slp_
*** 2201,2215 ****
    VEC (gimple, heap) *stmts = SLP_TREE_SCALAR_STMTS (slp_node);
    gimple stmt = VEC_index (gimple, stmts, 0);
    stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
!   int nunits;
    tree vec_cst;
!   tree t = NULL_TREE;
!   int j, number_of_places_left_in_vector;
    tree vector_type;
    tree vop;
    int group_size = VEC_length (gimple, stmts);
    unsigned int vec_num, i;
!   int number_of_copies = 1;
    VEC (tree, heap) *voprnds = VEC_alloc (tree, heap, number_of_vectors);
    bool constant_p, is_store;
    tree neutral_op = NULL;
--- 2201,2215 ----
    VEC (gimple, heap) *stmts = SLP_TREE_SCALAR_STMTS (slp_node);
    gimple stmt = VEC_index (gimple, stmts, 0);
    stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
!   unsigned nunits;
    tree vec_cst;
!   tree *elts;
!   unsigned j, number_of_places_left_in_vector;
    tree vector_type;
    tree vop;
    int group_size = VEC_length (gimple, stmts);
    unsigned int vec_num, i;
!   unsigned number_of_copies = 1;
    VEC (tree, heap) *voprnds = VEC_alloc (tree, heap, number_of_vectors);
    bool constant_p, is_store;
    tree neutral_op = NULL;
*************** vect_get_constant_vectors (tree op, slp_
*** 2303,2308 ****
--- 2303,2309 ----
    number_of_copies = least_common_multiple (nunits, group_size) / group_size;
  
    number_of_places_left_in_vector = nunits;
+   elts = XALLOCAVEC (tree, nunits);
    for (j = 0; j < number_of_copies; j++)
      {
        for (i = group_size - 1; VEC_iterate (gimple, stmts, i, stmt); i--)
*************** vect_get_constant_vectors (tree op, slp_
*** 2357,2377 ****
              }
  
            /* Create 'vect_ = {op0,op1,...,opn}'.  */
-           t = tree_cons (NULL_TREE, op, t);
- 
            number_of_places_left_in_vector--;
  
            if (number_of_places_left_in_vector == 0)
              {
                number_of_places_left_in_vector = nunits;
  
  	      if (constant_p)
! 		vec_cst = build_vector (vector_type, t);
  	      else
! 		vec_cst = build_constructor_from_list (vector_type, t);
                VEC_quick_push (tree, voprnds,
!                               vect_init_vector (stmt, vec_cst, vector_type, NULL));
!               t = NULL_TREE;
              }
          }
      }
--- 2358,2384 ----
              }
  
            /* Create 'vect_ = {op0,op1,...,opn}'.  */
            number_of_places_left_in_vector--;
+ 	  elts[number_of_places_left_in_vector] = op;
  
            if (number_of_places_left_in_vector == 0)
              {
                number_of_places_left_in_vector = nunits;
  
  	      if (constant_p)
! 		vec_cst = build_vector (vector_type, elts);
  	      else
! 		{
! 		  VEC(constructor_elt,gc) *v;
! 		  unsigned k;
! 		  v = VEC_alloc (constructor_elt, gc, nunits);
! 		  for (k = 0; k < nunits; ++k)
! 		    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[k]);
! 		  vec_cst = build_constructor (vector_type, v);
! 		}
                VEC_quick_push (tree, voprnds,
!                               vect_init_vector (stmt, vec_cst,
! 						vector_type, NULL));
              }
          }
      }
*************** vect_get_constant_vectors (tree op, slp_
*** 2379,2387 ****
    /* Since the vectors are created in the reverse order, we should invert
       them.  */
    vec_num = VEC_length (tree, voprnds);
!   for (j = vec_num - 1; j >= 0; j--)
      {
!       vop = VEC_index (tree, voprnds, j);
        VEC_quick_push (tree, *vec_oprnds, vop);
      }
  
--- 2386,2394 ----
    /* Since the vectors are created in the reverse order, we should invert
       them.  */
    vec_num = VEC_length (tree, voprnds);
!   for (j = vec_num; j != 0; j--)
      {
!       vop = VEC_index (tree, voprnds, j - 1);
        VEC_quick_push (tree, *vec_oprnds, vop);
      }
  
*************** vect_transform_slp_perm_load (gimple stm
*** 2773,2779 ****
  
                if (index == nunits)
                  {
! 		  tree mask_vec = NULL;
  
  		  if (!can_vec_perm_p (mode, false, mask))
  		    {
--- 2780,2787 ----
  
                if (index == nunits)
                  {
! 		  tree mask_vec, *mask_elts;
! 		  int l;
  
  		  if (!can_vec_perm_p (mode, false, mask))
  		    {
*************** vect_transform_slp_perm_load (gimple stm
*** 2787,2798 ****
  		      return false;
  		    }
  
! 		  while (--index >= 0)
! 		    {
! 		      tree t = build_int_cst (mask_element_type, mask[index]);
! 		      mask_vec = tree_cons (NULL, t, mask_vec);
! 		    }
! 		  mask_vec = build_vector (mask_type, mask_vec);
  		  index = 0;
  
                    if (!analyze_only)
--- 2795,2805 ----
  		      return false;
  		    }
  
! 		  mask_elts = XALLOCAVEC (tree, nunits);
! 		  for (l = 0; l < nunits; ++l)
! 		    mask_elts[l] = build_int_cst (mask_element_type,
! 						  mask[index]);
! 		  mask_vec = build_vector (mask_type, mask_elts);
  		  index = 0;
  
                    if (!analyze_only)
Index: gcc/tree-vect-stmts.c
===================================================================
*** gcc/tree-vect-stmts.c.orig	2012-03-07 12:58:34.000000000 +0100
--- gcc/tree-vect-stmts.c	2012-03-15 12:05:25.000000000 +0100
*************** vectorizable_store (gimple stmt, gimple_
*** 4091,4097 ****
  tree
  vect_gen_perm_mask (tree vectype, unsigned char *sel)
  {
!   tree mask_elt_type, mask_type, mask_vec;
    int i, nunits;
  
    nunits = TYPE_VECTOR_SUBPARTS (vectype);
--- 4091,4097 ----
  tree
  vect_gen_perm_mask (tree vectype, unsigned char *sel)
  {
!   tree mask_elt_type, mask_type, mask_vec, *mask_elts;
    int i, nunits;
  
    nunits = TYPE_VECTOR_SUBPARTS (vectype);
*************** vect_gen_perm_mask (tree vectype, unsign
*** 4103,4113 ****
  		    (int_mode_for_mode (TYPE_MODE (TREE_TYPE (vectype))), 1);
    mask_type = get_vectype_for_scalar_type (mask_elt_type);
  
!   mask_vec = NULL;
    for (i = nunits - 1; i >= 0; i--)
!     mask_vec = tree_cons (NULL, build_int_cst (mask_elt_type, sel[i]),
! 			  mask_vec);
!   mask_vec = build_vector (mask_type, mask_vec);
  
    return mask_vec;
  }
--- 4103,4112 ----
  		    (int_mode_for_mode (TYPE_MODE (TREE_TYPE (vectype))), 1);
    mask_type = get_vectype_for_scalar_type (mask_elt_type);
  
!   mask_elts = XALLOCAVEC (tree, nunits);
    for (i = nunits - 1; i >= 0; i--)
!     mask_elts[i] = build_int_cst (mask_elt_type, sel[i]);
!   mask_vec = build_vector (mask_type, mask_elts);
  
    return mask_vec;
  }
Index: gcc/config/sparc/sparc.c
===================================================================
*** gcc/config/sparc/sparc.c.orig	2012-02-13 12:08:36.000000000 +0100
--- gcc/config/sparc/sparc.c	2012-03-15 13:18:56.000000000 +0100
*************** static void sparc_vis_init_builtins (voi
*** 514,520 ****
  static rtx sparc_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
  static tree sparc_fold_builtin (tree, int, tree *, bool);
  static int sparc_vis_mul8x16 (int, int);
! static tree sparc_handle_vis_mul8x16 (int, tree, tree, tree);
  static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
  				   HOST_WIDE_INT, tree);
  static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT,
--- 514,520 ----
  static rtx sparc_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
  static tree sparc_fold_builtin (tree, int, tree *, bool);
  static int sparc_vis_mul8x16 (int, int);
! static void sparc_handle_vis_mul8x16 (tree *, int, tree, tree, tree);
  static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
  				   HOST_WIDE_INT, tree);
  static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT,
*************** sparc_vis_mul8x16 (int e8, int e16)
*** 9899,9963 ****
  
  /* Multiply the vector elements in ELTS0 to the elements in ELTS1 as specified
     by FNCODE.  All of the elements in ELTS0 and ELTS1 lists must be integer
!    constants.  A tree list with the results of the multiplications is returned,
!    and each element in the list is of INNER_TYPE.  */
  
! static tree
! sparc_handle_vis_mul8x16 (int fncode, tree inner_type, tree elts0, tree elts1)
  {
!   tree n_elts = NULL_TREE;
    int scale;
  
    switch (fncode)
      {
      case CODE_FOR_fmul8x16_vis:
!       for (; elts0 && elts1;
! 	   elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
  	{
  	  int val
! 	    = sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
! 				 TREE_INT_CST_LOW (TREE_VALUE (elts1)));
! 	  n_elts = tree_cons (NULL_TREE,
! 			      build_int_cst (inner_type, val),
! 			      n_elts);
  	}
        break;
  
      case CODE_FOR_fmul8x16au_vis:
!       scale = TREE_INT_CST_LOW (TREE_VALUE (elts1));
  
!       for (; elts0; elts0 = TREE_CHAIN (elts0))
  	{
  	  int val
! 	    = sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
  				 scale);
! 	  n_elts = tree_cons (NULL_TREE,
! 			      build_int_cst (inner_type, val),
! 			      n_elts);
  	}
        break;
  
      case CODE_FOR_fmul8x16al_vis:
!       scale = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (elts1)));
  
!       for (; elts0; elts0 = TREE_CHAIN (elts0))
  	{
  	  int val
! 	    = sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
  				 scale);
! 	  n_elts = tree_cons (NULL_TREE,
! 			      build_int_cst (inner_type, val),
! 			      n_elts);
  	}
        break;
  
      default:
        gcc_unreachable ();
      }
- 
-   return nreverse (n_elts);
- 
  }
  /* Handle TARGET_FOLD_BUILTIN target hook.
     Fold builtin functions for SPARC intrinsics.  If IGNORE is true the
     result of the function call is ignored.  NULL_TREE is returned if the
--- 9899,9955 ----
  
  /* Multiply the vector elements in ELTS0 to the elements in ELTS1 as specified
     by FNCODE.  All of the elements in ELTS0 and ELTS1 lists must be integer
!    constants.  A tree list with the results of the multiplications is stored
!    to the array *N_ELTS, and each element in the list is of INNER_TYPE.  */
  
! static void
! sparc_handle_vis_mul8x16 (tree *n_elts, int fncode, tree inner_type,
! 			  tree elts0, tree elts1)
  {
!   unsigned i, num = VECTOR_CST_NELTS (elts0);
    int scale;
  
    switch (fncode)
      {
      case CODE_FOR_fmul8x16_vis:
!       for (i = 0; i < num; ++i)
  	{
  	  int val
! 	    = sparc_vis_mul8x16 (TREE_INT_CST_LOW (VECTOR_CST_ELT (elts0, i)),
! 				 TREE_INT_CST_LOW (VECTOR_CST_ELT (elts1, i)));
! 	  n_elts[i] = build_int_cst (inner_type, val);
  	}
        break;
  
      case CODE_FOR_fmul8x16au_vis:
!       scale = TREE_INT_CST_LOW (VECTOR_CST_ELT (elts1, 0));
  
!       for (i = 0; i < num; ++i)
  	{
  	  int val
! 	    = sparc_vis_mul8x16 (TREE_INT_CST_LOW (VECTOR_CST_ELT (elts0, i)),
  				 scale);
! 	  n_elts[i] = build_int_cst (inner_type, val);
  	}
        break;
  
      case CODE_FOR_fmul8x16al_vis:
!       scale = TREE_INT_CST_LOW (VECTOR_CST_ELT (elts1, 0));
  
!       for (i = 0; i < num; ++i)
  	{
  	  int val
! 	    = sparc_vis_mul8x16 (TREE_INT_CST_LOW (VECTOR_CST_ELT (elts0, i)),
  				 scale);
! 	  n_elts[i] = build_int_cst (inner_type, val);
  	}
        break;
  
      default:
        gcc_unreachable ();
      }
  }
+ 
  /* Handle TARGET_FOLD_BUILTIN target hook.
     Fold builtin functions for SPARC intrinsics.  If IGNORE is true the
     result of the function call is ignored.  NULL_TREE is returned if the
*************** sparc_fold_builtin (tree fndecl, int n_a
*** 10001,10017 ****
        if (TREE_CODE (arg0) == VECTOR_CST)
  	{
  	  tree inner_type = TREE_TYPE (rtype);
! 	  tree elts = TREE_VECTOR_CST_ELTS (arg0);
! 	  tree n_elts = NULL_TREE;
  
! 	  for (; elts; elts = TREE_CHAIN (elts))
! 	    {
! 	      unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (elts)) << 4;
! 	      n_elts = tree_cons (NULL_TREE,
! 				  build_int_cst (inner_type, val),
! 				  n_elts);
! 	    }
! 	  return build_vector (rtype, nreverse (n_elts));
  	}
        break;
  
--- 9993,10007 ----
        if (TREE_CODE (arg0) == VECTOR_CST)
  	{
  	  tree inner_type = TREE_TYPE (rtype);
! 	  tree *n_elts;
! 	  unsigned i;
  
! 	  n_elts = XALLOCAVEC (tree, VECTOR_CST_NELTS (arg0));
! 	  for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)
! 	    n_elts[i] = build_int_cst (inner_type,
! 				       TREE_INT_CST_LOW
! 				         (VECTOR_CST_ELT (arg0, i)) << 4);
! 	  return build_vector (rtype, n_elts);
  	}
        break;
  
*************** sparc_fold_builtin (tree fndecl, int n_a
*** 10026,10036 ****
        if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
  	{
  	  tree inner_type = TREE_TYPE (rtype);
! 	  tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
! 	  tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
! 	  tree n_elts = sparc_handle_vis_mul8x16 (icode, inner_type, elts0,
! 						  elts1);
! 
  	  return build_vector (rtype, n_elts);
  	}
        break;
--- 10016,10023 ----
        if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
  	{
  	  tree inner_type = TREE_TYPE (rtype);
! 	  tree *n_elts = XALLOCAVEC (tree, VECTOR_CST_NELTS (arg0));
! 	  sparc_handle_vis_mul8x16 (n_elts, icode, inner_type, arg0, arg1);
  	  return build_vector (rtype, n_elts);
  	}
        break;
*************** sparc_fold_builtin (tree fndecl, int n_a
*** 10043,10060 ****
  
        if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
  	{
! 	  tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
! 	  tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
! 	  tree n_elts = NULL_TREE;
! 
! 	  for (; elts0 && elts1;
! 	       elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
  	    {
! 	      n_elts = tree_cons (NULL_TREE, TREE_VALUE (elts0), n_elts);
! 	      n_elts = tree_cons (NULL_TREE, TREE_VALUE (elts1), n_elts);
  	    }
  
! 	  return build_vector (rtype, nreverse (n_elts));
  	}
        break;
  
--- 10030,10044 ----
  
        if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
  	{
! 	  tree *n_elts = XALLOCAVEC (tree, 2 * VECTOR_CST_NELTS (arg0));
! 	  unsigned i;
! 	  for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)
  	    {
! 	      n_elts[2*i] = VECTOR_CST_ELT (arg0, i);
! 	      n_elts[2*i+1] = VECTOR_CST_ELT (arg1, i);
  	    }
  
! 	  return build_vector (rtype, n_elts);
  	}
        break;
  
*************** sparc_fold_builtin (tree fndecl, int n_a
*** 10073,10089 ****
  	  int overflow = 0;
  	  unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (arg2);
  	  HOST_WIDE_INT high = TREE_INT_CST_HIGH (arg2);
! 	  tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
! 	  tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
  
! 	  for (; elts0 && elts1;
! 	       elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
  	    {
  	      unsigned HOST_WIDE_INT
! 		low0 = TREE_INT_CST_LOW (TREE_VALUE (elts0)),
! 		low1 = TREE_INT_CST_LOW (TREE_VALUE (elts1));
! 	      HOST_WIDE_INT high0 = TREE_INT_CST_HIGH (TREE_VALUE (elts0));
! 	      HOST_WIDE_INT high1 = TREE_INT_CST_HIGH (TREE_VALUE (elts1));
  
  	      unsigned HOST_WIDE_INT l;
  	      HOST_WIDE_INT h;
--- 10057,10073 ----
  	  int overflow = 0;
  	  unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (arg2);
  	  HOST_WIDE_INT high = TREE_INT_CST_HIGH (arg2);
! 	  unsigned i;
  
! 	  for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)
  	    {
  	      unsigned HOST_WIDE_INT
! 		low0 = TREE_INT_CST_LOW (VECTOR_CST_ELT (arg0, i)),
! 		low1 = TREE_INT_CST_LOW (VECTOR_CST_ELT (arg1, i));
! 	      HOST_WIDE_INT
! 		high0 = TREE_INT_CST_HIGH (VECTOR_CST_ELT (arg0, i));
! 	      HOST_WIDE_INT
! 		high1 = TREE_INT_CST_HIGH (VECTOR_CST_ELT (arg1, i));
  
  	      unsigned HOST_WIDE_INT l;
  	      HOST_WIDE_INT h;
Index: gcc/expmed.c
===================================================================
*** gcc/expmed.c.orig	2012-02-02 16:24:26.000000000 +0100
--- gcc/expmed.c	2012-03-15 12:43:41.000000000 +0100
*************** make_tree (tree type, rtx x)
*** 4970,4987 ****
        {
  	int units = CONST_VECTOR_NUNITS (x);
  	tree itype = TREE_TYPE (type);
! 	tree t = NULL_TREE;
  	int i;
  
- 
  	/* Build a tree with vector elements.  */
  	for (i = units - 1; i >= 0; --i)
  	  {
  	    rtx elt = CONST_VECTOR_ELT (x, i);
! 	    t = tree_cons (NULL_TREE, make_tree (itype, elt), t);
  	  }
  
! 	return build_vector (type, t);
        }
  
      case PLUS:
--- 4970,4987 ----
        {
  	int units = CONST_VECTOR_NUNITS (x);
  	tree itype = TREE_TYPE (type);
! 	tree *elts;
  	int i;
  
  	/* Build a tree with vector elements.  */
+ 	elts = XALLOCAVEC (tree, units);
  	for (i = units - 1; i >= 0; --i)
  	  {
  	    rtx elt = CONST_VECTOR_ELT (x, i);
! 	    elts[i] = make_tree (itype, elt);
  	  }
  
! 	return build_vector (type, elts);
        }
  
      case PLUS:



More information about the Gcc-patches mailing list