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
This commit is contained in:
parent
e53ed9f4c5
commit
ee7d29b43f
5 changed files with 115 additions and 27 deletions
|
@ -1,3 +1,16 @@
|
|||
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>
|
||||
|
||||
PR ada/65102
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
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
|
||||
|
|
35
gcc/testsuite/g++.dg/ipa/ipa-pta-1.C
Normal file
35
gcc/testsuite/g++.dg/ipa/ipa-pta-1.C
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* { 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;
|
||||
}
|
19
gcc/testsuite/gcc.dg/torture/ipa-pta-3.c
Normal file
19
gcc/testsuite/gcc.dg/torture/ipa-pta-3.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* { 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 @@
|
|||
|
||||
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
|
||||
externally visible globals are escape points in IPA mode. This is
|
||||
also needed to fix the pt_solution_includes_global predicate
|
||||
(and thus ptr_deref_may_alias_global_p).
|
||||
externally visible globals are escape points in IPA mode.
|
||||
|
||||
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
|
||||
|
@ -186,6 +184,7 @@
|
|||
propagating it simply like the clobber / uses solutions. The
|
||||
solution can go alongside the non-IPA espaced solution and be
|
||||
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
|
||||
keep the set of called functions for indirect calls.
|
||||
|
@ -6150,7 +6149,8 @@ shared_bitmap_add (bitmap pt_vars)
|
|||
/* Set bits in INTO corresponding to the variable uids in solution set FROM. */
|
||||
|
||||
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;
|
||||
bitmap_iterator bi;
|
||||
|
@ -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
|
||||
set contains global variables. */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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. */
|
||||
|
||||
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;
|
||||
bitmap_iterator bi;
|
||||
|
@ -6263,7 +6275,7 @@ find_what_var_points_to (varinfo_t orig_vi)
|
|||
finished_solution = BITMAP_GGC_ALLOC ();
|
||||
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);
|
||||
if (!result)
|
||||
{
|
||||
|
@ -6282,7 +6294,7 @@ find_what_var_points_to (varinfo_t orig_vi)
|
|||
/* Given a pointer variable P, fill in its points-to set. */
|
||||
|
||||
static void
|
||||
find_what_p_points_to (tree p)
|
||||
find_what_p_points_to (tree fndecl, tree p)
|
||||
{
|
||||
struct ptr_info_def *pi;
|
||||
tree lookup_p = p;
|
||||
|
@ -6301,7 +6313,7 @@ find_what_p_points_to (tree p)
|
|||
return;
|
||||
|
||||
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)
|
|||
if (pt->ipa_escaped)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -6969,7 +6975,8 @@ compute_points_to_sets (void)
|
|||
solve_constraints ();
|
||||
|
||||
/* 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
|
||||
other solutions) does not reference itself. This simplifies
|
||||
|
@ -6982,7 +6989,7 @@ compute_points_to_sets (void)
|
|||
tree ptr = ssa_name (i);
|
||||
if (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. */
|
||||
|
@ -7004,7 +7011,7 @@ compute_points_to_sets (void)
|
|||
memset (pt, 0, sizeof (struct pt_solution));
|
||||
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
|
||||
implicitly used by calls. */
|
||||
/* ??? ESCAPED can be empty even though NONLOCAL
|
||||
|
@ -7025,7 +7032,7 @@ compute_points_to_sets (void)
|
|||
memset (pt, 0, sizeof (struct pt_solution));
|
||||
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
|
||||
implicitly clobbered by calls. */
|
||||
/* ??? ESCAPED can be empty even though NONLOCAL
|
||||
|
@ -7565,7 +7572,7 @@ ipa_pta_execute (void)
|
|||
??? Note that the computed escape set is not correct
|
||||
for the whole unit as we fail to consider graph edges to
|
||||
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
|
||||
other solutions) does not reference itself. This simplifies
|
||||
|
@ -7591,7 +7598,7 @@ ipa_pta_execute (void)
|
|||
{
|
||||
if (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
|
||||
|
@ -7625,10 +7632,10 @@ ipa_pta_execute (void)
|
|||
{
|
||||
*gimple_call_clobber_set (stmt)
|
||||
= 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)
|
||||
= 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. */
|
||||
else if (decl)
|
||||
|
@ -7638,7 +7645,7 @@ ipa_pta_execute (void)
|
|||
memset (pt, 0, sizeof (struct pt_solution));
|
||||
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
|
||||
implicitly used by calls. */
|
||||
/* ??? ESCAPED can be empty even though NONLOCAL
|
||||
|
@ -7659,7 +7666,7 @@ ipa_pta_execute (void)
|
|||
memset (pt, 0, sizeof (struct pt_solution));
|
||||
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
|
||||
implicitly clobbered by calls. */
|
||||
/* ??? ESCAPED can be empty even though NONLOCAL
|
||||
|
@ -7719,13 +7726,15 @@ ipa_pta_execute (void)
|
|||
if (!uses->anything)
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (!clobbers->anything)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -7735,6 +7744,12 @@ ipa_pta_execute (void)
|
|||
}
|
||||
|
||||
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 ();
|
||||
|
|
Loading…
Add table
Reference in a new issue