diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-16 14:49:05 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-16 14:49:05 +0000 |
commit | ae37ffafe757533bbdb7ca1abc6abe8b18a78b79 (patch) | |
tree | 3f9d570f112d058797d9ad03991da3a3f27c731c /gcc/fold-const.c | |
parent | ace64c064cf3d0dc797f3338fcda24840ba0eabc (diff) | |
download | gcc-ae37ffafe757533bbdb7ca1abc6abe8b18a78b79.tar.gz |
2012-03-16 Richard Guenther <rguenther@suse.de>
PR middle-end/52584
* fold-const.c (fold_ternary_loc): Fold vector typed BIT_FIELD_REFs
of vector constants and constructors.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@185468 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 55 |
1 files changed, 44 insertions, 11 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0cd84285ee1..6c4f7f86bad 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); + } } } |