+2015-10-30 Richard Biener <rguenther@suse.de>
+
+ * gimple-fold.c (fold_gimple_assign): Do not dispatch to
+ fold () on single RHSs. Allow CONSTRUCTORS with trailing
+ zeros to be folded to VECTOR_CSTs.
+ * tree.c (build_vector_from_ctor): Handle VECTOR_CST elements.
+ * fold-const.c (fold): Use build_vector_from_ctor.
+
2015-10-30 Evandro Menezes <e.menezes@samsung.com>
* config/aarch64/aarch64.md (*movhf_aarch64): Change the type of
if (TREE_CODE (type) != VECTOR_TYPE)
return t;
- tree *vec = XALLOCAVEC (tree, TYPE_VECTOR_SUBPARTS (type));
- unsigned HOST_WIDE_INT idx, pos = 0;
- tree value;
-
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), idx, value)
- {
- if (!CONSTANT_CLASS_P (value))
- return t;
- if (TREE_CODE (value) == VECTOR_CST)
- {
- for (unsigned i = 0; i < VECTOR_CST_NELTS (value); ++i)
- vec[pos++] = VECTOR_CST_ELT (value, i);
- }
- else
- vec[pos++] = value;
- }
- for (; pos < TYPE_VECTOR_SUBPARTS (type); ++pos)
- vec[pos] = build_zero_cst (TREE_TYPE (type));
+ unsigned i;
+ tree val;
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), i, val)
+ if (! CONSTANT_CLASS_P (val))
+ return t;
- return build_vector (type, vec);
+ return build_vector_from_ctor (type, CONSTRUCTOR_ELTS (t));
}
case CONST_DECL:
return val;
}
}
-
}
+
else if (TREE_CODE (rhs) == ADDR_EXPR)
{
tree ref = TREE_OPERAND (rhs, 0);
else if (TREE_CODE (ref) == MEM_REF
&& integer_zerop (TREE_OPERAND (ref, 1)))
result = fold_convert (TREE_TYPE (rhs), TREE_OPERAND (ref, 0));
+
+ if (result)
+ {
+ /* Strip away useless type conversions. Both the
+ NON_LVALUE_EXPR that may have been added by fold, and
+ "useless" type conversions that might now be apparent
+ due to propagation. */
+ STRIP_USELESS_TYPE_CONVERSION (result);
+
+ if (result != rhs && valid_gimple_rhs_p (result))
+ return result;
+ }
}
else if (TREE_CODE (rhs) == CONSTRUCTOR
- && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE
- && (CONSTRUCTOR_NELTS (rhs)
- == TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs))))
+ && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE)
{
/* Fold a constant vector CONSTRUCTOR to VECTOR_CST. */
unsigned i;
tree val;
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
- if (TREE_CODE (val) != INTEGER_CST
- && TREE_CODE (val) != REAL_CST
- && TREE_CODE (val) != FIXED_CST)
+ if (! CONSTANT_CLASS_P (val))
return NULL_TREE;
return build_vector_from_ctor (TREE_TYPE (rhs),
else if (DECL_P (rhs))
return get_symbol_constant_value (rhs);
-
- /* If we couldn't fold the RHS, hand over to the generic
- fold routines. */
- if (result == NULL_TREE)
- result = fold (rhs);
-
- /* Strip away useless type conversions. Both the NON_LVALUE_EXPR
- that may have been added by fold, and "useless" type
- conversions that might now be apparent due to propagation. */
- STRIP_USELESS_TYPE_CONVERSION (result);
-
- if (result != rhs && valid_gimple_rhs_p (result))
- return result;
-
- return NULL_TREE;
}
break;
build_vector_from_ctor (tree type, vec<constructor_elt, va_gc> *v)
{
tree *vec = XALLOCAVEC (tree, TYPE_VECTOR_SUBPARTS (type));
- unsigned HOST_WIDE_INT idx;
+ unsigned HOST_WIDE_INT idx, pos = 0;
tree value;
FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
- vec[idx] = value;
+ {
+ if (TREE_CODE (value) == VECTOR_CST)
+ for (unsigned i = 0; i < VECTOR_CST_NELTS (value); ++i)
+ vec[pos++] = VECTOR_CST_ELT (value, i);
+ else
+ vec[pos++] = value;
+ }
for (; idx < TYPE_VECTOR_SUBPARTS (type); ++idx)
- vec[idx] = build_zero_cst (TREE_TYPE (type));
+ vec[pos++] = build_zero_cst (TREE_TYPE (type));
return build_vector (type, vec);
}