aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-structalias.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-structalias.c')
-rw-r--r--gcc/tree-ssa-structalias.c101
1 files changed, 63 insertions, 38 deletions
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index d8dbf05..481b9fe 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -2063,7 +2063,24 @@ condense_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
si->scc_stack.safe_push (n);
}
-/* Label pointer equivalences. */
+/* Label pointer equivalences.
+
+ This performs a value numbering of the constraint graph to
+ discover which variables will always have the same points-to sets
+ under the current set of constraints.
+
+ The way it value numbers is to store the set of points-to bits
+ generated by the constraints and graph edges. This is just used as a
+ hash and equality comparison. The *actual set of points-to bits* is
+ completely irrelevant, in that we don't care about being able to
+ extract them later.
+
+ The equality values (currently bitmaps) just have to satisfy a few
+ constraints, the main ones being:
+ 1. The combining operation must be order independent.
+ 2. The end result of a given set of operations must be unique iff the
+ combination of input values is unique
+ 3. Hashable. */
static void
label_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
@@ -3979,8 +3996,8 @@ handle_lhs_call (gimple stmt, tree lhs, int flags, vec<ce_s> rhsc,
struct constraint_expr tmpc;
rhsc.create (0);
vi = make_heapvar ("HEAP");
- /* We delay marking allocated storage global until we know if
- it escapes. */
+ /* We marking allocated storage local, we deal with it becoming
+ global by escaping and setting of vars_contains_escaped_heap. */
DECL_EXTERNAL (vi->decl) = 0;
vi->is_global_var = 0;
/* If this is not a real malloc call assume the memory was
@@ -5983,6 +6000,9 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
{
unsigned int i;
bitmap_iterator bi;
+ varinfo_t escaped_vi = get_varinfo (find (escaped_id));
+ bool everything_escaped
+ = escaped_vi->solution && bitmap_bit_p (escaped_vi->solution, anything_id);
EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
{
@@ -5993,6 +6013,14 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
if (vi->is_artificial_var && !vi->is_heap_var)
continue;
+ if (everything_escaped
+ || (escaped_vi->solution
+ && bitmap_bit_p (escaped_vi->solution, i)))
+ {
+ pt->vars_contains_escaped = true;
+ pt->vars_contains_escaped_heap = vi->is_heap_var;
+ }
+
if (TREE_CODE (vi->decl) == VAR_DECL
|| TREE_CODE (vi->decl) == PARM_DECL
|| TREE_CODE (vi->decl) == RESULT_DECL)
@@ -6007,7 +6035,7 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
set contains global variables. */
bitmap_set_bit (into, DECL_PT_UID (vi->decl));
if (vi->is_global_var)
- pt->vars_contains_global = true;
+ pt->vars_contains_nonlocal = true;
}
}
}
@@ -6164,11 +6192,15 @@ pt_solution_reset (struct pt_solution *pt)
it contains restrict tag variables. */
void
-pt_solution_set (struct pt_solution *pt, bitmap vars, bool vars_contains_global)
+pt_solution_set (struct pt_solution *pt, bitmap vars,
+ bool vars_contains_nonlocal)
{
memset (pt, 0, sizeof (struct pt_solution));
pt->vars = vars;
- pt->vars_contains_global = vars_contains_global;
+ pt->vars_contains_nonlocal = vars_contains_nonlocal;
+ pt->vars_contains_escaped
+ = (cfun->gimple_df->escaped.anything
+ || bitmap_intersect_p (cfun->gimple_df->escaped.vars, vars));
}
/* Set the points-to solution *PT to point only to the variable VAR. */
@@ -6179,7 +6211,10 @@ pt_solution_set_var (struct pt_solution *pt, tree var)
memset (pt, 0, sizeof (struct pt_solution));
pt->vars = BITMAP_GGC_ALLOC ();
bitmap_set_bit (pt->vars, DECL_PT_UID (var));
- pt->vars_contains_global = is_global_var (var);
+ pt->vars_contains_nonlocal = is_global_var (var);
+ pt->vars_contains_escaped
+ = (cfun->gimple_df->escaped.anything
+ || bitmap_bit_p (cfun->gimple_df->escaped.vars, DECL_PT_UID (var)));
}
/* Computes the union of the points-to solutions *DEST and *SRC and
@@ -6202,7 +6237,9 @@ pt_solution_ior_into (struct pt_solution *dest, struct pt_solution *src)
dest->escaped |= src->escaped;
dest->ipa_escaped |= src->ipa_escaped;
dest->null |= src->null;
- dest->vars_contains_global |= src->vars_contains_global;
+ dest->vars_contains_nonlocal |= src->vars_contains_nonlocal;
+ dest->vars_contains_escaped |= src->vars_contains_escaped;
+ dest->vars_contains_escaped_heap |= src->vars_contains_escaped_heap;
if (!src->vars)
return;
@@ -6259,9 +6296,14 @@ pt_solution_includes_global (struct pt_solution *pt)
{
if (pt->anything
|| pt->nonlocal
- || pt->vars_contains_global)
+ || pt->vars_contains_nonlocal
+ /* The following is a hack to make the malloc escape hack work.
+ In reality we'd need different sets for escaped-through-return
+ and escaped-to-callees and passes would need to be updated. */
+ || pt->vars_contains_escaped_heap)
return true;
+ /* 'escaped' is also a placeholder so we have to look into it. */
if (pt->escaped)
return pt_solution_includes_global (&cfun->gimple_df->escaped);
@@ -6331,28 +6373,19 @@ pt_solutions_intersect_1 (struct pt_solution *pt1, struct pt_solution *pt2)
any global memory they alias. */
if ((pt1->nonlocal
&& (pt2->nonlocal
- || pt2->vars_contains_global))
+ || pt2->vars_contains_nonlocal))
|| (pt2->nonlocal
- && pt1->vars_contains_global))
+ && pt1->vars_contains_nonlocal))
return true;
- /* Check the escaped solution if required. */
- if ((pt1->escaped || pt2->escaped)
- && !pt_solution_empty_p (&cfun->gimple_df->escaped))
- {
- /* If both point to escaped memory and that solution
- is not empty they alias. */
- if (pt1->escaped && pt2->escaped)
- return true;
-
- /* If either points to escaped memory see if the escaped solution
- intersects with the other. */
- if ((pt1->escaped
- && pt_solutions_intersect_1 (&cfun->gimple_df->escaped, pt2))
- || (pt2->escaped
- && pt_solutions_intersect_1 (&cfun->gimple_df->escaped, pt1)))
- return true;
- }
+ /* If either points to all escaped memory and the other points to
+ any escaped memory they alias. */
+ if ((pt1->escaped
+ && (pt2->escaped
+ || pt2->vars_contains_escaped))
+ || (pt2->escaped
+ && pt1->vars_contains_escaped))
+ return true;
/* Check the escaped solution if required.
??? Do we need to check the local against the IPA escaped sets? */
@@ -6800,14 +6833,6 @@ compute_points_to_sets (void)
points-to solution queries. */
cfun->gimple_df->escaped.escaped = 0;
- /* Mark escaped HEAP variables as global. */
- FOR_EACH_VEC_ELT (varmap, i, vi)
- if (vi
- && vi->is_heap_var
- && !vi->is_global_var)
- DECL_EXTERNAL (vi->decl) = vi->is_global_var
- = pt_solution_includes (&cfun->gimple_df->escaped, vi->decl);
-
/* Compute the points-to sets for pointer SSA_NAMEs. */
for (i = 0; i < num_ssa_names; ++i)
{
@@ -7054,7 +7079,7 @@ gate_ipa_pta (void)
/* IPA PTA solutions for ESCAPED. */
struct pt_solution ipa_escaped_pt
- = { true, false, false, false, false, false, NULL };
+ = { true, false, false, false, false, false, false, false, NULL };
/* Associate node with varinfo DATA. Worker for
cgraph_for_node_and_aliases. */
@@ -7412,7 +7437,7 @@ const pass_data pass_data_ipa_pta =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_update_ssa, /* todo_flags_finish */
+ 0, /* todo_flags_finish */
};
class pass_ipa_pta : public simple_ipa_opt_pass