diff options
author | Diego Novillo <dnovillo@gcc.gnu.org> | 2007-11-13 10:20:40 -0500 |
---|---|---|
committer | Diego Novillo <dnovillo@gcc.gnu.org> | 2007-11-13 10:20:40 -0500 |
commit | d770555138f40fb929b5456b1548a92ebb60e6aa (patch) | |
tree | b04ec56bade931807b6ed40c6d251c05aa588f0b /gcc/tree-ssa-operands.c | |
parent | 0e506c4b4f1efe03e05b80fbc09bb77f474372a1 (diff) | |
download | gcc-d770555138f40fb929b5456b1548a92ebb60e6aa.tar.gz |
pr 33870
pr 33870
* tree.h (strcut tree_memory_tag): add field unpartitionable.
remove field in_nested_struct.
(struct tree_struct_field_tag): add field nesting_level.
(sft_in_nested_struct): remove.
(sft_nesting_level): define.
(sft_unpartitionable_p): define.
* tree-ssa-alias.c (mem_sym_score): if mp->var is not
partitionable, return long_max.
(compute_memory_partitions): do not partition sfts marked
unpartitionable.
(create_sft): add argument nesting_level. set
sft_nesting_level with it. update all users.
(create_overlap_variables_for): show nesting level.
* tree-dfa.c (dump_subvars_for): likewise.
(dump_variable): likewise.
show whether the sft is partitionable or not.
* tree-flow.h (struct fieldoff): remove field
in_nested_struct.
add field nesting_level.
* tree-ssa-structalias.c (struct variable_info): remove
field in_nested_struct.
(push_fields_onto_fieldstack): add argument
nesting_level. update all users.
update documentation.
update pair->nesting_level with nesting_level.
make recursive calls with nesting_level + 1.
(set_uids_in_ptset): if an sft is added to the points-to
set, mark it as unpartitionable.
* tree-ssa-operands.c (ref_nesting_level): new.
(add_vars_for_offset): call it.
add argument full_ref. update
callers.
if var is inside a nested structure and the nesting level
of full_ref is lower than the nesting level of var,
adjust offset by the offset of var.
testsuite/ChangeLog
PR 33870
* gcc.c-torture/execute/pr33870-1.c: New test.
* gcc.dg/tree-ssa/alias-16.c: New test.
From-SVN: r130141
Diffstat (limited to 'gcc/tree-ssa-operands.c')
-rw-r--r-- | gcc/tree-ssa-operands.c | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 87eec7452b7..cd8ade68639 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -1367,8 +1367,33 @@ access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset, return true; } + +/* Given an aggregate expression FULL_REF, return the number of + aggregates that are containing FULL_REF. So, given a structure + reference a.b.c.d, the nesting level for this expression is 2 (the + number of '.' in the expression minus 1). */ + +static unsigned +ref_nesting_level (tree full_ref) +{ + unsigned nesting_level = 0; + + if (!handled_component_p (full_ref)) + return 0; + + full_ref = TREE_OPERAND (full_ref, 0); + while (handled_component_p (full_ref)) + { + nesting_level++; + full_ref = TREE_OPERAND (full_ref, 0); + } + + return nesting_level; +} + + /* Add the actual variables FULL_REF can access, given a member of - full_ref's points-to set VAR, where FULL_REF is an access of SIZE at + FULL_REF's points-to set VAR, where FULL_REF is an access of SIZE at OFFSET from var. IS_CALL_SITE is true if this is a call, and IS_DEF is true if this is supposed to be a vdef, and false if this should be a VUSE. @@ -1386,10 +1411,12 @@ access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset, This is necessary because foop only actually points to foo's first member, so that is all the points-to set contains. However, an access to foop->a may be touching some single SFT if we have created some - SFT's for a structure. */ + SFT's for a structure. + + FULL_REF is the original memory expression being analyzed. */ static bool -add_vars_for_offset (tree var, unsigned HOST_WIDE_INT offset, +add_vars_for_offset (tree full_ref, tree var, unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size, bool is_def) { bool added = false; @@ -1397,14 +1424,21 @@ add_vars_for_offset (tree var, unsigned HOST_WIDE_INT offset, subvar_t sv; unsigned int i; - if (SFT_IN_NESTED_STRUCT (var)) + if (full_ref + && SFT_NESTING_LEVEL (var) > 0 + && ref_nesting_level (full_ref) < SFT_NESTING_LEVEL (var)) { /* Since VAR is an SFT inside a nested structure, the OFFSET computed by get_ref_base_and_extent is the offset from the - start of the immediately containing structure. However, to - find out what other SFTs are affected by this reference, we - need to know the offsets starting at the root structure in - the nesting hierarchy. + start of the immediately containing structure. If VAR is an + SFT inside a nested structure, then FULL_REF may be a + reference to the structure immediately enclosing SFT, and so + OFFSET will be the offset from the start of the immediately + enclosing structure. + + However, to find out what other SFTs are affected by this + reference, we need to know the offsets starting at the root + structure in the nesting hierarchy. For instance, given the following structure: @@ -1541,7 +1575,7 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags, if it is a potential points-to location. */ if (TREE_CODE (al) == STRUCT_FIELD_TAG && TREE_CODE (var) == NAME_MEMORY_TAG) - none_added &= !add_vars_for_offset (al, offset, size, + none_added &= !add_vars_for_offset (full_ref, al, offset, size, flags & opf_def); else { |