aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog28
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr39074-2.c34
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr39074-3.c25
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr39074.c31
-rw-r--r--gcc/tree-ssa-structalias.c156
6 files changed, 226 insertions, 55 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b6b9124..4d9cf7d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,31 @@
+2009-02-19 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/39207
+ PR tree-optimization/39074
+ * tree-ssa-structalias.c (storedanything_id, var_storedanything,
+ storedanything_tree): New.
+ (do_ds_constraint): Simplify ANYTHING shortcutting. Update
+ the STOREDANYTHING solution if the lhs solution contains
+ ANYTHING.
+ (build_succ_graph): Add edges from STOREDANYTHING to all
+ non-direct nodes.
+ (init_base_vars): Initialize STOREDANYTHING.
+ (compute_points_to_sets): Free substitution info after
+ building the succ graph.
+ (ipa_pta_execute): Likewise.
+
+ * tree-ssa-structalias.c (struct variable_info): Add may_have_pointers
+ field.
+ (do_ds_constraint): Do not add to special var or non-pointer
+ field solutions.
+ (type_could_have_pointers): Split out from ...
+ (could_have_pointers): ... here. For arrays use the element type.
+ (create_variable_info_for): Initialize may_have_pointers.
+ (new_var_info): Likewise.
+ (handle_lhs_call): Make the HEAP variable unknown-sized.
+ (intra_create_variable_infos): Use a type with pointers for
+ PARM_NOALIAS, make it unknown-sized.
+
2009-02-18 H.J. Lu <hongjiu.lu@intel.com>
PR target/39224
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bd0c95c..036d402 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2009-02-19 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/39074
+ * gcc.dg/torture/pr39074.c: New testcase.
+ * gcc.dg/torture/pr39074-2.c: Likewise.
+ * gcc.dg/torture/pr39074-3.c: Likewise.
+
2009-02-18 H.J. Lu <hongjiu.lu@intel.com>
PR c++/39219
diff --git a/gcc/testsuite/gcc.dg/torture/pr39074-2.c b/gcc/testsuite/gcc.dg/torture/pr39074-2.c
new file mode 100644
index 0000000..89f7ebf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr39074-2.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-require-effective-target stdint_types } */
+/* { dg-options "-fdump-tree-alias" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+#include <stdint.h>
+
+int i;
+uintptr_t __attribute__((noinline,const)) bar(int ***p) { return (uintptr_t)p; }
+void __attribute__((noinline))
+foo(void)
+{
+ int *y;
+ int **a = &y, **x;
+ int ***p;
+ uintptr_t b;
+ b = bar(&a);
+ p = (int ***)b;
+ x = *p;
+ *x = &i; /* *ANYTHING = &i has to make sure that y points to i. */
+ *y = 0;
+}
+extern void abort (void);
+int main()
+{
+ i = 1;
+ foo ();
+ if (i != 0)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "y.._., name memory tag: NMT..., is dereferenced, points-to vars: { i }" "alias" } } */
+/* { dg-final { cleanup-tree-dump "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr39074-3.c b/gcc/testsuite/gcc.dg/torture/pr39074-3.c
new file mode 100644
index 0000000..7c76048
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr39074-3.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-require-effective-target stdint_types } */
+
+#include <stdint.h>
+
+uintptr_t __attribute__((noinline,const)) bar(int ***p) { return (uintptr_t)p; }
+extern void abort (void);
+int main()
+{
+ int i, j;
+ int *y = &j;
+ int **a = &y, **x;
+ int ***p;
+ uintptr_t b;
+ b = bar(&a);
+ p = (int ***)b;
+ x = *p;
+ *x = &i;
+ i = 1;
+ *y = 0;
+ if (i != 0)
+ abort ();
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/torture/pr39074.c b/gcc/testsuite/gcc.dg/torture/pr39074.c
new file mode 100644
index 0000000..cc37c8e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr39074.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-fdump-tree-alias" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+int i;
+void __attribute__((noinline))
+foo(long b, long q)
+{
+ int *y;
+ int **a = &y, **x;
+ int ***p;
+ if (b)
+ p = (int ***)q;
+ else
+ p = &a;
+ x = *p;
+ *x = &i; /* *ANYTHING = &i has to make sure that y points to i. */
+ *y = 0;
+}
+extern void abort (void);
+int main()
+{
+ i = 1;
+ foo (0, 0);
+ if (i != 0)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "y.._., name memory tag: NMT..., is dereferenced, points-to vars: { i }" "alias" } } */
+/* { dg-final { cleanup-tree-dump "alias" } } */
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 8f88796..9de341b 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -230,6 +230,9 @@ struct variable_info
variable. This is used for C++ placement new. */
unsigned int no_tbaa_pruning : 1;
+ /* True if this field may contain pointers. */
+ unsigned int may_have_pointers : 1;
+
/* Variable id this was collapsed to due to type unsafety. Zero if
this variable was not collapsed. This should be unused completely
after build_succ_graph, or something is broken. */
@@ -297,7 +300,8 @@ get_varinfo_fc (unsigned int n)
/* Static IDs for the special variables. */
enum { nothing_id = 0, anything_id = 1, readonly_id = 2,
- escaped_id = 3, nonlocal_id = 4, callused_id = 5, integer_id = 6 };
+ escaped_id = 3, nonlocal_id = 4, callused_id = 5,
+ storedanything_id = 6, integer_id = 7 };
/* Variable that represents the unknown pointer. */
static varinfo_t var_anything;
@@ -323,6 +327,10 @@ static tree nonlocal_tree;
static varinfo_t var_callused;
static tree callused_tree;
+/* Variable that represents variables that are stored to anything. */
+static varinfo_t var_storedanything;
+static tree storedanything_tree;
+
/* Variable that represents integers. This is used for when people do things
like &0->a.b. */
static varinfo_t var_integer;
@@ -377,6 +385,7 @@ new_var_info (tree t, unsigned int id, const char *name)
ret->is_special_var = false;
ret->is_unknown_size_var = false;
ret->is_full_var = false;
+ ret->may_have_pointers = true;
var = t;
if (TREE_CODE (var) == SSA_NAME)
var = SSA_NAME_VAR (var);
@@ -1182,7 +1191,7 @@ build_pred_graph (void)
static void
build_succ_graph (void)
{
- int i;
+ unsigned i, t;
constraint_t c;
for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
@@ -1223,6 +1232,14 @@ build_succ_graph (void)
add_graph_edge (graph, lhsvar, rhsvar);
}
}
+
+ /* Add edges from STOREDANYTHING to all non-direct nodes. */
+ t = find (storedanything_id);
+ for (i = integer_id + 1; i < FIRST_REF_NODE; ++i)
+ {
+ if (!TEST_BIT (graph->direct_nodes, i))
+ add_graph_edge (graph, find (i), t);
+ }
}
@@ -1608,35 +1625,33 @@ do_ds_constraint (constraint_t c, bitmap delta)
unsigned int j;
bitmap_iterator bi;
- if (bitmap_bit_p (sol, anything_id))
- {
- EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
- {
- varinfo_t jvi = get_varinfo (j);
- unsigned int t;
- unsigned int loff = c->lhs.offset;
- unsigned HOST_WIDE_INT fieldoffset = jvi->offset + loff;
- varinfo_t v;
-
- v = get_varinfo (j);
- if (!v->is_full_var)
- {
- v = first_vi_for_offset (v, fieldoffset);
- /* If the access is outside of the variable we can ignore it. */
- if (!v)
- continue;
- }
- t = find (v->id);
-
- if (bitmap_set_bit (get_varinfo (t)->solution, anything_id)
- && !TEST_BIT (changed, t))
- {
- SET_BIT (changed, t);
- changed_count++;
- }
- }
- return;
- }
+ /* Our IL does not allow this. */
+ gcc_assert (c->rhs.offset == 0);
+
+ /* If the solution of y contains ANYTHING simply use the ANYTHING
+ solution. This avoids needlessly increasing the points-to sets. */
+ if (bitmap_bit_p (sol, anything_id))
+ sol = get_varinfo (find (anything_id))->solution;
+
+ /* If the solution for x contains ANYTHING we have to merge the
+ solution of y into all pointer variables which we do via
+ STOREDANYTHING. */
+ if (bitmap_bit_p (delta, anything_id))
+ {
+ unsigned t = find (storedanything_id);
+ if (add_graph_edge (graph, t, rhs))
+ {
+ if (bitmap_ior_into (get_varinfo (t)->solution, sol))
+ {
+ if (!TEST_BIT (changed, t))
+ {
+ SET_BIT (changed, t);
+ changed_count++;
+ }
+ }
+ }
+ return;
+ }
/* For each member j of delta (Sol(x)), add an edge from y to j and
union Sol(y) into Sol(j) */
@@ -1648,26 +1663,27 @@ do_ds_constraint (constraint_t c, bitmap delta)
varinfo_t v;
unsigned int t;
unsigned HOST_WIDE_INT fieldoffset = get_varinfo (j)->offset + loff;
- bitmap tmp;
v = first_vi_for_offset (get_varinfo (j), fieldoffset);
/* If the access is outside of the variable we can ignore it. */
if (!v)
continue;
- t = find (v->id);
- tmp = get_varinfo (t)->solution;
- if (add_graph_edge (graph, t, rhs))
+ if (v->may_have_pointers)
{
- if (bitmap_ior_into (get_varinfo (t)->solution, sol))
+ t = find (v->id);
+ if (add_graph_edge (graph, t, rhs))
{
- if (t == rhs)
- sol = get_varinfo (rhs)->solution;
- if (!TEST_BIT (changed, t))
- {
- SET_BIT (changed, t);
- changed_count++;
- }
+ if (bitmap_ior_into (get_varinfo (t)->solution, sol))
+ {
+ if (t == rhs)
+ sol = get_varinfo (rhs)->solution;
+ if (!TEST_BIT (changed, t))
+ {
+ SET_BIT (changed, t);
+ changed_count++;
+ }
+ }
}
}
}
@@ -2740,19 +2756,27 @@ process_constraint (constraint_t t)
}
}
+/* Return true if T is a type that could contain pointers. */
+
+static bool
+type_could_have_pointers (tree type)
+{
+ if (POINTER_TYPE_P (type))
+ return true;
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ return type_could_have_pointers (TREE_TYPE (type));
+
+ return AGGREGATE_TYPE_P (type);
+}
+
/* Return true if T is a variable of a type that could contain
pointers. */
static bool
could_have_pointers (tree t)
{
- tree type = TREE_TYPE (t);
-
- if (POINTER_TYPE_P (type)
- || AGGREGATE_TYPE_P (type))
- return true;
-
- return false;
+ return type_could_have_pointers (TREE_TYPE (t));
}
/* Return the position, in bits, of FIELD_DECL from the beginning of its
@@ -3516,6 +3540,9 @@ handle_lhs_call (tree lhs, int flags)
vi = get_varinfo (rhsc.var);
vi->is_artificial_var = 1;
vi->is_heap_var = 1;
+ vi->is_unknown_size_var = true;
+ vi->fullsize = ~0;
+ vi->size = ~0;
rhsc.type = ADDRESSOF;
rhsc.offset = 0;
}
@@ -4356,6 +4383,7 @@ create_variable_info_for (tree decl, const char *name)
vi = new_var_info (decl, index, name);
vi->decl = decl;
vi->offset = 0;
+ vi->may_have_pointers = could_have_pointers (decl);
if (!declsize
|| !host_integerp (declsize, 1))
{
@@ -4372,7 +4400,7 @@ create_variable_info_for (tree decl, const char *name)
insert_vi_for_tree (vi->decl, vi);
VEC_safe_push (varinfo_t, heap, varmap, vi);
if (is_global && (!flag_whole_program || !in_ipa_mode)
- && could_have_pointers (decl))
+ && vi->may_have_pointers)
{
if (var_ann (decl)
&& var_ann (decl)->noalias_state == NO_ALIAS_ANYTHING)
@@ -4433,6 +4461,7 @@ create_variable_info_for (tree decl, const char *name)
vi->size = fo->size;
vi->offset = fo->offset;
+ vi->may_have_pointers = fo->may_have_pointers;
for (i = VEC_length (fieldoff_s, fieldstack) - 1;
i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo);
i--)
@@ -4454,10 +4483,11 @@ create_variable_info_for (tree decl, const char *name)
newvi->offset = fo->offset;
newvi->size = fo->size;
newvi->fullsize = vi->fullsize;
+ newvi->may_have_pointers = fo->may_have_pointers;
insert_into_field_list (vi, newvi);
VEC_safe_push (varinfo_t, heap, varmap, newvi);
if (is_global && (!flag_whole_program || !in_ipa_mode)
- && fo->may_have_pointers)
+ && newvi->may_have_pointers)
make_constraint_from (newvi, escaped_id);
stats.total_vars++;
@@ -4541,7 +4571,7 @@ intra_create_variable_infos (void)
if (heapvar == NULL_TREE)
{
var_ann_t ann;
- heapvar = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (t)),
+ heapvar = create_tmp_var_raw (ptr_type_node,
"PARM_NOALIAS");
DECL_EXTERNAL (heapvar) = 1;
if (gimple_referenced_vars (cfun))
@@ -4564,6 +4594,9 @@ intra_create_variable_infos (void)
vi = get_vi_for_tree (heapvar);
vi->is_artificial_var = 1;
vi->is_heap_var = 1;
+ vi->is_unknown_size_var = true;
+ vi->fullsize = ~0;
+ vi->size = ~0;
rhs.var = vi->id;
rhs.type = ADDRESSOF;
rhs.offset = 0;
@@ -5239,6 +5272,19 @@ init_base_vars (void)
rhs.offset = 0;
process_constraint (new_constraint (lhs, rhs));
+ /* Create the STOREDANYTHING variable, used to represent the set of
+ variables stored to *ANYTHING. */
+ storedanything_tree = create_tmp_var_raw (ptr_type_node, "STOREDANYTHING");
+ var_storedanything = new_var_info (storedanything_tree, storedanything_id,
+ "STOREDANYTHING");
+ insert_vi_for_tree (storedanything_tree, var_storedanything);
+ var_storedanything->is_artificial_var = 1;
+ var_storedanything->offset = 0;
+ var_storedanything->size = ~0;
+ var_storedanything->fullsize = ~0;
+ var_storedanything->is_special_var = 0;
+ VEC_safe_push (varinfo_t, heap, varmap, var_storedanything);
+
/* Create the INTEGER variable, used to represent that a variable points
to an INTEGER. */
integer_tree = create_tmp_var_raw (void_type_node, "INTEGER");
@@ -5537,9 +5583,9 @@ compute_points_to_sets (void)
fprintf (dump_file, "Rewriting constraints and unifying "
"variables\n");
rewrite_constraints (graph, si);
- free_var_substitution_info (si);
build_succ_graph ();
+ free_var_substitution_info (si);
if (dump_file && (dump_flags & TDF_GRAPH))
dump_constraint_graph (dump_file);
@@ -5698,9 +5744,9 @@ ipa_pta_execute (void)
build_pred_graph ();
si = perform_var_substitution (graph);
rewrite_constraints (graph, si);
- free_var_substitution_info (si);
build_succ_graph ();
+ free_var_substitution_info (si);
move_complex_constraints (graph);
unite_pointer_equivalences (graph);
find_indirect_cycles (graph);