aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
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 /gcc/fold-const.c
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
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c86
1 files changed, 48 insertions, 38 deletions
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));
}
}
}