Use vec<> in build_vector
[gcc.git] / gcc / fold-const.c
index 492d7f16169226ac5c0cb6863827df07688879cd..013081da673999a94a1881d6885fc9194b064e87 100644 (file)
@@ -136,7 +136,6 @@ static tree fold_not_const (const_tree, tree);
 static tree fold_relational_const (enum tree_code, tree, tree, tree);
 static tree fold_convert_const (enum tree_code, tree, tree);
 static tree fold_view_convert_expr (tree, tree);
-static bool vec_cst_ctor_to_array (tree, tree *);
 static tree fold_negate_expr (location_t, tree);
 
 
@@ -410,7 +409,7 @@ negate_expr_p (tree t)
        if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type))
          return true;
 
-       int count = TYPE_VECTOR_SUBPARTS (type), i;
+       int count = VECTOR_CST_NELTS (t), i;
 
        for (i = 0; i < count; i++)
          if (!negate_expr_p (VECTOR_CST_ELT (t, i)))
@@ -564,14 +563,15 @@ fold_negate_expr_1 (location_t loc, tree t)
 
     case VECTOR_CST:
       {
-       int count = TYPE_VECTOR_SUBPARTS (type), i;
-       tree *elts = XALLOCAVEC (tree, count);
+       int count = VECTOR_CST_NELTS (t), i;
 
+       auto_vec<tree, 32> elts (count);
        for (i = 0; i < count; i++)
          {
-           elts[i] = fold_negate_expr (loc, VECTOR_CST_ELT (t, i));
-           if (elts[i] == NULL_TREE)
+           tree elt = fold_negate_expr (loc, VECTOR_CST_ELT (t, i));
+           if (elt == NULL_TREE)
              return NULL_TREE;
+           elts.quick_push (elt);
          }
 
        return build_vector (type, elts);
@@ -1413,20 +1413,21 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
       && TREE_CODE (arg2) == VECTOR_CST)
     {
       tree type = TREE_TYPE (arg1);
-      int count = TYPE_VECTOR_SUBPARTS (type), i;
-      tree *elts = XALLOCAVEC (tree, count);
+      int count = VECTOR_CST_NELTS (arg1), i;
 
+      auto_vec<tree, 32> elts (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);
+         tree elt = 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)
+         if (elt == NULL_TREE)
            return NULL_TREE;
+         elts.quick_push (elt);
        }
 
       return build_vector (type, elts);
@@ -1437,19 +1438,20 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
       && TREE_CODE (arg2) == INTEGER_CST)
     {
       tree type = TREE_TYPE (arg1);
-      int count = TYPE_VECTOR_SUBPARTS (type), i;
-      tree *elts = XALLOCAVEC (tree, count);
+      int count = VECTOR_CST_NELTS (arg1), i;
 
+      auto_vec<tree, 32> elts (count);
       for (i = 0; i < count; i++)
        {
          tree elem1 = VECTOR_CST_ELT (arg1, i);
 
-         elts[i] = const_binop (code, elem1, arg2);
+         tree elt = const_binop (code, elem1, arg2);
 
          /* It is possible that const_binop cannot handle the given
             code and return NULL_TREE.  */
-         if (elts[i] == NULL_TREE)
+         if (elt == NULL_TREE)
            return NULL_TREE;
+         elts.quick_push (elt);
        }
 
       return build_vector (type, elts);
@@ -1481,27 +1483,29 @@ const_binop (enum tree_code code, tree type, tree arg1, tree arg2)
     case VEC_PACK_TRUNC_EXPR:
     case VEC_PACK_FIX_TRUNC_EXPR:
       {
-       unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
-       tree *elts;
+       unsigned int out_nelts, in_nelts, i;
 
-       gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts / 2
-                   && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2)) == nelts / 2);
        if (TREE_CODE (arg1) != VECTOR_CST
            || TREE_CODE (arg2) != VECTOR_CST)
          return NULL_TREE;
 
-       elts = XALLOCAVEC (tree, nelts);
-       if (!vec_cst_ctor_to_array (arg1, elts)
-           || !vec_cst_ctor_to_array (arg2, elts + nelts / 2))
-         return NULL_TREE;
+       in_nelts = VECTOR_CST_NELTS (arg1);
+       out_nelts = in_nelts * 2;
+       gcc_assert (in_nelts == VECTOR_CST_NELTS (arg2)
+                   && out_nelts == TYPE_VECTOR_SUBPARTS (type));
 
