+/* If all values in the constructor vector are the same, return the value.
+ Otherwise return NULL_TREE. Not supposed to be called for empty
+ vectors. */
+
+static tree
+constructor_contains_same_values_p (VEC (constructor_elt, gc) *vec)
+{
+ unsigned int i;
+ tree prev = NULL_TREE;
+ constructor_elt *elt;
+
+ FOR_EACH_VEC_ELT (constructor_elt, vec, i, elt)
+ {
+ if (!prev)
+ prev = elt->value;
+ else if (!operand_equal_p (elt->value, prev, OEP_ONLY_CONST))
+ return NULL_TREE;
+ }
+ return prev;
+}
+
+/* Return type which should be used for array elements, either TYPE,
+ or for integral type some smaller integral type that can still hold
+ all the constants. */
+
+static tree
+array_value_type (gimple swtch, tree type, int num)
+{
+ unsigned int i, len = VEC_length (constructor_elt, info.constructors[num]);
+ constructor_elt *elt;
+ enum machine_mode mode;
+ int sign = 0;
+ tree smaller_type;
+
+ if (!INTEGRAL_TYPE_P (type))
+ return type;
+
+ mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (TYPE_MODE (type)));
+ if (GET_MODE_SIZE (TYPE_MODE (type)) <= GET_MODE_SIZE (mode))
+ return type;
+
+ if (len < (optimize_bb_for_size_p (gimple_bb (swtch)) ? 2 : 32))
+ return type;
+
+ FOR_EACH_VEC_ELT (constructor_elt, info.constructors[num], i, elt)
+ {
+ double_int cst;
+
+ if (TREE_CODE (elt->value) != INTEGER_CST)
+ return type;
+
+ cst = TREE_INT_CST (elt->value);
+ while (1)
+ {
+ unsigned int prec = GET_MODE_BITSIZE (mode);
+ if (prec > HOST_BITS_PER_WIDE_INT)
+ return type;
+
+ if (sign >= 0
+ && double_int_equal_p (cst, double_int_zext (cst, prec)))
+ {
+ if (sign == 0
+ && double_int_equal_p (cst, double_int_sext (cst, prec)))
+ break;
+ sign = 1;
+ break;
+ }
+ if (sign <= 0
+ && double_int_equal_p (cst, double_int_sext (cst, prec)))
+ {
+ sign = -1;
+ break;
+ }
+
+ if (sign == 1)
+ sign = 0;
+
+ mode = GET_MODE_WIDER_MODE (mode);
+ if (mode == VOIDmode
+ || GET_MODE_SIZE (mode) >= GET_MODE_SIZE (TYPE_MODE (type)))
+ return type;
+ }
+ }
+
+ if (sign == 0)
+ sign = TYPE_UNSIGNED (type) ? 1 : -1;
+ smaller_type = lang_hooks.types.type_for_mode (mode, sign >= 0);
+ if (GET_MODE_SIZE (TYPE_MODE (type))
+ <= GET_MODE_SIZE (TYPE_MODE (smaller_type)))
+ return type;
+
+ return smaller_type;
+}
+