diff options
author | Richard Biener <rguenther@suse.de> | 2019-04-15 10:09:08 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2019-04-15 10:09:08 +0000 |
commit | 869032b176d57ca8c8864a7818394106ca665d06 (patch) | |
tree | 091ea0a9c663a03956c774a6a3a164628d4e9f04 /gcc/tree-ssa-structalias.c | |
parent | 79a18702006d53bc378affcd5dd6c8df7883b58f (diff) | |
download | gcc-869032b176d57ca8c8864a7818394106ca665d06.zip gcc-869032b176d57ca8c8864a7818394106ca665d06.tar.gz gcc-869032b176d57ca8c8864a7818394106ca665d06.tar.bz2 |
re PR ipa/88936 (-fipa-pta breaks bash (incorrect optimisation of recursive static function))
2019-04-15 Richard Biener <rguenther@suse.de>
PR ipa/88936
* tree.h (auto_var_p): Declare.
* tree.c (auto_var_p): New function, split out from ...
(auto_var_in_fn_p): ... here.
* tree-ssa-structalias.c (struct variable_info): Add shadow_var_uid
member.
(new_var_info): Initialize it.
(set_uids_in_ptset): Also set the shadow variable uid if required.
(ipa_pta_execute): Postprocess points-to solutions assigning
shadow variable uids for locals that may reach their containing
function recursively.
* tree-ssa-ccp.c (fold_builtin_alloca_with_align): Do not
assert but instead check whether the points-to solution is
a singleton.
* gcc.dg/torture/pr88936-1.c: New testcase.
* gcc.dg/torture/pr88936-2.c: Likewise.
* gcc.dg/torture/pr88936-3.c: Likewise.
From-SVN: r270366
Diffstat (limited to 'gcc/tree-ssa-structalias.c')
-rw-r--r-- | gcc/tree-ssa-structalias.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index b92fcdd..4a0b02e 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -299,6 +299,11 @@ struct variable_info /* Full size of the base variable, in bits. */ unsigned HOST_WIDE_INT fullsize; + /* In IPA mode the shadow UID in case the variable needs to be duplicated in + the final points-to solution because it reaches its containing + function recursively. Zero if none is needed. */ + unsigned int shadow_var_uid; + /* Name of this variable */ const char *name; @@ -397,6 +402,7 @@ new_var_info (tree t, const char *name, bool add_id) ret->solution = BITMAP_ALLOC (&pta_obstack); ret->oldsolution = NULL; ret->next = 0; + ret->shadow_var_uid = 0; ret->head = ret->id; stats.total_vars++; @@ -6452,6 +6458,16 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt, && (TREE_STATIC (vi->decl) || DECL_EXTERNAL (vi->decl)) && ! decl_binds_to_current_def_p (vi->decl)) pt->vars_contains_interposable = true; + + /* If this is a local variable we can have overlapping lifetime + of different function invocations through recursion duplicate + it with its shadow variable. */ + if (in_ipa_mode + && vi->shadow_var_uid != 0) + { + bitmap_set_bit (into, vi->shadow_var_uid); + pt->vars_contains_nonlocal = true; + } } else if (TREE_CODE (vi->decl) == FUNCTION_DECL @@ -8076,6 +8092,62 @@ ipa_pta_execute (void) /* From the constraints compute the points-to sets. */ solve_constraints (); + /* Now post-process solutions to handle locals from different + runtime instantiations coming in through recursive invocations. */ + unsigned shadow_var_cnt = 0; + for (unsigned i = 1; i < varmap.length (); ++i) + { + varinfo_t fi = get_varinfo (i); + if (fi->is_fn_info + && fi->decl) + /* Automatic variables pointed to by their containing functions + parameters need this treatment. */ + for (varinfo_t ai = first_vi_for_offset (fi, fi_parm_base); + ai; ai = vi_next (ai)) + { + varinfo_t vi = get_varinfo (find (ai->id)); + bitmap_iterator bi; + unsigned j; + EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, j, bi) + { + varinfo_t pt = get_varinfo (j); + if (pt->shadow_var_uid == 0 + && pt->decl + && auto_var_in_fn_p (pt->decl, fi->decl)) + { + pt->shadow_var_uid = allocate_decl_uid (); + shadow_var_cnt++; + } + } + } + /* As well as global variables which are another way of passing + arguments to recursive invocations. */ + else if (fi->is_global_var) + { + for (varinfo_t ai = fi; ai; ai = vi_next (ai)) + { + varinfo_t vi = get_varinfo (find (ai->id)); + bitmap_iterator bi; + unsigned j; + EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, j, bi) + { + varinfo_t pt = get_varinfo (j); + if (pt->shadow_var_uid == 0 + && pt->decl + && auto_var_p (pt->decl)) + { + pt->shadow_var_uid = allocate_decl_uid (); + shadow_var_cnt++; + } + } + } + } + } + if (shadow_var_cnt && dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Allocated %u shadow variables for locals " + "maybe leaking into recursive invocations of their containing " + "functions\n", shadow_var_cnt); + /* Compute the global points-to sets for ESCAPED. ??? Note that the computed escape set is not correct for the whole unit as we fail to consider graph edges to |