From: glisse Date: Wed, 28 Nov 2012 10:11:27 +0000 (+0000) Subject: 2012-11-28 Marc Glisse X-Git-Tag: upstream/4.9.2~8918 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=be7b52a22048bbed91f81bd821522c456709c19b;p=platform%2Fupstream%2Flinaro-gcc.git 2012-11-28 Marc Glisse PR middle-end/55266 * fold-const.c (fold_ternary_loc) [BIT_FIELD_REF]: Handle CONSTRUCTOR with vector elements. * tree-ssa-propagate.c (valid_gimple_rhs_p): Handle CONSTRUCTOR and BIT_FIELD_REF. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@193884 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b1a4afb..a15b5ef 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2012-11-28 Marc Glisse + + PR middle-end/55266 + * fold-const.c (fold_ternary_loc) [BIT_FIELD_REF]: Handle + CONSTRUCTOR with vector elements. + * tree-ssa-propagate.c (valid_gimple_rhs_p): Handle CONSTRUCTOR + and BIT_FIELD_REF. + 2012-11-28 Richard Biener PR c/35634 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 98ef84f..e4693cd 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -14081,52 +14081,62 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type, { idx = idx / width; n = n / width; - if (TREE_CODE (type) == VECTOR_TYPE) + + if (TREE_CODE (arg0) == VECTOR_CST) { - 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 *vals; - unsigned i; - if (CONSTRUCTOR_NELTS (arg0) == 0) - return build_constructor (type, - NULL); - if (TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (arg0, - 0)->value)) - != VECTOR_TYPE) - { - vec_alloc (vals, 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); - } - } + if (n == 1) + return VECTOR_CST_ELT (arg0, idx); + + tree *vals = XALLOCAVEC (tree, n); + for (unsigned i = 0; i < n; ++i) + vals[i] = VECTOR_CST_ELT (arg0, idx + i); + return build_vector (type, vals); } - else if (n == 1) + + /* Constructor elements can be subvectors. */ + unsigned HOST_WIDE_INT k = 1; + if (CONSTRUCTOR_NELTS (arg0) != 0) { - if (TREE_CODE (arg0) == VECTOR_CST) - return VECTOR_CST_ELT (arg0, idx); - else if (CONSTRUCTOR_NELTS (arg0) == 0) - return build_zero_cst (type); - else if (TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (arg0, - 0)->value)) - != VECTOR_TYPE) + tree cons_elem = TREE_TYPE (CONSTRUCTOR_ELT (arg0, 0)->value); + if (TREE_CODE (cons_elem) == VECTOR_TYPE) + k = TYPE_VECTOR_SUBPARTS (cons_elem); + } + + /* We keep an exact subset of the constructor elements. */ + if ((idx % k) == 0 && (n % k) == 0) + { + if (CONSTRUCTOR_NELTS (arg0) == 0) + return build_constructor (type, NULL); + idx /= k; + n /= k; + if (n == 1) { if (idx < CONSTRUCTOR_NELTS (arg0)) return CONSTRUCTOR_ELT (arg0, idx)->value; return build_zero_cst (type); } + + vec *vals; + vec_alloc (vals, n); + for (unsigned 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); + } + /* The bitfield references a single constructor element. */ + else if (idx + n <= (idx / k + 1) * k) + { + if (CONSTRUCTOR_NELTS (arg0) <= idx / k) + return build_zero_cst (type); + else if (n == k) + return CONSTRUCTOR_ELT (arg0, idx / k)->value; + else + return fold_build3_loc (loc, code, type, + CONSTRUCTOR_ELT (arg0, idx / k)->value, op1, + build_int_cst (TREE_TYPE (op2), (idx % k) * width)); } } } diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c index 2203b66..a959ea7 100644 --- a/gcc/tree-ssa-propagate.c +++ b/gcc/tree-ssa-propagate.c @@ -611,10 +611,24 @@ valid_gimple_rhs_p (tree expr) return false; case tcc_exceptional: + if (code == CONSTRUCTOR) + { + unsigned i; + tree elt; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, elt) + if (!is_gimple_val (elt)) + return false; + return true; + } if (code != SSA_NAME) return false; break; + case tcc_reference: + if (code == BIT_FIELD_REF) + return is_gimple_val (TREE_OPERAND (expr, 0)); + return false; + default: return false; }