Commit ed315c04 by Richard Biener Committed by Richard Biener

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
parent c45c8424
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.
2019-06-06 Martin Liska <mliska@suse.cz> 2019-06-06 Martin Liska <mliska@suse.cz>
PR web/87933 PR web/87933
......
2019-06-06 Richard Biener <rguenther@suse.de>
* gcc.dg/tree-ssa/alias-37.c: New testcase.
* gcc.dg/torture/20190604-1.c: Likewise.
* gcc.dg/tree-ssa/pta-callused.c: Adjust.
2019-06-06 Claudiu Zissulescu <claziss@synopsys.com> 2019-06-06 Claudiu Zissulescu <claziss@synopsys.com>
* gcc.target/arc/tmac-1.c: Reoreder dg-directives. * gcc.target/arc/tmac-1.c: Reoreder dg-directives.
......
/* { dg-do run } */
struct S { int *mem; };
struct S * __attribute__((noinline,noipa))
foo ()
{
struct S *s = __builtin_malloc (sizeof (struct S));
s->mem = __builtin_malloc (sizeof (int));
s->mem[0] = 1;
return s;
}
int
main()
{
struct S *s = foo();
if (s->mem[0] != 1)
__builtin_abort ();
return 0;
}
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-dse1-details" } */
int i;
int *foo (int bogus, int n)
{
int a[n];
a[2] = bogus; /* Should elide this store since a cannot escape. */
int *p;
if (bogus)
p = &a[2];
else
p = &i;
return p;
}
/* { dg-final { scan-tree-dump "Deleted dead store" "dse1" } } */
...@@ -22,5 +22,5 @@ int bar (int b) ...@@ -22,5 +22,5 @@ int bar (int b)
return *foo (&q); return *foo (&q);
} }
/* { dg-final { scan-tree-dump "CALLUSED\\(\[0-9\]+\\) = { ESCAPED NONLOCAL f.* i q }" "alias" } } */ /* { dg-final { scan-tree-dump "CALLUSED\\(\[0-9\]+\\) = { f.* i q }" "alias" } } */
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "stringpool.h" #include "stringpool.h"
#include "attribs.h" #include "attribs.h"
#include "tree-ssa.h" #include "tree-ssa.h"
#include "tree-cfg.h"
/* The idea behind this analyzer is to generate set constraints from the /* The idea behind this analyzer is to generate set constraints from the
program, then solve the resulting constraints in order to generate the program, then solve the resulting constraints in order to generate the
...@@ -3854,7 +3855,6 @@ make_heapvar (const char *name, bool add_id) ...@@ -3854,7 +3855,6 @@ make_heapvar (const char *name, bool add_id)
DECL_EXTERNAL (heapvar) = 1; DECL_EXTERNAL (heapvar) = 1;
vi = new_var_info (heapvar, name, add_id); vi = new_var_info (heapvar, name, add_id);
vi->is_artificial_var = true;
vi->is_heap_var = true; vi->is_heap_var = true;
vi->is_unknown_size_var = true; vi->is_unknown_size_var = true;
vi->offset = 0; vi->offset = 0;
...@@ -4409,6 +4409,32 @@ find_func_aliases_for_builtin_call (struct function *fn, gcall *t) ...@@ -4409,6 +4409,32 @@ find_func_aliases_for_builtin_call (struct function *fn, gcall *t)
process_constraint (new_constraint (*lhsp, ac)); process_constraint (new_constraint (*lhsp, ac));
return true; 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: case BUILT_IN_POSIX_MEMALIGN:
{ {
tree ptrptr = gimple_call_arg (t, 0); tree ptrptr = gimple_call_arg (t, 0);
...@@ -4976,7 +5002,12 @@ find_func_aliases (struct function *fn, gimple *origt) ...@@ -4976,7 +5002,12 @@ find_func_aliases (struct function *fn, gimple *origt)
greturn *return_stmt = as_a <greturn *> (t); greturn *return_stmt = as_a <greturn *> (t);
fi = NULL; fi = NULL;
if (!in_ipa_mode 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)); make_escape_constraint (gimple_return_retval (return_stmt));
else if (in_ipa_mode) else if (in_ipa_mode)
{ {
...@@ -6422,9 +6453,7 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt, ...@@ -6422,9 +6453,7 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt,
{ {
varinfo_t vi = get_varinfo (i); varinfo_t vi = get_varinfo (i);
/* The only artificial variables that are allowed in a may-alias if (vi->is_artificial_var)
set are heap variables. */
if (vi->is_artificial_var && !vi->is_heap_var)
continue; continue;
if (everything_escaped if (everything_escaped
...@@ -6544,9 +6573,6 @@ find_what_var_points_to (tree fndecl, varinfo_t orig_vi) ...@@ -6544,9 +6573,6 @@ find_what_var_points_to (tree fndecl, varinfo_t orig_vi)
} }
else if (vi->id == nonlocal_id) else if (vi->id == nonlocal_id)
pt->nonlocal = 1; pt->nonlocal = 1;
else if (vi->is_heap_var)
/* We represent heapvars in the points-to set properly. */
;
else if (vi->id == string_id) else if (vi->id == string_id)
/* Nobody cares - STRING_CSTs are read-only entities. */ /* Nobody cares - STRING_CSTs are read-only entities. */
; ;
...@@ -7254,9 +7280,6 @@ solve_constraints (void) ...@@ -7254,9 +7280,6 @@ solve_constraints (void)
dump_constraint_graph (dump_file); dump_constraint_graph (dump_file);
fprintf (dump_file, "\n\n"); 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 /* Create points-to sets for the current function. See the comments
...@@ -7304,6 +7327,73 @@ compute_points_to_sets (void) ...@@ -7304,6 +7327,73 @@ compute_points_to_sets (void)
/* From the constraints compute the points-to sets. */ /* From the constraints compute the points-to sets. */
solve_constraints (); 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. */ /* Compute the points-to set for ESCAPED used for call-clobber analysis. */
cfun->gimple_df->escaped = find_what_var_points_to (cfun->decl, cfun->gimple_df->escaped = find_what_var_points_to (cfun->decl,
get_varinfo (escaped_id)); get_varinfo (escaped_id));
...@@ -8109,6 +8199,9 @@ ipa_pta_execute (void) ...@@ -8109,6 +8199,9 @@ ipa_pta_execute (void)
/* From the constraints compute the points-to sets. */ /* From the constraints compute the points-to sets. */
solve_constraints (); solve_constraints ();
if (dump_file)
dump_sa_points_to_info (dump_file);
/* Now post-process solutions to handle locals from different /* Now post-process solutions to handle locals from different
runtime instantiations coming in through recursive invocations. */ runtime instantiations coming in through recursive invocations. */
unsigned shadow_var_cnt = 0; unsigned shadow_var_cnt = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment