diff options
author | dberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-13 00:46:07 +0000 |
---|---|---|
committer | dberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-13 00:46:07 +0000 |
commit | 2be14d8b4c2974628dc7594f5d85b86c405e7d28 (patch) | |
tree | 03744f60b00db0493040ec2c836323945507bf16 /gcc/tree-ssa-operands.c | |
parent | 74637d104fa133d2792bd8f1e72069ba0b285523 (diff) | |
download | gcc-2be14d8b4c2974628dc7594f5d85b86c405e7d28.tar.gz |
In gcc/ada/
2005-03-12 Daniel Berlin <dberlin@dberlin.org>
* misc.c (gnat_post_options): Turn off structural
aliasing for now.
In gcc/
2005-03-12 Daniel Berlin <dberlin@dberlin.org>
* tree-flow-inline.h (ref_contains_array_ref): New function.
(lookup_subvars_for_var): Ditto.
(get_subvars_for_var): Ditto.
(var_can_have_subvars): Ditto.
* tree-flow.h (mem_tag_kind): Add STRUCT_FIELD.
(struct subvar): New type.
* tree-dfa.c (okay_component_ref_for_subvars): New function.
* tree-optimize.c (init_tree_optimization_passes): Call
pass_create_structure_vars.
* tree-ssa-alias.c: Include vec.h.
(init_alias_info): Don't auto-clear call clobbered on struct-field
tags.
(compute_flow_insensitive_aliasing): Handle subvars.
(group_aliases): Handle STRUCT_FIELD aliases.
(setup_pointers_and_addressables): Ditto.
Don't mark variables non-addressable if they still have
addressable subvars.
Also mark subvars addressable when the real variable is marked
addressable.
(add_pointed_to_var): Try to prune the pointed-to set by only
pointing to subvars when possible.
Otherwise, make sure we set addresses_needed and pt_vars to
properly include subvars.
(bitpos_of_field): New function.
(push_fields_onto_fieldstack): Ditto.
(get_or_create_used_part_for): Ditto.
(create_overlap_variables_for): Ditto.
(find_used_portions): Ditto.
(create_structure_vars): Ditto.
(pass_create_structure_vars): New structure.
* tree-ssa-operands.c (finalize_ssa_v_must_defs): Remove assert.
(get_expr_operands): Handle subvars. Also try to turn
COMPONENT_REF accesses into must-defs now that we can accurately
portray it.
(note_addressable): Try to only mark as addressable those subvars
we know a COMPONENT_REF touches.
(overlap_subvar): New function.
* tree-vect-analyze.c (vect_object_analysis): Add new parameter.
Handle subvar storing.
(vect_address_analysis): Update caller of vect_object_analysis.
* tree-vect-transform.c (vect_create_data_ref_ptr): Copy subvars.
* tree-vectorizer.h (struct _stmt_vec_info): Add subvars member.
(STMT_VINFO_SUBVARS): New macro.
* common.opts: add flag_tree_salias.
* opts.c (decode_options): flag_tree_salias defaults to on.
* doc/invoke.texi: Document fdump-tree-svars and -ftree-salias.
* doc/tree-ssa.texi: Document structural alias analysis.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@96362 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-operands.c')
-rw-r--r-- | gcc/tree-ssa-operands.c | 181 |
1 files changed, 142 insertions, 39 deletions
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 47b4f1b930f..8db74e1fadb 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -683,8 +683,12 @@ finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p, if (num == 0) return NULL; - /* There should only be a single V_MUST_DEF per assignment. */ - gcc_assert (TREE_CODE (stmt) != MODIFY_EXPR || num <= 1); + /* In the presence of subvars, there may be more than one V_MUST_DEF per + statement (one for each subvar). It is a bit expensive to verify that + all must-defs in a statement belong to subvars if there is more than one + MUST-def, so we don't do it. Suffice to say, if you reach here without + having subvars, and have num >1, you have hit a bug. */ + old_ops = *old_ops_p; @@ -907,7 +911,6 @@ build_ssa_operands (tree stmt, stmt_ann_t ann, stmt_operands_p old_ops, lhs = TREE_OPERAND (lhs, 0); if (TREE_CODE (lhs) != ARRAY_REF && TREE_CODE (lhs) != ARRAY_RANGE_REF - && TREE_CODE (lhs) != COMPONENT_REF && TREE_CODE (lhs) != BIT_FIELD_REF && TREE_CODE (lhs) != REALPART_EXPR && TREE_CODE (lhs) != IMAGPART_EXPR) @@ -1021,6 +1024,49 @@ get_stmt_operands (tree stmt) } +/* Return true if OFFSET and SIZE define a range that overlaps with some + portion of the range of SV, a subvar. If there was an exact overlap, + *EXACT will be set to true upon return. */ + +static bool +overlap_subvar (HOST_WIDE_INT offset, HOST_WIDE_INT size, + subvar_t sv, bool *exact) +{ + /* There are three possible cases of overlap. + 1. We can have an exact overlap, like so: + |offset, offset + size | + |sv->offset, sv->offset + sv->size | + + 2. We can have offset starting after sv->offset, like so: + + |offset, offset + size | + |sv->offset, sv->offset + sv->size | + + 3. We can have offset starting before sv->offset, like so: + + |offset, offset + size | + |sv->offset, sv->offset + sv->size| + */ + + if (exact) + *exact = false; + if (offset == sv->offset && size == sv->size) + { + if (exact) + *exact = true; + return true; + } + else if (offset >= sv->offset && offset < (sv->offset + sv->size)) + { + return true; + } + else if (offset < sv->offset && (offset + size > sv->offset)) + { + return true; + } + return false; + +} /* Recursively scan the expression pointed by EXPR_P in statement referred to by INFO. FLAGS is one of the OPF_* constants modifying how to interpret the operands found. */ @@ -1068,11 +1114,25 @@ get_expr_operands (tree stmt, tree *expr_p, int flags) case PARM_DECL: case RESULT_DECL: case CONST_DECL: - /* If we found a variable, add it to DEFS or USES depending - on the operand flags. */ - add_stmt_operand (expr_p, s_ann, flags); - return; - + { + subvar_t svars; + + /* Add the subvars for a variable if it has subvars, to DEFS or USES. + Otherwise, add the variable itself. + Whether it goes to USES or DEFS depends on the operand flags. */ + if (var_can_have_subvars (expr) + && (svars = get_subvars_for_var (expr))) + { + subvar_t sv; + for (sv = svars; sv; sv = sv->next) + add_stmt_operand (&sv->var, s_ann, flags); + } + else + { + add_stmt_operand (expr_p, s_ann, flags); + } + return; + } case MISALIGNED_INDIRECT_REF: get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags); /* fall through */ @@ -1104,30 +1164,39 @@ get_expr_operands (tree stmt, tree *expr_p, int flags) case COMPONENT_REF: case REALPART_EXPR: case IMAGPART_EXPR: - /* Similarly to arrays, references to compound variables (complex - types and structures/unions) are globbed. - - FIXME: This means that - - a.x = 6; - a.y = 7; - foo (a.x, a.y); - - will not be constant propagated because the two partial - definitions to 'a' will kill each other. Note that SRA may be - able to fix this problem if 'a' can be scalarized. */ - - /* If the LHS of the compound reference is not a regular variable, - recurse to keep looking for more operands in the subexpression. */ - if (SSA_VAR_P (TREE_OPERAND (expr, 0))) - add_stmt_operand (expr_p, s_ann, flags); - else - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); - - if (code == COMPONENT_REF) - get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none); - return; - + { + tree ref; + HOST_WIDE_INT offset, size; + /* 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) + { + 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 (exact) + flags &= ~opf_kill_def; + add_stmt_operand (&sv->var, s_ann, flags); + } + } + } + else + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), + flags & ~opf_kill_def); + + if (code == COMPONENT_REF) + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none); + return; + } case WITH_SIZE_EXPR: /* WITH_SIZE_EXPR is a pass-through reference to its first argument, and an rvalue reference to its second argument. */ @@ -1158,7 +1227,6 @@ get_expr_operands (tree stmt, tree *expr_p, int flags) op = TREE_OPERAND (expr, 0); if (TREE_CODE (op) == ARRAY_REF || TREE_CODE (op) == ARRAY_RANGE_REF - || TREE_CODE (op) == COMPONENT_REF || TREE_CODE (op) == REALPART_EXPR || TREE_CODE (op) == IMAGPART_EXPR) subflags = opf_is_def; @@ -1554,9 +1622,10 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags) { if (flags & opf_kill_def) { - /* Only regular variables may get a V_MUST_DEF - operand. */ - gcc_assert (v_ann->mem_tag_kind == NOT_A_TAG); + /* Only regular variables or struct fields may get a + V_MUST_DEF operand. */ + gcc_assert (v_ann->mem_tag_kind == NOT_A_TAG + || v_ann->mem_tag_kind == STRUCT_FIELD); /* V_MUST_DEF for non-aliased, non-GIMPLE register variable definitions. */ append_v_must_def (var); @@ -1615,26 +1684,60 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags) } } - + /* Record that VAR had its address taken in the statement with annotations S_ANN. */ static void note_addressable (tree var, stmt_ann_t s_ann) { + tree ref; + subvar_t svars; + HOST_WIDE_INT offset; + HOST_WIDE_INT size; + if (!s_ann) return; + + /* If this is a COMPONENT_REF, and we know exactly what it touches, we only + take the address of the subvariables it will touch. + Otherwise, we take the address of all the subvariables, plus the real + ones. */ + if (var && TREE_CODE (var) == COMPONENT_REF + && (ref = okay_component_ref_for_subvars (var, &offset, &size))) + { + subvar_t sv; + svars = get_subvars_for_var (ref); + + if (s_ann->addresses_taken == NULL) + s_ann->addresses_taken = BITMAP_GGC_ALLOC (); + + for (sv = svars; sv; sv = sv->next) + { + if (overlap_subvar (offset, size, sv, NULL)) + bitmap_set_bit (s_ann->addresses_taken, var_ann (sv->var)->uid); + } + return; + } + var = get_base_address (var); if (var && SSA_VAR_P (var)) { if (s_ann->addresses_taken == NULL) - s_ann->addresses_taken = BITMAP_GGC_ALLOC (); + s_ann->addresses_taken = BITMAP_GGC_ALLOC (); + bitmap_set_bit (s_ann->addresses_taken, var_ann (var)->uid); + if (var_can_have_subvars (var) + && (svars = get_subvars_for_var (var))) + { + subvar_t sv; + for (sv = svars; sv; sv = sv->next) + bitmap_set_bit (s_ann->addresses_taken, var_ann (sv->var)->uid); + } } } - /* Add clobbering definitions for .GLOBAL_VAR or for each of the call clobbered variables in the function. */ |