aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2012-11-28 11:11:27 +0100
committerMarc Glisse <glisse@gcc.gnu.org>2012-11-28 10:11:27 +0000
commite9d6bd8c9b12e8022cdb18d492f41e9f5e46c114 (patch)
treecfedd2f3857f9383136b9f4f7f838c9bfb22dcc0
parent2c3e2ce268d8285936c6ecd3d478f70be407194f (diff)
downloadgcc-e9d6bd8c9b12e8022cdb18d492f41e9f5e46c114.zip
gcc-e9d6bd8c9b12e8022cdb18d492f41e9f5e46c114.tar.gz
gcc-e9d6bd8c9b12e8022cdb18d492f41e9f5e46c114.tar.bz2
re PR middle-end/55266 (vector expansion: 24 movs for 4 adds)
2012-11-28 Marc Glisse <marc.glisse@inria.fr> 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. From-SVN: r193884
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/fold-const.c86
-rw-r--r--gcc/tree-ssa-propagate.c14
3 files changed, 70 insertions, 38 deletions
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 <marc.glisse@inria.fr>
+
+ 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 <rguenther@suse.de>
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<constructor_elt, va_gc> *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<constructor_elt, va_gc> *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;
}