Commit ee7d29b4 by Richard Biener Committed by Richard Biener

re PR ipa/68331 ([meta-bug] fipa-pta issues)

2015-12-10  Richard Biener  <rguenther@suse.de>

	PR ipa/68331
	* tree-ssa-structalias.c (set_uids_in_ptset): Add fndecl
	parameter and make vars_contains_nonlocal properly have
	function-scope semantics in IPA mode.
	(find_what_var_points_to): Add fndecl parameter.
	(find_what_p_points_to): Likewise.
	(pt_solution_includes_global): Remove IPA PTA early out.
	(compute_points_to_sets): Adjust.
	(ipa_pta_execute): Likewise.  Clear final_solutions after
	each function.

	* gcc.dg/torture/ipa-pta-3.c: New testcase.
	* g++.dg/ipa/ipa-pta-1.C: Likewise.

From-SVN: r231498
parent e53ed9f4
2015-12-10 Richard Biener <rguenther@suse.de>
PR ipa/68331
* tree-ssa-structalias.c (set_uids_in_ptset): Add fndecl
parameter and make vars_contains_nonlocal properly have
function-scope semantics in IPA mode.
(find_what_var_points_to): Add fndecl parameter.
(find_what_p_points_to): Likewise.
(pt_solution_includes_global): Remove IPA PTA early out.
(compute_points_to_sets): Adjust.
(ipa_pta_execute): Likewise. Clear final_solutions after
each function.
2015-12-10 Tom de Vries <tom@codesourcery.com> 2015-12-10 Tom de Vries <tom@codesourcery.com>
PR ada/65102 PR ada/65102
2015-12-10 Richard Biener <rguenther@suse.de> 2015-12-10 Richard Biener <rguenther@suse.de>
PR ipa/68331
* gcc.dg/torture/ipa-pta-3.c: New testcase.
* g++.dg/ipa/ipa-pta-1.C: Likewise.
2015-12-10 Richard Biener <rguenther@suse.de>
PR ipa/68721 PR ipa/68721
* gcc.dg/torture/pr68721.c: New testcase. * gcc.dg/torture/pr68721.c: New testcase.
......
/* { dg-do run } */
/* { dg-options "-O2 -fipa-pta" } */
struct A {
A() {ptr=&b;}
A(const A &a) {ptr = &b;}
void test() { if (ptr != &b) __builtin_abort ();}
int b;
int *ptr;
};
A test1(A a)
{
a.test();
return a;
}
A test2(A a)
{
a.test();
return a;
}
__attribute__ ((noinline))
static void
test_me (A (*t)(A))
{
struct A a, b=t(a);
b.test ();
}
int
main()
{
test_me (test1);
test_me (test2);
return 0;
}
/* { dg-do run } */
/* { dg-additional-options "-fipa-pta" } */
extern void abort (void);
extern void *malloc (__SIZE_TYPE__);
static int *p;
static void __attribute__((noinline,noclone)) foo ()
{
p = (int *) malloc (24);
*p = 2;
}
int main()
{
foo ();
if (*p != 2)
abort ();
return 0;
}
...@@ -159,9 +159,7 @@ ...@@ -159,9 +159,7 @@
The is_global_var bit which marks escape points is overly conservative The is_global_var bit which marks escape points is overly conservative
in IPA mode. Split it to is_escape_point and is_global_var - only in IPA mode. Split it to is_escape_point and is_global_var - only
externally visible globals are escape points in IPA mode. This is externally visible globals are escape points in IPA mode.
also needed to fix the pt_solution_includes_global predicate
(and thus ptr_deref_may_alias_global_p).
The way we introduce DECL_PT_UID to avoid fixing up all points-to The way we introduce DECL_PT_UID to avoid fixing up all points-to
sets in the translation unit when we copy a DECL during inlining sets in the translation unit when we copy a DECL during inlining
...@@ -186,6 +184,7 @@ ...@@ -186,6 +184,7 @@
propagating it simply like the clobber / uses solutions. The propagating it simply like the clobber / uses solutions. The
solution can go alongside the non-IPA espaced solution and be solution can go alongside the non-IPA espaced solution and be
used to query which vars escape the unit through a function. used to query which vars escape the unit through a function.
This is also required to make the escaped-HEAP trick work in IPA mode.
We never put function decls in points-to sets so we do not We never put function decls in points-to sets so we do not
keep the set of called functions for indirect calls. keep the set of called functions for indirect calls.
...@@ -6150,7 +6149,8 @@ shared_bitmap_add (bitmap pt_vars) ...@@ -6150,7 +6149,8 @@ shared_bitmap_add (bitmap pt_vars)
/* Set bits in INTO corresponding to the variable uids in solution set FROM. */ /* Set bits in INTO corresponding to the variable uids in solution set FROM. */
static void static void
set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt) set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt,
tree fndecl)
{ {
unsigned int i; unsigned int i;
bitmap_iterator bi; bitmap_iterator bi;
...@@ -6188,7 +6188,19 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt) ...@@ -6188,7 +6188,19 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
/* Add the decl to the points-to set. Note that the points-to /* Add the decl to the points-to set. Note that the points-to
set contains global variables. */ set contains global variables. */
bitmap_set_bit (into, DECL_PT_UID (vi->decl)); bitmap_set_bit (into, DECL_PT_UID (vi->decl));
if (vi->is_global_var) if (vi->is_global_var
/* In IPA mode the escaped_heap trick doesn't work as
ESCAPED is escaped from the unit but
pt_solution_includes_global needs to answer true for
all variables not automatic within a function.
For the same reason is_global_var is not the
correct flag to track - local variables from other
functions also need to be considered global.
Conveniently all HEAP vars are not put in function
scope. */
|| (in_ipa_mode
&& fndecl
&& ! auto_var_in_fn_p (vi->decl, fndecl)))
pt->vars_contains_nonlocal = true; pt->vars_contains_nonlocal = true;
} }
} }
...@@ -6198,7 +6210,7 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt) ...@@ -6198,7 +6210,7 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
/* Compute the points-to solution *PT for the variable VI. */ /* Compute the points-to solution *PT for the variable VI. */
static struct pt_solution static struct pt_solution
find_what_var_points_to (varinfo_t orig_vi) find_what_var_points_to (tree fndecl, varinfo_t orig_vi)
{ {
unsigned int i; unsigned int i;
bitmap_iterator bi; bitmap_iterator bi;
...@@ -6263,7 +6275,7 @@ find_what_var_points_to (varinfo_t orig_vi) ...@@ -6263,7 +6275,7 @@ find_what_var_points_to (varinfo_t orig_vi)
finished_solution = BITMAP_GGC_ALLOC (); finished_solution = BITMAP_GGC_ALLOC ();
stats.points_to_sets_created++; stats.points_to_sets_created++;
set_uids_in_ptset (finished_solution, vi->solution, pt); set_uids_in_ptset (finished_solution, vi->solution, pt, fndecl);
result = shared_bitmap_lookup (finished_solution); result = shared_bitmap_lookup (finished_solution);
if (!result) if (!result)
{ {
...@@ -6282,7 +6294,7 @@ find_what_var_points_to (varinfo_t orig_vi) ...@@ -6282,7 +6294,7 @@ find_what_var_points_to (varinfo_t orig_vi)
/* Given a pointer variable P, fill in its points-to set. */ /* Given a pointer variable P, fill in its points-to set. */
static void static void
find_what_p_points_to (tree p) find_what_p_points_to (tree fndecl, tree p)
{ {
struct ptr_info_def *pi; struct ptr_info_def *pi;
tree lookup_p = p; tree lookup_p = p;
...@@ -6301,7 +6313,7 @@ find_what_p_points_to (tree p) ...@@ -6301,7 +6313,7 @@ find_what_p_points_to (tree p)
return; return;
pi = get_ptr_info (p); pi = get_ptr_info (p);
pi->pt = find_what_var_points_to (vi); pi->pt = find_what_var_points_to (fndecl, vi);
} }
...@@ -6467,12 +6479,6 @@ pt_solution_includes_global (struct pt_solution *pt) ...@@ -6467,12 +6479,6 @@ pt_solution_includes_global (struct pt_solution *pt)
if (pt->ipa_escaped) if (pt->ipa_escaped)
return pt_solution_includes_global (&ipa_escaped_pt); return pt_solution_includes_global (&ipa_escaped_pt);
/* ??? This predicate is not correct for the IPA-PTA solution
as we do not properly distinguish between unit escape points
and global variables. */
if (cfun->gimple_df->ipa_pta)
return true;
return false; return false;
} }
...@@ -6969,7 +6975,8 @@ compute_points_to_sets (void) ...@@ -6969,7 +6975,8 @@ compute_points_to_sets (void)
solve_constraints (); solve_constraints ();
/* 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 (get_varinfo (escaped_id)); cfun->gimple_df->escaped = find_what_var_points_to (cfun->decl,
get_varinfo (escaped_id));
/* Make sure the ESCAPED solution (which is used as placeholder in /* Make sure the ESCAPED solution (which is used as placeholder in
other solutions) does not reference itself. This simplifies other solutions) does not reference itself. This simplifies
...@@ -6982,7 +6989,7 @@ compute_points_to_sets (void) ...@@ -6982,7 +6989,7 @@ compute_points_to_sets (void)
tree ptr = ssa_name (i); tree ptr = ssa_name (i);
if (ptr if (ptr
&& POINTER_TYPE_P (TREE_TYPE (ptr))) && POINTER_TYPE_P (TREE_TYPE (ptr)))
find_what_p_points_to (ptr); find_what_p_points_to (cfun->decl, ptr);
} }
/* Compute the call-used/clobbered sets. */ /* Compute the call-used/clobbered sets. */
...@@ -7004,7 +7011,7 @@ compute_points_to_sets (void) ...@@ -7004,7 +7011,7 @@ compute_points_to_sets (void)
memset (pt, 0, sizeof (struct pt_solution)); memset (pt, 0, sizeof (struct pt_solution));
else if ((vi = lookup_call_use_vi (stmt)) != NULL) else if ((vi = lookup_call_use_vi (stmt)) != NULL)
{ {
*pt = find_what_var_points_to (vi); *pt = find_what_var_points_to (cfun->decl, vi);
/* Escaped (and thus nonlocal) variables are always /* Escaped (and thus nonlocal) variables are always
implicitly used by calls. */ implicitly used by calls. */
/* ??? ESCAPED can be empty even though NONLOCAL /* ??? ESCAPED can be empty even though NONLOCAL
...@@ -7025,7 +7032,7 @@ compute_points_to_sets (void) ...@@ -7025,7 +7032,7 @@ compute_points_to_sets (void)
memset (pt, 0, sizeof (struct pt_solution)); memset (pt, 0, sizeof (struct pt_solution));
else if ((vi = lookup_call_clobber_vi (stmt)) != NULL) else if ((vi = lookup_call_clobber_vi (stmt)) != NULL)
{ {
*pt = find_what_var_points_to (vi); *pt = find_what_var_points_to (cfun->decl, vi);
/* Escaped (and thus nonlocal) variables are always /* Escaped (and thus nonlocal) variables are always
implicitly clobbered by calls. */ implicitly clobbered by calls. */
/* ??? ESCAPED can be empty even though NONLOCAL /* ??? ESCAPED can be empty even though NONLOCAL
...@@ -7565,7 +7572,7 @@ ipa_pta_execute (void) ...@@ -7565,7 +7572,7 @@ ipa_pta_execute (void)
??? Note that the computed escape set is not correct ??? Note that the computed escape set is not correct
for the whole unit as we fail to consider graph edges to for the whole unit as we fail to consider graph edges to
externally visible functions. */ externally visible functions. */
ipa_escaped_pt = find_what_var_points_to (get_varinfo (escaped_id)); ipa_escaped_pt = find_what_var_points_to (NULL, get_varinfo (escaped_id));
/* Make sure the ESCAPED solution (which is used as placeholder in /* Make sure the ESCAPED solution (which is used as placeholder in
other solutions) does not reference itself. This simplifies other solutions) does not reference itself. This simplifies
...@@ -7591,7 +7598,7 @@ ipa_pta_execute (void) ...@@ -7591,7 +7598,7 @@ ipa_pta_execute (void)
{ {
if (ptr if (ptr
&& POINTER_TYPE_P (TREE_TYPE (ptr))) && POINTER_TYPE_P (TREE_TYPE (ptr)))
find_what_p_points_to (ptr); find_what_p_points_to (node->decl, ptr);
} }
/* Compute the call-use and call-clobber sets for indirect calls /* Compute the call-use and call-clobber sets for indirect calls
...@@ -7625,10 +7632,10 @@ ipa_pta_execute (void) ...@@ -7625,10 +7632,10 @@ ipa_pta_execute (void)
{ {
*gimple_call_clobber_set (stmt) *gimple_call_clobber_set (stmt)
= find_what_var_points_to = find_what_var_points_to
(first_vi_for_offset (fi, fi_clobbers)); (node->decl, first_vi_for_offset (fi, fi_clobbers));
*gimple_call_use_set (stmt) *gimple_call_use_set (stmt)
= find_what_var_points_to = find_what_var_points_to
(first_vi_for_offset (fi, fi_uses)); (node->decl, first_vi_for_offset (fi, fi_uses));
} }
/* Handle direct calls to external functions. */ /* Handle direct calls to external functions. */
else if (decl) else if (decl)
...@@ -7638,7 +7645,7 @@ ipa_pta_execute (void) ...@@ -7638,7 +7645,7 @@ ipa_pta_execute (void)
memset (pt, 0, sizeof (struct pt_solution)); memset (pt, 0, sizeof (struct pt_solution));
else if ((vi = lookup_call_use_vi (stmt)) != NULL) else if ((vi = lookup_call_use_vi (stmt)) != NULL)
{ {
*pt = find_what_var_points_to (vi); *pt = find_what_var_points_to (node->decl, vi);
/* Escaped (and thus nonlocal) variables are always /* Escaped (and thus nonlocal) variables are always
implicitly used by calls. */ implicitly used by calls. */
/* ??? ESCAPED can be empty even though NONLOCAL /* ??? ESCAPED can be empty even though NONLOCAL
...@@ -7659,7 +7666,7 @@ ipa_pta_execute (void) ...@@ -7659,7 +7666,7 @@ ipa_pta_execute (void)
memset (pt, 0, sizeof (struct pt_solution)); memset (pt, 0, sizeof (struct pt_solution));
else if ((vi = lookup_call_clobber_vi (stmt)) != NULL) else if ((vi = lookup_call_clobber_vi (stmt)) != NULL)
{ {
*pt = find_what_var_points_to (vi); *pt = find_what_var_points_to (node->decl, vi);
/* Escaped (and thus nonlocal) variables are always /* Escaped (and thus nonlocal) variables are always
implicitly clobbered by calls. */ implicitly clobbered by calls. */
/* ??? ESCAPED can be empty even though NONLOCAL /* ??? ESCAPED can be empty even though NONLOCAL
...@@ -7719,13 +7726,15 @@ ipa_pta_execute (void) ...@@ -7719,13 +7726,15 @@ ipa_pta_execute (void)
if (!uses->anything) if (!uses->anything)
{ {
sol = find_what_var_points_to sol = find_what_var_points_to
(first_vi_for_offset (vi, fi_uses)); (node->decl,
first_vi_for_offset (vi, fi_uses));
pt_solution_ior_into (uses, &sol); pt_solution_ior_into (uses, &sol);
} }
if (!clobbers->anything) if (!clobbers->anything)
{ {
sol = find_what_var_points_to sol = find_what_var_points_to
(first_vi_for_offset (vi, fi_clobbers)); (node->decl,
first_vi_for_offset (vi, fi_clobbers));
pt_solution_ior_into (clobbers, &sol); pt_solution_ior_into (clobbers, &sol);
} }
} }
...@@ -7735,6 +7744,12 @@ ipa_pta_execute (void) ...@@ -7735,6 +7744,12 @@ ipa_pta_execute (void)
} }
fn->gimple_df->ipa_pta = true; fn->gimple_df->ipa_pta = true;
/* We have to re-set the final-solution cache after each function
because what is a "global" is dependent on function context. */
final_solutions->empty ();
obstack_free (&final_solutions_obstack, NULL);
gcc_obstack_init (&final_solutions_obstack);
} }
delete_points_to_sets (); delete_points_to_sets ();
......
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