aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Lawrence <alan.lawrence@arm.com>2015-10-30 19:03:14 +0000
committerAlan Lawrence <alalaw01@gcc.gnu.org>2015-10-30 19:03:14 +0000
commit6a6360148aac759fe9fffbbf57e914d281509d72 (patch)
tree048ba4fc557bff29b1270bd479190d404999156b
parent3b1661a9b93fe8000faa6ab4b721a96ffb48d525 (diff)
downloadgcc-6a6360148aac759fe9fffbbf57e914d281509d72.zip
gcc-6a6360148aac759fe9fffbbf57e914d281509d72.tar.gz
gcc-6a6360148aac759fe9fffbbf57e914d281509d72.tar.bz2
Share code from fold_array_ctor_reference with fold.
* gimple-fold.c (fold_array_ctor_reference): Move searching code to: * fold-const.c (get_array_ctor_element_at_index): New. (fold): Remove binary-search through CONSTRUCTOR, call previous. * fold-const.h (get_array_ctor_element_at_index): New. From-SVN: r229605
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/fold-const.c96
-rw-r--r--gcc/fold-const.h1
-rw-r--r--gcc/gimple-fold.c47
4 files changed, 83 insertions, 69 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1edff5d..ee6a34f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2015-10-30 Alan Lawrence <alan.lawrence@arm.com>
+
+ * gimple-fold.c (fold_array_ctor_reference): Move searching code to:
+ * fold-const.c (get_array_ctor_element_at_index): New.
+ (fold): Remove binary-search through CONSTRUCTOR, call previous.
+
+ * fold-const.h (get_array_ctor_element_at_index): New.
+
2015-10-30 Evgeny Stupachenko <evstupac@gmail.com>
* Makefile.in (OBJS): Add multiple_target.o.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 06d0b59..b9168f3 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -11845,6 +11845,73 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
} /* switch (code) */
}
+/* Gets the element ACCESS_INDEX from CTOR, which must be a CONSTRUCTOR
+ of an array (or vector). */
+
+tree
+get_array_ctor_element_at_index (tree ctor, offset_int access_index)
+{
+ tree index_type = NULL_TREE;
+ offset_int low_bound = 0;
+
+ if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE)
+ {
+ tree domain_type = TYPE_DOMAIN (TREE_TYPE (ctor));
+ if (domain_type && TYPE_MIN_VALUE (domain_type))
+ {
+ /* Static constructors for variably sized objects makes no sense. */
+ gcc_assert (TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST);
+ index_type = TREE_TYPE (TYPE_MIN_VALUE (domain_type));
+ low_bound = wi::to_offset (TYPE_MIN_VALUE (domain_type));
+ }
+ }
+
+ if (index_type)
+ access_index = wi::ext (access_index, TYPE_PRECISION (index_type),
+ TYPE_SIGN (index_type));
+
+ offset_int index = low_bound - 1;
+ if (index_type)
+ index = wi::ext (index, TYPE_PRECISION (index_type),
+ TYPE_SIGN (index_type));
+
+ offset_int max_index;
+ unsigned HOST_WIDE_INT cnt;
+ tree cfield, cval;
+
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
+ {
+ /* Array constructor might explicitely set index, or specify range
+ * or leave index NULL meaning that it is next index after previous
+ * one. */
+ if (cfield)
+ {
+ if (TREE_CODE (cfield) == INTEGER_CST)
+ max_index = index = wi::to_offset (cfield);
+ else
+ {
+ gcc_assert (TREE_CODE (cfield) == RANGE_EXPR);
+ index = wi::to_offset (TREE_OPERAND (cfield, 0));
+ max_index = wi::to_offset (TREE_OPERAND (cfield, 1));
+ }
+ }
+ else
+ {
+ index += 1;
+ if (index_type)
+ index = wi::ext (index, TYPE_PRECISION (index_type),
+ TYPE_SIGN (index_type));
+ max_index = index;
+ }
+
+ /* Do we have match? */
+ if (wi::cmpu (access_index, index) >= 0
+ && wi::cmpu (access_index, max_index) <= 0)
+ return cval;
+ }
+ return NULL_TREE;
+}
+
/* Perform constant folding and related simplification of EXPR.
The related simplifications include x*1 => x, x*0 => 0, etc.,
and application of the associative law.
@@ -11921,31 +11988,10 @@ fold (tree expr)
&& TREE_CODE (op0) == CONSTRUCTOR
&& ! type_contains_placeholder_p (TREE_TYPE (op0)))
{
- vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (op0);
- unsigned HOST_WIDE_INT end = vec_safe_length (elts);
- unsigned HOST_WIDE_INT begin = 0;
-
- /* Find a matching index by means of a binary search. */
- while (begin != end)
- {
- unsigned HOST_WIDE_INT middle = (begin + end) / 2;
- tree index = (*elts)[middle].index;
-
- if (TREE_CODE (index) == INTEGER_CST
- && tree_int_cst_lt (index, op1))
- begin = middle + 1;
- else if (TREE_CODE (index) == INTEGER_CST
- && tree_int_cst_lt (op1, index))
- end = middle;
- else if (TREE_CODE (index) == RANGE_EXPR
- && tree_int_cst_lt (TREE_OPERAND (index, 1), op1))
- begin = middle + 1;
- else if (TREE_CODE (index) == RANGE_EXPR
- && tree_int_cst_lt (op1, TREE_OPERAND (index, 0)))
- end = middle;
- else
- return (*elts)[middle].value;
- }
+ tree val = get_array_ctor_element_at_index (op0,
+ wi::to_offset (op1));
+ if (val)
+ return val;
}
return t;
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 8e49c98..97d18cf 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -73,6 +73,7 @@ extern tree fold_build_call_array_loc (location_t, tree, tree, int, tree *);
#define fold_build_call_array_initializer(T1,T2,N,T4)\
fold_build_call_array_initializer_loc (UNKNOWN_LOCATION, T1, T2, N, T4)
extern tree fold_build_call_array_initializer_loc (location_t, tree, tree, int, tree *);
+extern tree get_array_ctor_element_at_index (tree, offset_int);
extern bool fold_convertible_p (const_tree, const_tree);
#define fold_convert(T1,T2)\
fold_convert_loc (UNKNOWN_LOCATION, T1, T2)
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 77c3e75..c9b9593 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -5301,13 +5301,10 @@ fold_array_ctor_reference (tree type, tree ctor,
unsigned HOST_WIDE_INT size,
tree from_decl)
{
- unsigned HOST_WIDE_INT cnt;
- tree cfield, cval;
offset_int low_bound;
offset_int elt_size;
- offset_int index, max_index;
offset_int access_index;
- tree domain_type = NULL_TREE, index_type = NULL_TREE;
+ tree domain_type = NULL_TREE;
HOST_WIDE_INT inner_offset;
/* Compute low bound and elt size. */
@@ -5317,7 +5314,6 @@ fold_array_ctor_reference (tree type, tree ctor,
{
/* Static constructors for variably sized objects makes no sense. */
gcc_assert (TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST);
- index_type = TREE_TYPE (TYPE_MIN_VALUE (domain_type));
low_bound = wi::to_offset (TYPE_MIN_VALUE (domain_type));
}
else
@@ -5339,9 +5335,6 @@ fold_array_ctor_reference (tree type, tree ctor,
access_index = wi::udiv_trunc (offset_int (offset / BITS_PER_UNIT),
elt_size);
access_index += low_bound;
- if (index_type)
- access_index = wi::ext (access_index, TYPE_PRECISION (index_type),
- TYPE_SIGN (index_type));
/* And offset within the access. */
inner_offset = offset % (elt_size.to_uhwi () * BITS_PER_UNIT);
@@ -5350,43 +5343,9 @@ fold_array_ctor_reference (tree type, tree ctor,
care to fold accesses spanning multiple array indexes. */
if (inner_offset + size > elt_size.to_uhwi () * BITS_PER_UNIT)
return NULL_TREE;
+ if (tree val = get_array_ctor_element_at_index (ctor, access_index))
+ return fold_ctor_reference (type, val, inner_offset, size, from_decl);
- index = low_bound - 1;
- if (index_type)
- index = wi::ext (index, TYPE_PRECISION (index_type),
- TYPE_SIGN (index_type));
-
- FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
- {
- /* Array constructor might explicitely set index, or specify range
- or leave index NULL meaning that it is next index after previous
- one. */
- if (cfield)
- {
- if (TREE_CODE (cfield) == INTEGER_CST)
- max_index = index = wi::to_offset (cfield);
- else
- {
- gcc_assert (TREE_CODE (cfield) == RANGE_EXPR);
- index = wi::to_offset (TREE_OPERAND (cfield, 0));
- max_index = wi::to_offset (TREE_OPERAND (cfield, 1));
- }
- }
- else
- {
- index += 1;
- if (index_type)
- index = wi::ext (index, TYPE_PRECISION (index_type),
- TYPE_SIGN (index_type));
- max_index = index;
- }
-
- /* Do we have match? */
- if (wi::cmpu (access_index, index) >= 0
- && wi::cmpu (access_index, max_index) <= 0)
- return fold_ctor_reference (type, cval, inner_offset, size,
- from_decl);
- }
/* When memory is not explicitely mentioned in constructor,
it is 0 (or out of range). */
return build_zero_cst (type);