-       for (i = 0; i < nelts; i++)
+       auto_vec<tree, 32> elts (out_nelts);
+       for (i = 0; i < out_nelts; i++)
          {
-           elts[i] = fold_convert_const (code == VEC_PACK_TRUNC_EXPR
-                                         ? NOP_EXPR : FIX_TRUNC_EXPR,
-                                         TREE_TYPE (type), elts[i]);
-           if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
+           tree elt = (i < in_nelts
+                       ? VECTOR_CST_ELT (arg1, i)
+                       : VECTOR_CST_ELT (arg2, i - in_nelts));
+           elt = fold_convert_const (code == VEC_PACK_TRUNC_EXPR
+                                     ? NOP_EXPR : FIX_TRUNC_EXPR,
+                                     TREE_TYPE (type), elt);
+           if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
              return NULL_TREE;
+           elts.quick_push (elt);
          }
 
        return build_vector (type, elts);
@@ -1512,43 +1516,40 @@ const_binop (enum tree_code code, tree type, tree arg1, tree arg2)
     case VEC_WIDEN_MULT_EVEN_EXPR:
     case VEC_WIDEN_MULT_ODD_EXPR:
       {
-       unsigned int nelts = TYPE_VECTOR_SUBPARTS (type);
-       unsigned int out, ofs, scale;
-       tree *elts;
+       unsigned int out_nelts, in_nelts, out, ofs, scale;
 
-       gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)) == nelts * 2
-                   && TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg2)) == nelts * 2);
        if (TREE_CODE (arg1) != VECTOR_CST || TREE_CODE (arg2) != VECTOR_CST)
          return NULL_TREE;
 
-       elts = XALLOCAVEC (tree, nelts * 4);
-       if (!vec_cst_ctor_to_array (arg1, elts)
-           || !vec_cst_ctor_to_array (arg2, elts + nelts * 2))
-         return NULL_TREE;
+       in_nelts = VECTOR_CST_NELTS (arg1);
+       out_nelts = in_nelts / 2;
+       gcc_assert (in_nelts == VECTOR_CST_NELTS (arg2)
+                   && out_nelts == TYPE_VECTOR_SUBPARTS (type));
 
        if (code == VEC_WIDEN_MULT_LO_EXPR)
-         scale = 0, ofs = BYTES_BIG_ENDIAN ? nelts : 0;
+         scale = 0, ofs = BYTES_BIG_ENDIAN ? out_nelts : 0;
        else if (code == VEC_WIDEN_MULT_HI_EXPR)
-         scale = 0, ofs = BYTES_BIG_ENDIAN ? 0 : nelts;
+         scale = 0, ofs = BYTES_BIG_ENDIAN ? 0 : out_nelts;
        else if (code == VEC_WIDEN_MULT_EVEN_EXPR)
          scale = 1, ofs = 0;
        else /* if (code == VEC_WIDEN_MULT_ODD_EXPR) */
          scale = 1, ofs = 1;
 
-       for (out = 0; out < nelts; out++)
+       auto_vec<tree, 32> elts (out_nelts);
+       for (out = 0; out < out_nelts; out++)
          {
-           unsigned int in1 = (out << scale) + ofs;
-           unsigned int in2 = in1 + nelts * 2;
-           tree t1, t2;
-
-           t1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in1]);
-           t2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in2]);
+           unsigned int in = (out << scale) + ofs;
+           tree t1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type),
+                                         VECTOR_CST_ELT (arg1, in));
+           tree t2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type),
+                                         VECTOR_CST_ELT (arg2, in));
 
            if (t1 == NULL_TREE || t2 == NULL_TREE)
              return NULL_TREE;
-           elts[out] = const_binop (MULT_EXPR, t1, t2);
-           if (elts[out] == NULL_TREE || !CONSTANT_CLASS_P (elts[out]))
+           tree elt = const_binop (MULT_EXPR, t1, t2);
+           if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
              return NULL_TREE;
+           elts.quick_push (elt);
          }
 
        return build_vector (type, elts);
