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
This commit is contained in:
Richard Biener 2019-06-06 07:25:19 +00:00 committed by Richard Biener
parent c45c8424de
commit ed315c041f
6 changed files with 164 additions and 12 deletions

View File

@ -1,3 +1,18 @@
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>
PR web/87933

View File

@ -1,3 +1,9 @@
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>
* gcc.target/arc/tmac-1.c: Reoreder dg-directives.

View File

@ -0,0 +1,21 @@
/* { 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;
}

View File

@ -0,0 +1,17 @@
/* { 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" } } */

View File

@ -22,5 +22,5 @@ int bar (int b)
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" } } */

View File

@ -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;