diff options
author | Diego Novillo <dnovillo@google.com> | 2007-11-07 19:01:38 -0500 |
---|---|---|
committer | Diego Novillo <dnovillo@gcc.gnu.org> | 2007-11-07 19:01:38 -0500 |
commit | 6f09f3140c724335069034b6b43d391867d43267 (patch) | |
tree | 06efa0a928d92fb0ec421d6bddae19cebfe2145b | |
parent | e4fd5b87bf37f1a58194897e10fae8132470f84a (diff) | |
download | gcc-6f09f3140c724335069034b6b43d391867d43267.zip gcc-6f09f3140c724335069034b6b43d391867d43267.tar.gz gcc-6f09f3140c724335069034b6b43d391867d43267.tar.bz2 |
re PR tree-optimization/33870 (miscompiles sqlite)
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.
From-SVN: r129976
-rw-r--r-- | gcc/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr33870.x | 9 | ||||
-rw-r--r-- | gcc/tree-dfa.c | 2 | ||||
-rw-r--r-- | gcc/tree-flow.h | 4 | ||||
-rw-r--r-- | gcc/tree-ssa-operands.c | 44 | ||||
-rw-r--r-- | gcc/tree-ssa-structalias.c | 24 | ||||
-rw-r--r-- | gcc/tree.h | 6 |
8 files changed, 100 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7cbf17f..efc6293 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2007-11-07 Diego Novillo <dnovillo@google.com> + + 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 <ebotcazou@libertysurf.fr> PR rtl-optimization/33737 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 063d20f..2a863b9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-11-07 Diego Novillo <dnovillo@google.com> + + PR 33870 + * gcc.c-torture/execute/pr33870.x: Remove. + 2007-11-07 Douglas Gregor <doug.gregor@gmail.com> 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 fbf8aae..0000000 --- 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 1ec0264..6ee90d7 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 3421c14..1b63e95 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 9ce133d..87eec74 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 0212499..2d3a40a 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++; @@ -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. */ |