On Thu, 29 Oct 2015, Richard Biener wrote: > > After > > Index: gcc/gimple-fold.c > =================================================================== > --- gcc/gimple-fold.c (revision 229518) > +++ gcc/gimple-fold.c (working copy) > @@ -398,7 +398,10 @@ fold_gimple_assign (gimple_stmt_iterator > /* If we couldn't fold the RHS, hand over to the generic > fold routines. */ > if (result == NULL_TREE) > - result = fold (rhs); > + { > + result = fold (rhs); > + gcc_assert (result == rhs); > + } > > /* Strip away useless type conversions. Both the NON_LVALUE_EXPR > that may have been added by fold, and "useless" type > > passed bootstrap and regtest on x86_64-unknown-linux-gnu I am now > testing the following.
The following is what I ended up applying. Bootstrapped & tested on x86_64-unknown-linux-gnu. Richard. 2015-10-30 Richard Biener <rguent...@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. Index: gcc/gimple-fold.c =================================================================== *** gcc/gimple-fold.c (revision 229520) --- gcc/gimple-fold.c (working copy) *************** fold_gimple_assign (gimple_stmt_iterator *** 355,362 **** return val; } } - } else if (TREE_CODE (rhs) == ADDR_EXPR) { tree ref = TREE_OPERAND (rhs, 0); --- 355,362 ---- return val; } } } + else if (TREE_CODE (rhs) == ADDR_EXPR) { tree ref = TREE_OPERAND (rhs, 0); *************** fold_gimple_assign (gimple_stmt_iterator *** 371,391 **** else if (TREE_CODE (ref) == MEM_REF && integer_zerop (TREE_OPERAND (ref, 1))) result = fold_convert (TREE_TYPE (rhs), TREE_OPERAND (ref, 0)); } else if (TREE_CODE (rhs) == CONSTRUCTOR ! && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE ! && (CONSTRUCTOR_NELTS (rhs) ! == TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs)))) { /* 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) return NULL_TREE; return build_vector_from_ctor (TREE_TYPE (rhs), --- 371,399 ---- 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) { /* Fold a constant vector CONSTRUCTOR to VECTOR_CST. */ unsigned i; tree val; FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val) ! if (! CONSTANT_CLASS_P (val)) return NULL_TREE; return build_vector_from_ctor (TREE_TYPE (rhs), *************** fold_gimple_assign (gimple_stmt_iterator *** 394,414 **** 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; --- 402,407 ---- Index: gcc/tree.c =================================================================== *** gcc/tree.c (revision 229520) --- gcc/tree.c (working copy) *************** tree *** 1730,1742 **** 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; 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); } --- 1730,1748 ---- 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, pos = 0; tree value; FOR_EACH_CONSTRUCTOR_VALUE (v, 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[pos++] = build_zero_cst (TREE_TYPE (type)); return build_vector (type, vec); } Index: gcc/fold-const.c =================================================================== *** gcc/fold-const.c (revision 229520) --- gcc/fold-const.c (working copy) *************** fold (tree expr) *** 11960,11985 **** 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)); ! return build_vector (type, vec); } case CONST_DECL: --- 11977,11989 ---- if (TREE_CODE (type) != VECTOR_TYPE) return t; ! unsigned i; ! tree val; ! FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), i, val) ! if (! CONSTANT_CLASS_P (val)) ! return t; ! return build_vector_from_ctor (type, CONSTRUCTOR_ELTS (t)); } case CONST_DECL: