diff options
author | Richard Biener <rguenther@suse.de> | 2023-11-27 10:20:02 +0100 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2023-11-27 15:35:12 +0100 |
commit | f7884f7673444b8a2c10ea0981d480f2e82dd16a (patch) | |
tree | 41e4be377fb4f4609c5f85969b462ef15e167be1 /gcc | |
parent | 061a82fa2b751b42d0d8ddfcd45367c848d3ee64 (diff) | |
download | gcc-f7884f7673444b8a2c10ea0981d480f2e82dd16a.zip gcc-f7884f7673444b8a2c10ea0981d480f2e82dd16a.tar.gz gcc-f7884f7673444b8a2c10ea0981d480f2e82dd16a.tar.bz2 |
tree-optimization/112653 - PTA and return
The following separates the escape solution for return stmts not
only during points-to solving but also for later querying. This
requires adjusting the points-to-global tests to include escapes
through returns. Technically the patch replaces the existing
post-processing which computes the transitive closure of the
returned value solution by a proper artificial variable with
transitive closure constraints. Instead of adding the solution
to escaped we track it separately.
PR tree-optimization/112653
* gimple-ssa.h (gimple_df): Add escaped_return solution.
* tree-ssa.cc (init_tree_ssa): Reset it.
(delete_tree_ssa): Likewise.
* tree-ssa-structalias.cc (escaped_return_id): New.
(find_func_aliases): Handle non-IPA return stmts by
adding to ESCAPED_RETURN.
(set_uids_in_ptset): Adjust HEAP escaping to also cover
escapes through return.
(init_base_vars): Initialize ESCAPED_RETURN.
(compute_points_to_sets): Replace ESCAPED post-processing
with recording the ESCAPED_RETURN solution.
* tree-ssa-alias.cc (ref_may_alias_global_p_1): Check
the ESCAPED_RETUNR solution.
(dump_alias_info): Dump it.
* cfgexpand.cc (update_alias_info_with_stack_vars): Update it.
* ipa-icf.cc (sem_item_optimizer::fixup_points_to_sets):
Likewise.
* tree-inline.cc (expand_call_inline): Reset it.
* tree-parloops.cc (parallelize_loops): Likewise.
* tree-sra.cc (maybe_add_sra_candidate): Check it.
* gcc.dg/tree-ssa/pta-return-1.c: New testcase.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cfgexpand.cc | 3 | ||||
-rw-r--r-- | gcc/gimple-ssa.h | 4 | ||||
-rw-r--r-- | gcc/ipa-icf.cc | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pta-return-1.c | 16 | ||||
-rw-r--r-- | gcc/tree-inline.cc | 5 | ||||
-rw-r--r-- | gcc/tree-parloops.cc | 5 | ||||
-rw-r--r-- | gcc/tree-sra.cc | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.cc | 6 | ||||
-rw-r--r-- | gcc/tree-ssa-structalias.cc | 124 | ||||
-rw-r--r-- | gcc/tree-ssa.cc | 2 |
10 files changed, 85 insertions, 83 deletions
diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc index 4262703..3fee256 100644 --- a/gcc/cfgexpand.cc +++ b/gcc/cfgexpand.cc @@ -859,7 +859,8 @@ update_alias_info_with_stack_vars (void) add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped, decls_to_partitions, &visited, temp); - + add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped_return, + decls_to_partitions, &visited, temp); delete decls_to_partitions; BITMAP_FREE (temp); } diff --git a/gcc/gimple-ssa.h b/gcc/gimple-ssa.h index 604af8b..0d9fbd3 100644 --- a/gcc/gimple-ssa.h +++ b/gcc/gimple-ssa.h @@ -76,8 +76,10 @@ struct GTY(()) gimple_df { /* Artificial variable used for the virtual operand FUD chain. */ tree vop; - /* The PTA solution for the ESCAPED artificial variable. */ + /* The PTA solution for the ESCAPED and ESCAPED_RETURN artificial + variables. */ struct pt_solution escaped; + struct pt_solution escaped_return; /* A map of decls to artificial ssa-names that point to the partition of the decl. */ diff --git a/gcc/ipa-icf.cc b/gcc/ipa-icf.cc index bbdfd44..c72c9d5 100644 --- a/gcc/ipa-icf.cc +++ b/gcc/ipa-icf.cc @@ -3506,6 +3506,7 @@ sem_item_optimizer::fixup_points_to_sets (void) && SSA_NAME_PTR_INFO (name)) fixup_pt_set (&SSA_NAME_PTR_INFO (name)->pt); fixup_pt_set (&fn->gimple_df->escaped); + fixup_pt_set (&fn->gimple_df->escaped_return); /* The above gets us to 99% I guess, at least catching the address compares. Below also gets us aliasing correct diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-return-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-return-1.c new file mode 100644 index 0000000..9c2416e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pta-return-1.c @@ -0,0 +1,16 @@ +/* PR112653 */ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +char *test; +char * +copy_test () +{ + char *test2 = __builtin_malloc (1000); + __builtin_memmove (test2, test, 1000); + return test2; +} + +/* We should be able to turn the memmove into memcpy by means of alias + analysis. */ +/* { dg-final { scan-tree-dump "memcpy" "optimized" } } */ diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 0b14118..5984716 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -5147,7 +5147,10 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id, /* Reset the escaped solution. */ if (cfun->gimple_df) - pt_solution_reset (&cfun->gimple_df->escaped); + { + pt_solution_reset (&cfun->gimple_df->escaped); + pt_solution_reset (&cfun->gimple_df->escaped_return); + } /* Add new automatic variables to IFN_GOMP_SIMT_ENTER arguments. */ if (id->dst_simt_vars && id->dst_simt_vars->length () > 0) diff --git a/gcc/tree-parloops.cc b/gcc/tree-parloops.cc index 80f3dd6..50e61f0 100644 --- a/gcc/tree-parloops.cc +++ b/gcc/tree-parloops.cc @@ -4147,7 +4147,10 @@ parallelize_loops (bool oacc_kernels_p) which local variables will escape. Reset the points-to solution for ESCAPED. */ if (changed) - pt_solution_reset (&cfun->gimple_df->escaped); + { + pt_solution_reset (&cfun->gimple_df->escaped); + pt_solution_reset (&cfun->gimple_df->escaped_return); + } return changed; } diff --git a/gcc/tree-sra.cc b/gcc/tree-sra.cc index 3a0d5267..0349410 100644 --- a/gcc/tree-sra.cc +++ b/gcc/tree-sra.cc @@ -2026,7 +2026,7 @@ maybe_add_sra_candidate (tree var) /* There are cases where non-addressable variables fail the pt_solutions_check test, e.g in gcc.dg/uninit-40.c. */ || (TREE_ADDRESSABLE (var) - && pt_solution_includes (&cfun->gimple_df->escaped, var)) + && pt_solution_includes (&cfun->gimple_df->escaped_return, var)) || (TREE_CODE (var) == RESULT_DECL && !DECL_BY_REFERENCE (var) && aggregate_value_p (var, current_function_decl))) diff --git a/gcc/tree-ssa-alias.cc b/gcc/tree-ssa-alias.cc index 373940b..a708f7e 100644 --- a/gcc/tree-ssa-alias.cc +++ b/gcc/tree-ssa-alias.cc @@ -496,7 +496,8 @@ ref_may_alias_global_p_1 (tree base, bool escaped_local_p) if (DECL_P (base)) return (is_global_var (base) || (escaped_local_p - && pt_solution_includes (&cfun->gimple_df->escaped, base))); + && pt_solution_includes (&cfun->gimple_df->escaped_return, + base))); else if (TREE_CODE (base) == MEM_REF || TREE_CODE (base) == TARGET_MEM_REF) return ptr_deref_may_alias_global_p (TREE_OPERAND (base, 0), @@ -579,6 +580,9 @@ dump_alias_info (FILE *file) fprintf (file, "\nESCAPED"); dump_points_to_solution (file, &cfun->gimple_df->escaped); + fprintf (file, "\nESCAPED_RETURN"); + dump_points_to_solution (file, &cfun->gimple_df->escaped_return); + fprintf (file, "\n\nFlow-insensitive points-to information\n\n"); FOR_EACH_SSA_NAME (i, ptr, cfun) diff --git a/gcc/tree-ssa-structalias.cc b/gcc/tree-ssa-structalias.cc index ee9313c..6db10d5 100644 --- a/gcc/tree-ssa-structalias.cc +++ b/gcc/tree-ssa-structalias.cc @@ -365,8 +365,8 @@ vi_next (varinfo_t vi) /* Static IDs for the special variables. Variable ID zero is unused and used as terminator for the sub-variable chain. */ enum { nothing_id = 1, anything_id = 2, string_id = 3, - escaped_id = 4, nonlocal_id = 5, - storedanything_id = 6, integer_id = 7 }; + escaped_id = 4, nonlocal_id = 5, escaped_return_id = 6, + storedanything_id = 7, integer_id = 8 }; /* Return a new variable info structure consisting for a variable named NAME, and using constraint graph node NODE. Append it @@ -5221,23 +5221,18 @@ find_func_aliases (struct function *fn, gimple *origt) && gimple_return_retval (as_a <greturn *> (t)) != NULL_TREE) { greturn *return_stmt = as_a <greturn *> (t); - fi = NULL; - if (!in_ipa_mode - && 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) + tree retval = gimple_return_retval (return_stmt); + if (!in_ipa_mode) + make_constraint_to (escaped_return_id, retval); + else { struct constraint_expr lhs ; struct constraint_expr *rhsp; unsigned i; + fi = lookup_vi_for_tree (fn->decl); lhs = get_function_part_constraint (fi, fi_result); - get_constraint_for_rhs (gimple_return_retval (return_stmt), &rhsc); + get_constraint_for_rhs (retval, &rhsc); FOR_EACH_VEC_ELT (rhsc, i, rhsp) process_constraint (new_constraint (lhs, *rhsp)); } @@ -6665,6 +6660,7 @@ 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)); + varinfo_t escaped_return_vi = get_varinfo (find (escaped_return_id)); bool everything_escaped = escaped_vi->solution && bitmap_bit_p (escaped_vi->solution, anything_id); @@ -6682,6 +6678,9 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt, pt->vars_contains_escaped = true; pt->vars_contains_escaped_heap |= vi->is_heap_var; } + if (escaped_return_vi->solution + && bitmap_bit_p (escaped_return_vi->solution, i)) + pt->vars_contains_escaped_heap |= vi->is_heap_var; if (vi->is_restrict_var) pt->vars_contains_restrict = true; @@ -7196,6 +7195,7 @@ init_base_vars (void) varinfo_t var_string; varinfo_t var_escaped; varinfo_t var_nonlocal; + varinfo_t var_escaped_return; varinfo_t var_storedanything; varinfo_t var_integer; @@ -7271,6 +7271,16 @@ init_base_vars (void) var_nonlocal->fullsize = ~0; var_nonlocal->is_special_var = 1; + /* Create the ESCAPED_RETURN variable, used to represent the set of escaped + memory via a regular return stmt. */ + var_escaped_return = new_var_info (NULL_TREE, "ESCAPED_RETURN", false); + gcc_assert (var_escaped_return->id == escaped_return_id); + var_escaped_return->is_artificial_var = 1; + var_escaped_return->offset = 0; + var_escaped_return->size = ~0; + var_escaped_return->fullsize = ~0; + var_escaped_return->is_special_var = 0; + /* ESCAPED = *ESCAPED, because escaped is may-deref'd at calls, etc. */ lhs.type = SCALAR; lhs.var = escaped_id; @@ -7315,6 +7325,24 @@ init_base_vars (void) rhs.offset = 0; process_constraint (new_constraint (lhs, rhs)); + /* Transitively close ESCAPED_RETURN. + ESCAPED_RETURN = ESCAPED_RETURN + UNKNOWN_OFFSET + ESCAPED_RETURN = *ESCAPED_RETURN. */ + lhs.type = SCALAR; + lhs.var = escaped_return_id; + lhs.offset = 0; + rhs.type = SCALAR; + rhs.var = escaped_return_id; + rhs.offset = UNKNOWN_OFFSET; + process_constraint (new_constraint (lhs, rhs)); + lhs.type = SCALAR; + lhs.var = escaped_return_id; + lhs.offset = 0; + rhs.type = DEREF; + rhs.var = escaped_return_id; + rhs.offset = 0; + process_constraint (new_constraint (lhs, rhs)); + /* Create the STOREDANYTHING variable, used to represent the set of variables stored to *ANYTHING. */ var_storedanything = new_var_info (NULL_TREE, "STOREDANYTHING", false); @@ -7555,70 +7583,6 @@ 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 *> (*gsi_last_bb (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_flags & TDF_STATS)) dump_sa_stats (dump_file); @@ -7634,6 +7598,12 @@ compute_points_to_sets (void) points-to solution queries. */ cfun->gimple_df->escaped.escaped = 0; + /* The ESCAPED_RETURN solution is what contains all memory that needs + to be considered global. */ + cfun->gimple_df->escaped_return + = find_what_var_points_to (cfun->decl, get_varinfo (escaped_return_id)); + cfun->gimple_df->escaped_return.escaped = 1; + /* Compute the points-to sets for pointer SSA_NAMEs. */ unsigned i; tree ptr; diff --git a/gcc/tree-ssa.cc b/gcc/tree-ssa.cc index 2f3210f..76856be 100644 --- a/gcc/tree-ssa.cc +++ b/gcc/tree-ssa.cc @@ -1216,6 +1216,7 @@ init_tree_ssa (struct function *fn, int size) fn->gimple_df = ggc_cleared_alloc<gimple_df> (); fn->gimple_df->default_defs = hash_table<ssa_name_hasher>::create_ggc (20); pt_solution_reset (&fn->gimple_df->escaped); + pt_solution_reset (&fn->gimple_df->escaped_return); init_ssanames (fn, size); } @@ -1233,6 +1234,7 @@ delete_tree_ssa (struct function *fn) fn->gimple_df->default_defs->empty (); fn->gimple_df->default_defs = NULL; pt_solution_reset (&fn->gimple_df->escaped); + pt_solution_reset (&fn->gimple_df->escaped_return); if (fn->gimple_df->decls_to_pointers != NULL) delete fn->gimple_df->decls_to_pointers; fn->gimple_df->decls_to_pointers = NULL; |