* 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
+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
+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
+++ /dev/null
-# 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
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, "}");
/* 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;
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. */
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;
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
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
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))
|| (!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
}
/* Share the final set of variables when possible. */
-
finished_solution = BITMAP_GGC_ALLOC ();
stats.points_to_sets_created++;
/* 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. */