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
This commit is contained in:
Diego Novillo 2007-11-07 19:01:38 -05:00 committed by Diego Novillo
parent e4fd5b87bf
commit 6f09f3140c
8 changed files with 100 additions and 13 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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, "}");

View File

@ -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;

View File

@ -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. */

View File

@ -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++;

View File

@ -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. */