From 3fefae7a51f38acf585785f19e5dac4bd01b7172 Mon Sep 17 00:00:00 2001 From: rguenth Date: Thu, 15 Dec 2005 10:34:44 +0000 Subject: [PATCH] 2005-12-15 Richard Guenther * 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 --- gcc/ChangeLog | 11 +++ gcc/tree-dfa.c | 180 ++++++++++++++++++++++++++++++++++++--------- gcc/tree-flow.h | 4 +- gcc/tree-ssa-alias.c | 45 +++--------- gcc/tree-ssa-operands.c | 11 +-- gcc/tree-ssa-structalias.c | 14 ++-- 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 + + * 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 * 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) { -- 2.7.4