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:
parent
c45c8424de
commit
ed315c041f
@ -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
|
||||
|
@ -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.
|
||||
|
21
gcc/testsuite/gcc.dg/torture/20190604-1.c
Normal file
21
gcc/testsuite/gcc.dg/torture/20190604-1.c
Normal 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;
|
||||
}
|
17
gcc/testsuite/gcc.dg/tree-ssa/alias-37.c
Normal file
17
gcc/testsuite/gcc.dg/tree-ssa/alias-37.c
Normal 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" } } */
|
@ -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" } } */
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user