@@ -1633,18 +1634,17 @@ const_unop (enum tree_code code, tree type, tree arg0)
       /* 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);
+         auto_vec<tree, 32> elements (count);
          for (i = 0; i < count; i++)
            {
              elem = VECTOR_CST_ELT (arg0, i);
              elem = const_unop (BIT_NOT_EXPR, TREE_TYPE (type), elem);
              if (elem == NULL_TREE)
                break;
-             elements[i] = elem;
+             elements.quick_push (elem);
            }
          if (i == count)
            return build_vector (type, elements);
@@ -1671,32 +1671,34 @@ const_unop (enum tree_code code, tree type, tree arg0)
     case VEC_UNPACK_FLOAT_LO_EXPR:
     case VEC_UNPACK_FLOAT_HI_EXPR:
       {
-       unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
-       tree *elts;
+       unsigned int out_nelts, in_nelts, i;
        enum tree_code subcode;
 
-       gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2);
        if (TREE_CODE (arg0) != VECTOR_CST)
          return NULL_TREE;
 
-       elts = XALLOCAVEC (tree, nelts * 2);
-       if (!vec_cst_ctor_to_array (arg0, elts))
-         return NULL_TREE;
+       in_nelts = VECTOR_CST_NELTS (arg0);
+       out_nelts = in_nelts / 2;
+       gcc_assert (out_nelts == TYPE_VECTOR_SUBPARTS (type));
 
+       unsigned int offset = 0;
        if ((!BYTES_BIG_ENDIAN) ^ (code == VEC_UNPACK_LO_EXPR
                                   || code == VEC_UNPACK_FLOAT_LO_EXPR))
-         elts += nelts;
+         offset = out_nelts;
 
        if (code == VEC_UNPACK_LO_EXPR || code == VEC_UNPACK_HI_EXPR)
          subcode = NOP_EXPR;
        else
          subcode = FLOAT_EXPR;
 
-       for (i = 0; i < nelts; i++)
+       auto_vec<tree, 32> elts (out_nelts);
+       for (i = 0; i < out_nelts; i++)
          {
-           elts[i] = fold_convert_const (subcode, TREE_TYPE (type), elts[i]);
-           if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
+           tree elt = fold_convert_const (subcode, TREE_TYPE (type),
+                                          VECTOR_CST_ELT (arg0, i + offset));
+           if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
              return NULL_TREE;
+           elts.quick_push (elt);
          }
 
        return build_vector (type, elts);
@@ -1707,16 +1709,11 @@ const_unop (enum tree_code code, tree type, tree arg0)
     case REDUC_PLUS_EXPR:
       {
        unsigned int nelts, i;
-       tree *elts;
        enum tree_code subcode;
 
        if (TREE_CODE (arg0) != VECTOR_CST)
          return NULL_TREE;
-        nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0));
-
-       elts = XALLOCAVEC (tree, nelts);
-       if (!vec_cst_ctor_to_array (arg0, elts))
-         return NULL_TREE;
+       nelts = VECTOR_CST_NELTS (arg0);
 
        switch (code)
          {
@@ -1726,14 +1723,15 @@ const_unop (enum tree_code code, tree type, tree arg0)
          default: gcc_unreachable ();
          }
 
+       tree res = VECTOR_CST_ELT (arg0, 0);
        for (i = 1; i < nelts; i++)
          {
-           elts[0] = const_binop (subcode, elts[0], elts[i]);
-           if (elts[0] == NULL_TREE || !CONSTANT_CLASS_P (elts[0]))
+           res = const_binop (subcode, res, VECTOR_CST_ELT (arg0, i));
+           if (res == NULL_TREE || !CONSTANT_CLASS_P (res))
              return NULL_TREE;
          }
 
-       return elts[0];
+       return res;
       }
 
     default:
@@ -1944,7 +1942,7 @@ fold_convert_const_int_from_fixed (tree type, const_tree arg1)
 {
   tree t;
   double_int temp, temp_trunc;
-  unsigned int mode;
+  scalar_mode mode;
 
   /* Right shift FIXED_CST to temp by fbit.  */
   temp = TREE_FIXED_CST (arg1).data;
@@ -2050,8 +2048,8 @@ fold_convert_const_fixed_from_fixed (tree type, const_tree arg1)
   tree t;
   bool overflow_p;
 
