summaryrefslogtreecommitdiff
path: root/gcc/tree-dfa.c
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2005-12-15 10:34:44 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2005-12-15 10:34:44 +0000
commit3fefae7a51f38acf585785f19e5dac4bd01b7172 (patch)
tree37e6c4df71824b584a70181905ff6a757f809b5f /gcc/tree-dfa.c
parentb1fc8ef135b900872d46ae829c4793a6019792dd (diff)
downloadgcc-3fefae7a51f38acf585785f19e5dac4bd01b7172.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@108568 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-dfa.c')
-rw-r--r--gcc/tree-dfa.c180
1 files changed, 146 insertions, 34 deletions
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index 3f89047714b..771c9f8d4ab 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;
}