From f5ef996258725dd451733c21e2bba88c87019646 Mon Sep 17 00:00:00 2001 From: dnovillo Date: Thu, 8 Nov 2007 00:01:38 +0000 Subject: [PATCH] PR 33870 * tree.h (struct tree_struct_field_tag): Add field in_nested_struct. (SFT_IN_NESTED_STRUCT): Define. * tree-dfa.c (dump_subvars_for): Show offset of each sub-var. * tree-flow.h (struct fieldoff): Add field in_nested_struct. * tree-ssa-structalias.c (struct variable_info): Likewise. (push_fields_onto_fieldstack): If OFFSET is positive, set in_nested_struct. (create_variable_info_for): Copy setting of in_nested_struct from the field offset object. (set_uids_in_ptset): Set SFT_IN_NESTED_STRUCT from the variable info object. * tree-ssa-operands.c (add_vars_for_offset): If VAR belongs to a nested structure, adjust OFFSET by SFT_OFFSET(VAR). testsuite/ChangeLog * gcc.c-torture/execute/pr33870.x: Remove. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@129976 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 19 ++++++++++++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.c-torture/execute/pr33870.x | 9 ------ gcc/tree-dfa.c | 2 +- gcc/tree-flow.h | 4 +++ gcc/tree-ssa-operands.c | 44 +++++++++++++++++++++++++-- gcc/tree-ssa-structalias.c | 24 ++++++++++++++- gcc/tree.h | 6 ++++ 8 files changed, 100 insertions(+), 13 deletions(-) delete mode 100644 gcc/testsuite/gcc.c-torture/execute/pr33870.x diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7cbf17fd8ba..efc629375ef 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2007-11-07 Diego Novillo + + PR 33870 + * tree.h (struct tree_struct_field_tag): Add field in_nested_struct. + (SFT_IN_NESTED_STRUCT): Define. + * tree-dfa.c (dump_subvars_for): Show offset of each + sub-var. + * tree-flow.h (struct fieldoff): Add field in_nested_struct. + * tree-ssa-structalias.c (struct variable_info): Likewise. + (push_fields_onto_fieldstack): If OFFSET is positive, + set in_nested_struct. + (create_variable_info_for): Copy setting of + in_nested_struct from the field offset object. + (set_uids_in_ptset): Set SFT_IN_NESTED_STRUCT from the + variable info object. + * tree-ssa-operands.c (add_vars_for_offset): If VAR + belongs to a nested structure, adjust OFFSET by + SFT_OFFSET(VAR). + 2007-11-07 Eric Botcazou PR rtl-optimization/33737 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 063d20f97ce..2a863b9463f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-11-07 Diego Novillo + + PR 33870 + * gcc.c-torture/execute/pr33870.x: Remove. + 2007-11-07 Douglas Gregor PR c++/33045 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr33870.x b/gcc/testsuite/gcc.c-torture/execute/pr33870.x deleted file mode 100644 index fbf8aae4ab6..00000000000 --- a/gcc/testsuite/gcc.c-torture/execute/pr33870.x +++ /dev/null @@ -1,9 +0,0 @@ -# The test breaks because of wrong alias info for -O2 and -Os - -set torture_eval_before_compile { - if {[string match {*-O[2s]*} "$option"]} { - set torture_execute_xfail "*-*-*" - } -} - -return 0 diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index 1ec0264a5fa..6ee90d74617 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -287,7 +287,7 @@ dump_subvars_for (FILE *file, tree var) for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i) { print_generic_expr (file, subvar, dump_flags); - fprintf (file, " "); + fprintf (file, "@" HOST_WIDE_INT_PRINT_UNSIGNED " ", SFT_OFFSET (subvar)); } fprintf (file, "}"); diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 3421c14b97d..1b63e95d3bd 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -1159,6 +1159,10 @@ struct fieldoff /* Field. */ tree decl; + /* True if this field is inside a structure nested inside the base + containing object. */ + unsigned int in_nested_struct : 1; + /* Offset from the base of the base containing object to this field. */ HOST_WIDE_INT offset; diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 9ce133d5eae..87eec7452b7 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -1397,8 +1397,48 @@ add_vars_for_offset (tree var, unsigned HOST_WIDE_INT offset, subvar_t sv; unsigned int i; - /* Adjust offset by the pointed-to location. */ - offset += SFT_OFFSET (var); + if (SFT_IN_NESTED_STRUCT (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. + + For instance, given the following structure: + + struct X { + int a; + struct Y { + int b; + struct Z { + int c[3]; + } d; + } e; + } m; + + and the following address expression: + + p_1 = &m.e.d; + + This structure will receive 5 SFTs, namely 2 for fields 'a' + and 'b' and 3 for the array 'c' in struct Z. So, the + reference p_1->c[2] and m.e.d.c[2] access the exact same + memory location (ie, SFT.5). + + Now, alias analysis computed the points-to set for pointer + p_1 as { SFT.3 } because that is the first field that p_1 + actually points to. When the expression p_1->c[2] is + analyzed, get_ref_base_and_extent will return an offset of 96 + because we are accessing the third element of the array. But + the SFT we are looking for is actually at offset 160, + counting from the top of struct X. + + Therefore, we adjust OFFSET by the offset of VAR so that we + can get at all the fields starting at VAR. */ + offset += SFT_OFFSET (var); + } /* Add all subvars of var that overlap with the access. Binary search for the first relevant SFT. */ diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 02124992b5b..2d3a40a8731 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -253,6 +253,15 @@ struct variable_info variable. This is used for C++ placement new. */ unsigned int no_tbaa_pruning : 1; + /* True if this variable is inside a structure nested in the + structure for the base variable. For instance, in + struct X { int a; struct Y { int b; int c; } }, the variables for + fields 'b' and 'c' are inside a nested structure. We are not + interested in tracking how many levels of nesting, just whether + there is nesting at all. This is later used to adjust offsets + for pointers pointing into sub-structures. */ + unsigned int in_nested_struct : 1; + /* Points-to set for this variable. */ bitmap solution; @@ -4133,6 +4142,12 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, pair->alias_set = get_alias_set (addressable_type); else pair->alias_set = -1; + + /* If the base offset is positive, this field belongs to + a structure nested inside the base structure. */ + if (offset > 0) + pair->in_nested_struct = true; + count++; } else @@ -4181,6 +4196,12 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, pair->alias_set = get_alias_set (addressable_type); else pair->alias_set = -1; + + /* If the base offset is positive, this field belongs to + a structure nested inside the base structure. */ + if (offset > 0) + pair->in_nested_struct = true; + count++; } else @@ -4491,6 +4512,7 @@ create_variable_info_for (tree decl, const char *name) newvi->offset = fo->offset; newvi->size = TREE_INT_CST_LOW (fo->size); newvi->fullsize = vi->fullsize; + newvi->in_nested_struct = fo->in_nested_struct; insert_into_field_list (vi, newvi); VEC_safe_push (varinfo_t, heap, varmap, newvi); if (is_global && (!flag_whole_program || !in_ipa_mode)) @@ -4743,6 +4765,7 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed, || (!is_derefed && !vi->directly_dereferenced) || alias_sets_conflict_p (ptr_alias_set, var_alias_set)) bitmap_set_bit (into, DECL_UID (sft)); + SFT_IN_NESTED_STRUCT (sft) = vi->in_nested_struct; } } else @@ -4946,7 +4969,6 @@ find_what_p_points_to (tree p) } /* Share the final set of variables when possible. */ - finished_solution = BITMAP_GGC_ALLOC (); stats.points_to_sets_created++; diff --git a/gcc/tree.h b/gcc/tree.h index ede0cd8303b..d82ce850eff 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2573,15 +2573,21 @@ struct tree_struct_field_tag GTY(()) /* Size of the field. */ unsigned HOST_WIDE_INT size; + /* True if this SFT is for a field in a nested structure. */ + unsigned int in_nested_struct : 1; + /* Alias set for a DECL_NONADDRESSABLE_P field. Otherwise -1. */ alias_set_type alias_set; }; + #define SFT_PARENT_VAR(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.parent_var) #define SFT_OFFSET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.offset) #define SFT_SIZE(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.size) #define SFT_NONADDRESSABLE_P(NODE) \ (STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set != -1) #define SFT_ALIAS_SET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set) +#define SFT_IN_NESTED_STRUCT(NODE) \ + (STRUCT_FIELD_TAG_CHECK (NODE)->sft.in_nested_struct) /* Memory Partition Tags (MPTs) group memory symbols under one common name for the purposes of placing memory PHI nodes. */ -- 2.11.4.GIT