-  overflow_p = fixed_convert (&value, TYPE_MODE (type), &TREE_FIXED_CST (arg1),
-                             TYPE_SATURATING (type));
+  overflow_p = fixed_convert (&value, SCALAR_TYPE_MODE (type),
+                             &TREE_FIXED_CST (arg1), TYPE_SATURATING (type));
   t = build_fixed (type, value);
 
   /* Propagate overflow flags.  */
@@ -2079,7 +2077,7 @@ fold_convert_const_fixed_from_int (tree type, const_tree arg1)
   else
     di.high = TREE_INT_CST_ELT (arg1, 1);
 
-  overflow_p = fixed_convert_from_int (&value, TYPE_MODE (type), di,
+  overflow_p = fixed_convert_from_int (&value, SCALAR_TYPE_MODE (type), di,
                                       TYPE_UNSIGNED (TREE_TYPE (arg1)),
                                       TYPE_SATURATING (type));
   t = build_fixed (type, value);
@@ -2100,7 +2098,7 @@ fold_convert_const_fixed_from_real (tree type, const_tree arg1)
   tree t;
   bool overflow_p;
 
-  overflow_p = fixed_convert_from_real (&value, TYPE_MODE (type),
+  overflow_p = fixed_convert_from_real (&value, SCALAR_TYPE_MODE (type),
                                        &TREE_REAL_CST (arg1),
                                        TYPE_SATURATING (type));
   t = build_fixed (type, value);
@@ -2153,16 +2151,16 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
       if (TREE_CODE (arg1) == VECTOR_CST
          && TYPE_VECTOR_SUBPARTS (type) == VECTOR_CST_NELTS (arg1))
        {
-         int len = TYPE_VECTOR_SUBPARTS (type);
+         int len = VECTOR_CST_NELTS (arg1);
          tree elttype = TREE_TYPE (type);
-         tree *v = XALLOCAVEC (tree, len);
+         auto_vec<tree, 32> v (len);
          for (int i = 0; i < len; ++i)
            {
              tree elt = VECTOR_CST_ELT (arg1, i);
              tree cvt = fold_convert_const (code, elttype, elt);
              if (cvt == NULL_TREE)
                return NULL_TREE;
-             v[i] = cvt;
+             v.quick_push (cvt);
            }
          return build_vector (type, v);
        }
@@ -5394,6 +5392,7 @@ fold_range_test (location_t loc, enum tree_code code, tree type,
      short-circuited branch and the underlying object on both sides
      is the same, make a non-short-circuit operation.  */
   else if (LOGICAL_OP_NON_SHORT_CIRCUIT
+          && !flag_sanitize_coverage
           && lhs != 0 && rhs != 0
           && (code == TRUTH_ANDIF_EXPR
               || code == TRUTH_ORIF_EXPR)
@@ -7027,7 +7026,7 @@ static int
 native_encode_fixed (const_tree expr, unsigned char *ptr, int len, int off)
 {
   tree type = TREE_TYPE (expr);
-  machine_mode mode = TYPE_MODE (type);
+  scalar_mode mode = SCALAR_TYPE_MODE (type);
   int total_bytes = GET_MODE_SIZE (mode);
   FIXED_VALUE_TYPE value;
   tree i_value, i_type;
@@ -7129,7 +7128,7 @@ native_encode_complex (const_tree expr, unsigned char *ptr, int len, int off)
     return 0;
   part = TREE_IMAGPART (expr);
   if (off != -1)
-    off = MAX (0, off - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (part))));
+    off = MAX (0, off - GET_MODE_SIZE (SCALAR_TYPE_MODE (TREE_TYPE (part))));
   isize = native_encode_expr (part, ptr+rsize, len-rsize, off);
   if (off == -1
       && isize != rsize)
@@ -7153,7 +7152,7 @@ native_encode_vector (const_tree expr, unsigned char *ptr, int len, int off)
   offset = 0;
   count = VECTOR_CST_NELTS (expr);
   itype = TREE_TYPE (TREE_TYPE (expr));
-  size = GET_MODE_SIZE (TYPE_MODE (itype));
+  size = GET_MODE_SIZE (SCALAR_TYPE_MODE (itype));
   for (i = 0; i < count; i++)
     {
       if (off >= size)
@@ -7184,16 +7183,10 @@ native_encode_vector (const_tree expr, unsigned char *ptr, int len, int off)
 static int
 native_encode_string (const_tree expr, unsigned char *ptr, int len, int off)
 {
-  tree type = TREE_TYPE (expr);
-  HOST_WIDE_INT total_bytes;
-
-  if (TREE_CODE (type) != ARRAY_TYPE
-      || TREE_CODE (TREE_TYPE (type)) != INTEGER_TYPE
-      || (GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (type)))
-         != BITS_PER_UNIT)
-      || !tree_fits_shwi_p (TYPE_SIZE_UNIT (type)))
+  if (! can_native_encode_string_p (expr))
     return 0;
-  total_bytes = tree_to_shwi (TYPE_SIZE_UNIT (type));
+
+  HOST_WIDE_INT total_bytes = tree_to_shwi (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
   if ((off == -1 && total_bytes > len)
       || off >= total_bytes)
     return 0;
@@ -7281,7 +7274,8 @@ native_interpret_int (tree type, const unsigned char *ptr, int len)
 static tree
 native_interpret_fixed (tree type, const unsigned char *ptr, int len)
 {
-  int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
+  scalar_mode mode = SCALAR_TYPE_MODE (type);
+  int total_bytes = GET_MODE_SIZE (mode);
   double_int result;
   FIXED_VALUE_TYPE fixed_value;
 
@@ -7290,7 +7284,7 @@ native_interpret_fixed (tree type, const unsigned char *ptr, int len)
     return NULL_TREE;
 
   result = double_int::from_buffer (ptr, total_bytes);
-  fixed_value = fixed_from_double_int (result, TYPE_MODE (type));
+  fixed_value = fixed_from_double_int (result, mode);
 
   return build_fixed (type, fixed_value);
 }
@@ -7312,7 +7306,6 @@ native_interpret_real (tree type, const unsigned char *ptr, int len)
   REAL_VALUE_TYPE r;
   long tmp[6];
 
-  total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
   if (total_bytes > len || total_bytes > 24)
     return NULL_TREE;
   int words = (32 / BITS_PER_UNIT) / UNITS_PER_WORD;
@@ -7367,7 +7360,7 @@ native_interpret_complex (tree type, const unsigned char *ptr, int len)
   int size;
 
   etype = TREE_TYPE (type);
-  size = GET_MODE_SIZE (TYPE_MODE (etype));
+  size = GET_MODE_SIZE (SCALAR_TYPE_MODE (etype));
   if (size * 2 > len)
     return NULL_TREE;
   rpart = native_interpret_expr (etype, ptr, size);
@@ -7389,21 +7382,20 @@ 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));
+  size = GET_MODE_SIZE (SCALAR_TYPE_MODE (etype));
   count = TYPE_VECTOR_SUBPARTS (type);
   if (size * count > len)
     return NULL_TREE;
 
-  elements = XALLOCAVEC (tree, count);
-  for (i = count - 1; i >= 0; i--)
+  auto_vec<tree, 32> elements (count);
+  for (i = 0; i < count; ++i)
     {
       elem = native_interpret_expr (etype, ptr+(i*size), size);
       if (!elem)
        return NULL_TREE;
-      elements[i] = elem;
+      elements.quick_push (elem);
     }
   return build_vector (type, elements);
 }
@@ -7487,6 +7479,24 @@ can_native_encode_type_p (tree type)
     }
 }
 
