diff options
Diffstat (limited to 'gcc/tree-ssa-structalias.c')
-rw-r--r-- | gcc/tree-ssa-structalias.c | 101 |
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 |