From ee7d29b43faf156f55e55dfcb841fa38da2e855a Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 10 Dec 2015 09:41:08 +0000 Subject: [PATCH] re PR ipa/68331 ([meta-bug] fipa-pta issues) 2015-12-10 Richard Biener 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 --- gcc/ChangeLog | 13 +++++ gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/ipa/ipa-pta-1.C | 35 ++++++++++++ gcc/testsuite/gcc.dg/torture/ipa-pta-3.c | 19 +++++++ gcc/tree-ssa-structalias.c | 69 ++++++++++++++---------- 5 files changed, 115 insertions(+), 27 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ipa/ipa-pta-1.C create mode 100644 gcc/testsuite/gcc.dg/torture/ipa-pta-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9a7c01f5b99..eac59176108 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2015-12-10 Richard Biener + + 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 PR ada/65102 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7ac1418b9b8..6141624b7b9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-12-10 Richard Biener + + 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 PR ipa/68721 diff --git a/gcc/testsuite/g++.dg/ipa/ipa-pta-1.C b/gcc/testsuite/g++.dg/ipa/ipa-pta-1.C new file mode 100644 index 00000000000..a3d12f5f0c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/ipa-pta-1.C @@ -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; +} diff --git a/gcc/testsuite/gcc.dg/torture/ipa-pta-3.c b/gcc/testsuite/gcc.dg/torture/ipa-pta-3.c new file mode 100644 index 00000000000..c3ef3682f2b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/ipa-pta-3.c @@ -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; +} diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index ec30e1d6f48..5d29e5cca66 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -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 (); -- 2.30.2