+/* Return true iff a STRING_CST S is accepted by
+   native_encode_expr.  */
+
+bool
+can_native_encode_string_p (const_tree expr)
+{
+  tree type = TREE_TYPE (expr);
+
+  /* Wide-char strings are encoded in target byte-order so native
+     encoding them is trivial.  */
+  if (BITS_PER_UNIT != CHAR_BIT
+      || TREE_CODE (type) != ARRAY_TYPE
+      || TREE_CODE (TREE_TYPE (type)) != INTEGER_TYPE
+      || !tree_fits_shwi_p (TYPE_SIZE_UNIT (type)))
+    return false;
+  return true;
+}
+
 /* Fold a VIEW_CONVERT_EXPR of a constant expression EXPR to type
    TYPE at compile-time.  If we're unable to perform the conversion
    return NULL_TREE.  */
@@ -8035,6 +8045,7 @@ fold_truth_andor (location_t loc, enum tree_code code, tree type,
     return tem;
 
   if (LOGICAL_OP_NON_SHORT_CIRCUIT
+      && !flag_sanitize_coverage
       && (code == TRUTH_AND_EXPR
           || code == TRUTH_ANDIF_EXPR
           || code == TRUTH_OR_EXPR
@@ -8739,12 +8750,13 @@ fold_mult_zconjz (location_t loc, tree type, tree expr)
 
 
 /* Helper function for fold_vec_perm.  Store elements of VECTOR_CST or
-   CONSTRUCTOR ARG into array ELTS and return true if successful.  */
+   CONSTRUCTOR ARG into array ELTS, which has NELTS elements, and return
+   true if successful.  */
 
 static bool
-vec_cst_ctor_to_array (tree arg, tree *elts)
+vec_cst_ctor_to_array (tree arg, unsigned int nelts, tree *elts)
 {
-  unsigned int nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)), i;
+  unsigned int i;
 
   if (TREE_CODE (arg) == VECTOR_CST)
     {
@@ -8777,7 +8789,6 @@ static tree
 fold_vec_perm (tree type, tree arg0, tree arg1, const unsigned char *sel)
 {
   unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
-  tree *elts;
   bool need_ctor = false;
 
   gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts
@@ -8786,16 +8797,17 @@ fold_vec_perm (tree type, tree arg0, tree arg1, const unsigned char *sel)
       || TREE_TYPE (TREE_TYPE (arg1)) != TREE_TYPE (type))
     return NULL_TREE;
 
-  elts = XALLOCAVEC (tree, nelts * 3);
-  if (!vec_cst_ctor_to_array (arg0, elts)
-      || !vec_cst_ctor_to_array (arg1, elts + nelts))
+  tree *in_elts = XALLOCAVEC (tree, nelts * 2);
+  if (!vec_cst_ctor_to_array (arg0, nelts, in_elts)
+      || !vec_cst_ctor_to_array (arg1, nelts, in_elts + nelts))
     return NULL_TREE;
 
+  auto_vec<tree, 32> out_elts (nelts);
   for (i = 0; i < nelts; i++)
     {
-      if (!CONSTANT_CLASS_P (elts[sel[i]]))
+      if (!CONSTANT_CLASS_P (in_elts[sel[i]]))
        need_ctor = true;
-      elts[i + 2 * nelts] = unshare_expr (elts[sel[i]]);
+      out_elts.quick_push (unshare_expr (in_elts[sel[i]]));
     }
 
   if (need_ctor)
@@ -8803,11 +8815,11 @@ fold_vec_perm (tree type, tree arg0, tree arg1, const unsigned char *sel)
       vec<constructor_elt, va_gc> *v;
       vec_alloc (v, nelts);
       for (i = 0; i < nelts; i++)
-       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[2 * nelts + i]);
+       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, out_elts[i]);
       return build_constructor (type, v);
     }
   else
