diff options
author | Richard Biener <rguenther@suse.de> | 2019-06-06 07:25:19 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2019-06-06 07:25:19 +0000 |
commit | ed315c041f48f491d6310fe83810bb93cc3e5d17 (patch) | |
tree | c39d72532d4b3cb1d9f09502f7a8087d40d9893a /gcc/tree-ssa-structalias.c | |
parent | c45c8424de8773ee4305a7932fb2a3ee878ea56a (diff) | |
download | gcc-ed315c041f48f491d6310fe83810bb93cc3e5d17.zip gcc-ed315c041f48f491d6310fe83810bb93cc3e5d17.tar.gz gcc-ed315c041f48f491d6310fe83810bb93cc3e5d17.tar.bz2 |
tree-ssa-structalias.c: Include tree-cfg.h.
2019-06-06 Richard Biener <rguenther@suse.de>
* tree-ssa-structalias.c: Include tree-cfg.h.
(make_heapvar): Do not make heap vars artificial.
(find_func_aliases_for_builtin_call): Handle stack allocation
functions.
(find_func_aliases): Delay processing of simple enough returns
in non-IPA mode.
(set_uids_in_ptset): Adjust.
(find_what_var_points_to): Likewise.
(solve_constraints): Do not dump points-to sets here.
(compute_points_to_sets): Post-process return statements,
amending the escaped solution. Dump points-to sets afterwards.
(ipa_pta_execute): Dump points-to sets.
* gcc.dg/tree-ssa/alias-37.c: New testcase.
* gcc.dg/torture/20190604-1.c: Likewise.
* gcc.dg/tree-ssa/pta-callused.c: Adjust.
From-SVN: r271989
Diffstat (limited to 'gcc/tree-ssa-structalias.c')
-rw-r--r-- | gcc/tree-ssa-structalias.c | 115 |
1 files changed, 104 insertions, 11 deletions
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index d8ff2ce6..0779151 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -43,6 +43,7 @@ #include "stringpool.h" #include "attribs.h" #include "tree-ssa.h" +#include "tree-cfg.h" /* The idea behind this analyzer is to generate set constraints from the program, then solve the resulting constraints in order to generate the @@ -3854,7 +3855,6 @@ make_heapvar (const char *name, bool add_id) DECL_EXTERNAL (heapvar) = 1; vi = new_var_info (heapvar, name, add_id); - vi->is_artificial_var = true; vi->is_heap_var = true; vi->is_unknown_size_var = true; vi->offset = 0; @@ -4409,6 +4409,32 @@ find_func_aliases_for_builtin_call (struct function *fn, gcall *t) process_constraint (new_constraint (*lhsp, ac)); return true; } + case BUILT_IN_STACK_SAVE: + case BUILT_IN_STACK_RESTORE: + /* Nothing interesting happens. */ + return true; + case BUILT_IN_ALLOCA: + case BUILT_IN_ALLOCA_WITH_ALIGN: + case BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX: + { + tree ptr = gimple_call_lhs (t); + if (ptr == NULL_TREE) + return true; + get_constraint_for (ptr, &lhsc); + varinfo_t vi = make_heapvar ("HEAP", true); + /* Alloca storage is never global. To exempt it from escaped + handling make it a non-heap var. */ + DECL_EXTERNAL (vi->decl) = 0; + vi->is_global_var = 0; + vi->is_heap_var = 0; + struct constraint_expr tmpc; + tmpc.var = vi->id; + tmpc.offset = 0; + tmpc.type = ADDRESSOF; + rhsc.safe_push (tmpc); + process_all_all_constraints (lhsc, rhsc); + return true; + } case BUILT_IN_POSIX_MEMALIGN: { tree ptrptr = gimple_call_arg (t, 0); @@ -4976,7 +5002,12 @@ find_func_aliases (struct function *fn, gimple *origt) greturn *return_stmt = as_a <greturn *> (t); fi = NULL; if (!in_ipa_mode - || !(fi = get_vi_for_tree (fn->decl))) + && SSA_VAR_P (gimple_return_retval (return_stmt))) + { + /* We handle simple returns by post-processing the solutions. */ + ; + } + if (!(fi = get_vi_for_tree (fn->decl))) make_escape_constraint (gimple_return_retval (return_stmt)); else if (in_ipa_mode) { @@ -6422,9 +6453,7 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt, { varinfo_t vi = get_varinfo (i); - /* The only artificial variables that are allowed in a may-alias - set are heap variables. */ - if (vi->is_artificial_var && !vi->is_heap_var) + if (vi->is_artificial_var) continue; if (everything_escaped @@ -6544,9 +6573,6 @@ find_what_var_points_to (tree fndecl, varinfo_t orig_vi) } else if (vi->id == nonlocal_id) pt->nonlocal = 1; - else if (vi->is_heap_var) - /* We represent heapvars in the points-to set properly. */ - ; else if (vi->id == string_id) /* Nobody cares - STRING_CSTs are read-only entities. */ ; @@ -7254,9 +7280,6 @@ solve_constraints (void) dump_constraint_graph (dump_file); fprintf (dump_file, "\n\n"); } - - if (dump_file) - dump_sa_points_to_info (dump_file); } /* Create points-to sets for the current function. See the comments @@ -7304,6 +7327,73 @@ compute_points_to_sets (void) /* From the constraints compute the points-to sets. */ solve_constraints (); + /* Post-process solutions for escapes through returns. */ + edge_iterator ei; + edge e; + FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) + if (greturn *ret = safe_dyn_cast <greturn *> (last_stmt (e->src))) + { + tree val = gimple_return_retval (ret); + /* ??? Easy to handle simple indirections with some work. + Arbitrary references like foo.bar.baz are more difficult + (but conservatively easy enough with just looking at the base). + Mind to fixup find_func_aliases as well. */ + if (!val || !SSA_VAR_P (val)) + continue; + /* returns happen last in non-IPA so they only influence + the ESCAPED solution and we can filter local variables. */ + varinfo_t escaped_vi = get_varinfo (find (escaped_id)); + varinfo_t vi = lookup_vi_for_tree (val); + bitmap delta = BITMAP_ALLOC (&pta_obstack); + bitmap_iterator bi; + unsigned i; + for (; vi; vi = vi_next (vi)) + { + varinfo_t part_vi = get_varinfo (find (vi->id)); + EXECUTE_IF_AND_COMPL_IN_BITMAP (part_vi->solution, + escaped_vi->solution, 0, i, bi) + { + varinfo_t pointed_to_vi = get_varinfo (i); + if (pointed_to_vi->is_global_var + /* We delay marking of heap memory as global. */ + || pointed_to_vi->is_heap_var) + bitmap_set_bit (delta, i); + } + } + + /* Now compute the transitive closure. */ + bitmap_ior_into (escaped_vi->solution, delta); + bitmap new_delta = BITMAP_ALLOC (&pta_obstack); + while (!bitmap_empty_p (delta)) + { + EXECUTE_IF_SET_IN_BITMAP (delta, 0, i, bi) + { + varinfo_t pointed_to_vi = get_varinfo (i); + pointed_to_vi = get_varinfo (find (pointed_to_vi->id)); + unsigned j; + bitmap_iterator bi2; + EXECUTE_IF_AND_COMPL_IN_BITMAP (pointed_to_vi->solution, + escaped_vi->solution, + 0, j, bi2) + { + varinfo_t pointed_to_vi2 = get_varinfo (j); + if (pointed_to_vi2->is_global_var + /* We delay marking of heap memory as global. */ + || pointed_to_vi2->is_heap_var) + bitmap_set_bit (new_delta, j); + } + } + bitmap_ior_into (escaped_vi->solution, new_delta); + bitmap_clear (delta); + std::swap (delta, new_delta); + } + BITMAP_FREE (delta); + BITMAP_FREE (new_delta); + } + + if (dump_file) + dump_sa_points_to_info (dump_file); + /* Compute the points-to set for ESCAPED used for call-clobber analysis. */ cfun->gimple_df->escaped = find_what_var_points_to (cfun->decl, get_varinfo (escaped_id)); @@ -8109,6 +8199,9 @@ ipa_pta_execute (void) /* From the constraints compute the points-to sets. */ solve_constraints (); + if (dump_file) + dump_sa_points_to_info (dump_file); + /* Now post-process solutions to handle locals from different runtime instantiations coming in through recursive invocations. */ unsigned shadow_var_cnt = 0; |