summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-operands.c
diff options
context:
space:
mode:
authorDiego Novillo <dnovillo@gcc.gnu.org>2007-11-13 10:20:40 -0500
committerDiego Novillo <dnovillo@gcc.gnu.org>2007-11-13 10:20:40 -0500
commitd770555138f40fb929b5456b1548a92ebb60e6aa (patch)
treeb04ec56bade931807b6ed40c6d251c05aa588f0b /gcc/tree-ssa-operands.c
parent0e506c4b4f1efe03e05b80fbc09bb77f474372a1 (diff)
downloadgcc-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.c52
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
{