-    return build_vector (type, &elts[2 * nelts]);
+    return build_vector (type, out_elts);
 }
 
 /* Try to fold a pointer difference of type TYPE two address expressions of
@@ -8857,7 +8869,7 @@ tree
 exact_inverse (tree type, tree cst)
 {
   REAL_VALUE_TYPE r;
-  tree unit_type, *elts;
+  tree unit_type;
   machine_mode mode;
   unsigned vec_nelts, i;
 
@@ -8872,20 +8884,22 @@ exact_inverse (tree type, tree cst)
       return NULL_TREE;
 
     case VECTOR_CST:
-      vec_nelts = VECTOR_CST_NELTS (cst);
-      elts = XALLOCAVEC (tree, vec_nelts);
-      unit_type = TREE_TYPE (type);
-      mode = TYPE_MODE (unit_type);
+      {
+       vec_nelts = VECTOR_CST_NELTS (cst);
+       unit_type = TREE_TYPE (type);
+       mode = TYPE_MODE (unit_type);
 
-      for (i = 0; i < vec_nelts; i++)
-       {
-         r = TREE_REAL_CST (VECTOR_CST_ELT (cst, i));
-         if (!exact_real_inverse (mode, &r))
-           return NULL_TREE;
-         elts[i] = build_real (unit_type, r);
-       }
+       auto_vec<tree, 32> elts (vec_nelts);
+       for (i = 0; i < vec_nelts; i++)
+         {
+           r = TREE_REAL_CST (VECTOR_CST_ELT (cst, i));
+           if (!exact_real_inverse (mode, &r))
+             return NULL_TREE;
+           elts.quick_push (build_real (unit_type, r));
+         }
 
-      return build_vector (type, elts);
+       return build_vector (type, elts);
+      }
 
     default:
       return NULL_TREE;
@@ -11297,9 +11311,9 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
              && (TREE_CODE (arg2) == VECTOR_CST
                  || TREE_CODE (arg2) == CONSTRUCTOR))
            {
-             unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
+             unsigned int nelts = VECTOR_CST_NELTS (arg0), i;
              unsigned char *sel = XALLOCAVEC (unsigned char, nelts);
-             gcc_assert (nelts == VECTOR_CST_NELTS (arg0));
+             gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (type));
              for (i = 0; i < nelts; i++)
                {
                  tree val = VECTOR_CST_ELT (arg0, i);
@@ -11574,9 +11588,9 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
                  if (n == 1)
                    return VECTOR_CST_ELT (arg0, idx);
 
-                 tree *vals = XALLOCAVEC (tree, n);
+                 auto_vec<tree, 32> vals (n);
                  for (unsigned i = 0; i < n; ++i)
-                   vals[i] = VECTOR_CST_ELT (arg0, idx + i);
+                   vals.quick_push (VECTOR_CST_ELT (arg0, idx + i));
                  return build_vector (type, vals);
                }
            }
@@ -11628,7 +11642,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
     case VEC_PERM_EXPR:
       if (TREE_CODE (arg2) == VECTOR_CST)
        {
-         unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i, mask, mask2;
+         unsigned int nelts = VECTOR_CST_NELTS (arg2), i, mask, mask2;
          unsigned char *sel = XALLOCAVEC (unsigned char, 2 * nelts);
          unsigned char *sel2 = sel + nelts;
          bool need_mask_canon = false;
@@ -11641,7 +11655,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
 
          mask2 = 2 * nelts - 1;
          mask = single_arg ? (nelts - 1) : mask2;
-         gcc_assert (nelts == VECTOR_CST_NELTS (arg2));
+         gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (type));
          for (i = 0; i < nelts; i++)
            {
              tree val = VECTOR_CST_ELT (arg2, i);
@@ -11709,10 +11723,10 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
 
          if (need_mask_canon && arg2 == op2)
            {
-             tree *tsel = XALLOCAVEC (tree, nelts);
              tree eltype = TREE_TYPE (TREE_TYPE (arg2));
+             auto_vec<tree, 32> tsel (nelts);
              for (i = 0; i < nelts; i++)
-               tsel[i] = build_int_cst (eltype, sel[i]);
+               tsel.quick_push (build_int_cst (eltype, sel[i]));
              op2 = build_vector (TREE_TYPE (arg2), tsel);
              changed = true;
            }
@@ -11752,9 +11766,11 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
                return arg0;
              else
                {
-                 tree *elts = XALLOCAVEC (tree, TYPE_VECTOR_SUBPARTS (type));
-                 memcpy (elts, VECTOR_CST_ELTS (arg0),
-                         sizeof (tree) * TYPE_VECTOR_SUBPARTS (type));
+                 unsigned int nelts = VECTOR_CST_NELTS (arg0);
+                 auto_vec<tree, 32> elts (nelts);
+                 elts.quick_grow (nelts);
+                 memcpy (&elts[0], VECTOR_CST_ELTS (arg0),
+                         sizeof (tree) * nelts);
                  elts[k] = arg1;
                  return build_vector (type, elts);
                }
@@ -13872,10 +13888,10 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
          return constant_boolean_node (true, type);
        }
       unsigned count = VECTOR_CST_NELTS (op0);
-      tree *elts =  XALLOCAVEC (tree, count);
       gcc_assert (VECTOR_CST_NELTS (op1) == count
                  && TYPE_VECTOR_SUBPARTS (type) == count);
 
+      auto_vec<tree, 32> elts (count);
       for (unsigned i = 0; i < count; i++)
        {
          tree elem_type = TREE_TYPE (type);
@@ -13888,7 +13904,8 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
          if (tem == NULL_TREE)
            return NULL_TREE;
 
-         elts[i] = build_int_cst (elem_type, integer_zerop (tem) ? 0 : -1);
+         elts.quick_push (build_int_cst (elem_type,
+                                         integer_zerop (tem) ? 0 : -1));
        }
 
       return build_vector (type, elts);