diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-12-15 10:34:44 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-12-15 10:34:44 +0000 |
commit | 3fefae7a51f38acf585785f19e5dac4bd01b7172 (patch) | |
tree | 37e6c4df71824b584a70181905ff6a757f809b5f /gcc/tree-dfa.c | |
parent | b1fc8ef135b900872d46ae829c4793a6019792dd (diff) | |
download | gcc-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.c | 180 |
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; } |