From ada3df5081a4fb89ae83bce787fc9c949cdfc9ce Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Fri, 16 Mar 2012 14:49:05 +0000 Subject: [PATCH] re PR middle-end/52584 (Fails to constant fold vector upper/lower half BIT_FIELD_REFs) 2012-03-16 Richard Guenther PR middle-end/52584 * fold-const.c (fold_ternary_loc): Fold vector typed BIT_FIELD_REFs of vector constants and constructors. From-SVN: r185468 --- gcc/ChangeLog | 6 ++++++ gcc/fold-const.c | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d246b85..1775524 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2012-03-16 Richard Guenther + PR middle-end/52584 + * fold-const.c (fold_ternary_loc): Fold vector typed BIT_FIELD_REFs + of vector constants and constructors. + +2012-03-16 Richard Guenther + * tree-vect-stmts.c (vect_get_vec_def_for_operand): Use VIEW_CONVERT_EXPR to convert constants. (vect_is_simple_use): Treat all constants as vec_constant_def. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0cd8428..6c4f7f8 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -13920,22 +13920,55 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type, case BIT_FIELD_REF: if ((TREE_CODE (arg0) == VECTOR_CST || TREE_CODE (arg0) == CONSTRUCTOR) - && type == TREE_TYPE (TREE_TYPE (arg0))) + && (type == TREE_TYPE (TREE_TYPE (arg0)) + || (TREE_CODE (type) == VECTOR_TYPE + && TREE_TYPE (type) == TREE_TYPE (TREE_TYPE (arg0))))) { - unsigned HOST_WIDE_INT width = tree_low_cst (arg1, 1); + tree eltype = TREE_TYPE (TREE_TYPE (arg0)); + unsigned HOST_WIDE_INT width = tree_low_cst (TYPE_SIZE (eltype), 1); + unsigned HOST_WIDE_INT n = tree_low_cst (arg1, 1); unsigned HOST_WIDE_INT idx = tree_low_cst (op2, 1); - if (width != 0 - && simple_cst_equal (arg1, TYPE_SIZE (type)) == 1 + if (n != 0 && (idx % width) == 0 - && (idx = idx / width) - < TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0))) + && (n % width) == 0 + && ((idx + n) / width) <= 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); + idx = idx / width; + n = n / width; + if (TREE_CODE (type) == VECTOR_TYPE) + { + if (TREE_CODE (arg0) == VECTOR_CST) + { + tree *vals = XALLOCAVEC (tree, n); + unsigned i; + for (i = 0; i < n; ++i) + vals[i] = VECTOR_CST_ELT (arg0, idx + i); + return build_vector (type, vals); + } + else + { + VEC(constructor_elt, gc) *vals; + unsigned i; + if (CONSTRUCTOR_NELTS (arg0) == 0) + return build_constructor (type, NULL); + vals = VEC_alloc (constructor_elt, gc, n); + for (i = 0; i < n && idx + i < CONSTRUCTOR_NELTS (arg0); + ++i) + CONSTRUCTOR_APPEND_ELT (vals, NULL_TREE, + CONSTRUCTOR_ELT + (arg0, idx + i)->value); + return build_constructor (type, vals); + } + } + else if (n == 1) + { + 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); + } } } -- 2.7.4