summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-structalias.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2009-02-23 07:00:35 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2009-02-23 07:00:35 +0000
commit813491d0029a21981f65785cacf0f4229315df5f (patch)
tree038dd7e767cab757a10ca9400a1952ae841999ce /gcc/tree-ssa-structalias.c
parentf4618e1c2c649db169baee64b4791fe40205ca7c (diff)
downloadgcc-813491d0029a21981f65785cacf0f4229315df5f.tar.gz
2009-02-23 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk r144379 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@144380 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-structalias.c')
-rw-r--r--gcc/tree-ssa-structalias.c158
1 files changed, 102 insertions, 56 deletions
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 8f887969427..07fd9ed2a85 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -1,5 +1,5 @@
/* Tree based points-to analysis
- Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Daniel Berlin <dberlin@dberlin.org>
This file is part of GCC.
@@ -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);