aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Novillo <dnovillo@google.com>2007-11-08 00:01:38 +0000
committerDiego Novillo <dnovillo@google.com>2007-11-08 00:01:38 +0000
commit76808307b5442ec4f46e9ec13ea03c45a70c1fd8 (patch)
tree06efa0a928d92fb0ec421d6bddae19cebfe2145b
parentfe8d169bb1f6b10602e495ec8acbe82f62dcb9dc (diff)
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: https://gcc.gnu.org/svn/gcc/trunk@129976 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr33870.x9
-rw-r--r--gcc/tree-dfa.c2
-rw-r--r--gcc/tree-flow.h4
-rw-r--r--gcc/tree-ssa-operands.c44
-rw-r--r--gcc/tree-ssa-structalias.c24
-rw-r--r--gcc/tree.h6
8 files changed, 100 insertions, 13 deletions
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 <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 063d20f97ce..2a863b9463f 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 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. */