aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2005-12-15 10:34:44 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2005-12-15 10:34:44 +0000
commit6bec9271941b9b72ad47b3b357a243ed0690baa7 (patch)
tree37e6c4df71824b584a70181905ff6a757f809b5f /gcc
parentcd6dba21ac4803bde1b149365d543dd81500ded5 (diff)
downloadgcc-6bec9271941b9b72ad47b3b357a243ed0690baa7.zip
gcc-6bec9271941b9b72ad47b3b357a243ed0690baa7.tar.gz
gcc-6bec9271941b9b72ad47b3b357a243ed0690baa7.tar.bz2
tree-flow.h (okay_component_ref_for_subvars): Remove.
2005-12-15 Richard Guenther <rguenther@suse.de> * tree-flow.h (okay_component_ref_for_subvars): Remove. (get_ref_base_and_extent): Declare. * tree-dfa.c (okay_component_ref_for_subvars): Remove. (get_ref_base_and_extent): New function. * tree-ssa-alias.c (find_used_portions): Use it. * tree-ssa-structalias.c (get_constraint_for_component_ref): Likewise. * tree-ssa-operands.c (get_expr_operands): Likewise. From-SVN: r108568
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/tree-dfa.c180
-rw-r--r--gcc/tree-flow.h4
-rw-r--r--gcc/tree-ssa-alias.c45
-rw-r--r--gcc/tree-ssa-operands.c11
-rw-r--r--gcc/tree-ssa-structalias.c14
6 files changed, 182 insertions, 83 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index de3e458..dd6bda6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2005-12-15 Richard Guenther <rguenther@suse.de>
+
+ * tree-flow.h (okay_component_ref_for_subvars): Remove.
+ (get_ref_base_and_extent): Declare.
+ * tree-dfa.c (okay_component_ref_for_subvars): Remove.
+ (get_ref_base_and_extent): New function.
+ * tree-ssa-alias.c (find_used_portions): Use it.
+ * tree-ssa-structalias.c (get_constraint_for_component_ref):
+ Likewise.
+ * tree-ssa-operands.c (get_expr_operands): Likewise.
+
2005-12-15 Paolo Bonzini <bonzini@gnu.org>
* combine.c: Remove force_to_mode's fourth parameter.
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index 3f89047..771c9f8 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -792,45 +792,157 @@ find_new_referenced_vars (tree *stmt_p)
}
-/* If REF is a COMPONENT_REF for a structure that can have sub-variables, and
- we know where REF is accessing, return the variable in REF that has the
- sub-variables. If the return value is not NULL, POFFSET will be the
- offset, in bits, of REF inside the return value, and PSIZE will be the
- size, in bits, of REF inside the return value. */
+/* If REF is a handled component reference for a structure, return the
+ base variable. The access range is delimited by bit positions *POFFSET and
+ *POFFSET + *PMAX_SIZE. The access size is *PSIZE bits. If either
+ *PSIZE or *PMAX_SIZE is -1, they could not be determined. If *PSIZE
+ and *PMAX_SIZE are equal, the access is non-variable. */
tree
-okay_component_ref_for_subvars (tree ref, unsigned HOST_WIDE_INT *poffset,
- unsigned HOST_WIDE_INT *psize)
+get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
+ HOST_WIDE_INT *psize,
+ HOST_WIDE_INT *pmax_size)
{
- tree result = NULL;
- HOST_WIDE_INT bitsize;
- HOST_WIDE_INT bitpos;
- tree offset;
- enum machine_mode mode;
- int unsignedp;
- int volatilep;
-
- gcc_assert (!SSA_VAR_P (ref));
- *poffset = 0;
- *psize = (unsigned int) -1;
-
- if (ref_contains_array_ref (ref))
- return result;
- ref = get_inner_reference (ref, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
- if (TREE_CODE (ref) == INDIRECT_REF)
- return result;
- else if (offset == NULL && bitsize != -1 && SSA_VAR_P (ref))
+ HOST_WIDE_INT bitsize = -1;
+ HOST_WIDE_INT maxsize = -1;
+ tree size_tree = NULL_TREE;
+ tree bit_offset = bitsize_zero_node;
+
+ gcc_assert (!SSA_VAR_P (exp));
+
+ /* First get the final access size from just the outermost expression. */
+ if (TREE_CODE (exp) == COMPONENT_REF)
+ size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
+ else if (TREE_CODE (exp) == BIT_FIELD_REF)
+ size_tree = TREE_OPERAND (exp, 1);
+ else
{
- *poffset = bitpos;
- *psize = bitsize;
- if (get_subvars_for_var (ref) != NULL)
- return ref;
+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
+ if (mode == BLKmode)
+ size_tree = TYPE_SIZE (TREE_TYPE (exp));
+ else
+ bitsize = GET_MODE_BITSIZE (mode);
}
- else if (SSA_VAR_P (ref))
+ if (size_tree != NULL_TREE)
{
- if (get_subvars_for_var (ref) != NULL)
- return ref;
+ if (! host_integerp (size_tree, 1))
+ bitsize = -1;
+ else
+ bitsize = TREE_INT_CST_LOW (size_tree);
}
- return NULL_TREE;
+
+ /* Initially, maxsize is the same as the accessed element size.
+ In the following it will only grow (or become -1). */
+ maxsize = bitsize;
+
+ /* Compute cumulative bit-offset for nested component-refs and array-refs,
+ and find the ultimate containing object. */
+ while (1)
+ {
+ switch (TREE_CODE (exp))
+ {
+ case BIT_FIELD_REF:
+ bit_offset = size_binop (PLUS_EXPR, bit_offset,
+ TREE_OPERAND (exp, 2));
+ break;
+
+ case COMPONENT_REF:
+ {
+ tree field = TREE_OPERAND (exp, 1);
+ tree this_offset = component_ref_field_offset (exp);
+
+ if (this_offset && TREE_CODE (this_offset) == INTEGER_CST)
+ {
+ this_offset = size_binop (MULT_EXPR,
+ fold_convert (bitsizetype,
+ this_offset),
+ bitsize_unit_node);
+ bit_offset = size_binop (PLUS_EXPR,
+ bit_offset, this_offset);
+ bit_offset = size_binop (PLUS_EXPR, bit_offset,
+ DECL_FIELD_BIT_OFFSET (field));
+ }
+ else
+ {
+ tree csize = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+ /* We need to adjust maxsize to the whole structure bitsize.
+ But we can subtract any constant offset seen sofar,
+ because that would get us out of the structure otherwise. */
+ if (maxsize != -1
+ && csize && host_integerp (csize, 1))
+ {
+ maxsize = (TREE_INT_CST_LOW (csize)
+ - TREE_INT_CST_LOW (bit_offset));
+ }
+ else
+ maxsize = -1;
+ }
+ }
+ break;
+
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ {
+ tree index = TREE_OPERAND (exp, 1);
+ tree low_bound = array_ref_low_bound (exp);
+ tree unit_size = array_ref_element_size (exp);
+
+ if (! integer_zerop (low_bound))
+ index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
+ index, low_bound);
+ index = size_binop (MULT_EXPR,
+ fold_convert (sizetype, index), unit_size);
+ if (TREE_CODE (index) == INTEGER_CST)
+ {
+ index = size_binop (MULT_EXPR,
+ fold_convert (bitsizetype, index),
+ bitsize_unit_node);
+ bit_offset = size_binop (PLUS_EXPR, bit_offset, index);
+ }
+ else
+ {
+ tree asize = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+ /* We need to adjust maxsize to the whole array bitsize.
+ But we can subtract any constant offset seen sofar,
+ because that would get us outside of the array otherwise. */
+ if (maxsize != -1
+ && asize && host_integerp (asize, 1))
+ {
+ maxsize = (TREE_INT_CST_LOW (asize)
+ - TREE_INT_CST_LOW (bit_offset));
+ }
+ else
+ maxsize = -1;
+ }
+ }
+ break;
+
+ case REALPART_EXPR:
+ break;
+
+ case IMAGPART_EXPR:
+ bit_offset = size_binop (PLUS_EXPR, bit_offset,
+ bitsize_int (bitsize));
+ break;
+
+ case VIEW_CONVERT_EXPR:
+ /* ??? We probably should give up here and bail out. */
+ break;
+
+ default:
+ goto done;
+ }
+
+ exp = TREE_OPERAND (exp, 0);
+ }
+ done:
+
+ /* ??? Due to negative offsets in ARRAY_REF we can end up with
+ negative bit_offset here. We might want to store a zero offset
+ in this case. */
+ *poffset = TREE_INT_CST_LOW (bit_offset);
+ *psize = bitsize;
+ *pmax_size = maxsize;
+
+ return exp;
}
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 62b8027..9ebfeb8 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -592,8 +592,8 @@ static inline subvar_t get_subvars_for_var (tree);
static inline tree get_subvar_at (tree, unsigned HOST_WIDE_INT);
static inline bool ref_contains_array_ref (tree);
static inline bool array_ref_contains_indirect_ref (tree);
-extern tree okay_component_ref_for_subvars (tree, unsigned HOST_WIDE_INT *,
- unsigned HOST_WIDE_INT *);
+extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
+ HOST_WIDE_INT *, HOST_WIDE_INT *);
static inline bool var_can_have_subvars (tree);
static inline bool overlap_subvar (unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 1a9c006..d7d11c1 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -2695,16 +2695,14 @@ find_used_portions (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
case COMPONENT_REF:
{
HOST_WIDE_INT bitsize;
+ HOST_WIDE_INT bitmaxsize;
HOST_WIDE_INT bitpos;
- tree offset;
- enum machine_mode mode;
- int unsignedp;
- int volatilep;
tree ref;
- ref = get_inner_reference (*tp, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
- if (DECL_P (ref) && offset == NULL && bitsize != -1)
- {
+ ref = get_ref_base_and_extent (*tp, &bitpos, &bitsize, &bitmaxsize);
+ if (DECL_P (ref)
+ && var_can_have_subvars (ref)
+ && bitmaxsize != -1)
+ {
size_t uid = DECL_UID (ref);
used_part_t up;
@@ -2712,37 +2710,18 @@ find_used_portions (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
if (bitpos <= up->minused)
up->minused = bitpos;
- if ((bitpos + bitsize >= up->maxused))
- up->maxused = bitpos + bitsize;
+ if ((bitpos + bitmaxsize >= up->maxused))
+ up->maxused = bitpos + bitmaxsize;
- up->explicit_uses = true;
+ if (bitsize == bitmaxsize)
+ up->explicit_uses = true;
+ else
+ up->implicit_uses = true;
up_insert (uid, up);
*walk_subtrees = 0;
return NULL_TREE;
}
- else if (DECL_P (ref))
- {
- if (DECL_SIZE (ref)
- && var_can_have_subvars (ref)
- && TREE_CODE (DECL_SIZE (ref)) == INTEGER_CST)
- {
- used_part_t up;
- size_t uid = DECL_UID (ref);
-
- up = get_or_create_used_part_for (uid);
-
- up->minused = 0;
- up->maxused = TREE_INT_CST_LOW (DECL_SIZE (ref));
-
- up->implicit_uses = true;
-
- up_insert (uid, up);
-
- *walk_subtrees = 0;
- return NULL_TREE;
- }
- }
}
break;
/* This is here to make sure we mark the entire base variable as used
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index c75f30c..0e0f365 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -1133,25 +1133,26 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
case IMAGPART_EXPR:
{
tree ref;
- unsigned HOST_WIDE_INT offset, size;
+ HOST_WIDE_INT offset, size, maxsize;
/* This component ref becomes an access to all of the subvariables
it can touch, if we can determine that, but *NOT* the real one.
If we can't determine which fields we could touch, the recursion
will eventually get to a variable and add *all* of its subvars, or
whatever is the minimum correct subset. */
- ref = okay_component_ref_for_subvars (expr, &offset, &size);
- if (ref)
+ ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize);
+ if (SSA_VAR_P (ref) && get_subvars_for_var (ref))
{
subvar_t svars = get_subvars_for_var (ref);
subvar_t sv;
for (sv = svars; sv; sv = sv->next)
{
bool exact;
- if (overlap_subvar (offset, size, sv, &exact))
+ if (overlap_subvar (offset, maxsize, sv, &exact))
{
int subvar_flags = flags;
- if (!exact)
+ if (!exact
+ || size != maxsize)
subvar_flags &= ~opf_kill_def;
add_stmt_operand (&sv->var, s_ann, subvar_flags);
}
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 7f3446b..9ed4d78 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -2348,11 +2348,8 @@ get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results,
{
tree orig_t = t;
HOST_WIDE_INT bitsize = -1;
+ HOST_WIDE_INT bitmaxsize = -1;
HOST_WIDE_INT bitpos;
- tree offset = NULL_TREE;
- enum machine_mode mode;
- int unsignedp;
- int volatilep;
tree forzero;
struct constraint_expr *result;
unsigned int beforelength = VEC_length (ce_s, *results);
@@ -2374,8 +2371,7 @@ get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results,
return;
}
- t = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
+ t = get_ref_base_and_extent (t, &bitpos, &bitsize, &bitmaxsize);
get_constraint_for (t, results, anyoffset);
result = VEC_last (ce_s, *results);
@@ -2386,11 +2382,11 @@ get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results,
result->type = SCALAR;
/* If we know where this goes, then yay. Otherwise, booo. */
-
- if (offset == NULL && bitsize != -1)
+ if (bitmaxsize != -1
+ && bitsize == bitmaxsize)
{
result->offset = bitpos;
- }
+ }
/* FIXME: Handle the DEREF case. */
else if (anyoffset && result->type != DEREF)
{