On Fri, 12 Apr 2019, Richard Biener wrote: > On Fri, 12 Apr 2019, Michael Matz wrote: > > > Hi, > > > > On Fri, 12 Apr 2019, Richard Biener wrote: > > > > > > You miss PARM_DECLs and RESULT_DECLs, i.e. it's probably better to > > > > factor > > > > out tree.c:auto_var_in_fn_p and place the new auto_var_p in tree.c as > > > > well. > > > > > > Hmm, I left the above unchanged from a different variant of the patch > > > where for some reason I do not remember I explicitely decided > > > parameters and results are not affected... > > > > Even if that were the case the function is sufficiently general (also its > > name) that it should be generic infrastructure, not hidden away in > > structalias. > > It was not fully equivalent, but yes. So - like the following? > I think checking DECL_CONTEXT isn't necessary given the > !DECL_EXTERNAL/STATIC checks. > > Bootstrap / regtest running on x86_64-unknown-linux-gnu.
Aww, hits /space/rguenther/src/svn/trunk/libgomp/testsuite/libgomp.oacc-c/../libgomp.oacc-c-c++-common/zero_length_subarrays.c:33:1: internal compiler error: in fold_builtin_alloca_with_align, at tree-ssa-ccp.c:2186^M 0x6d7e45 fold_builtin_alloca_with_align^M have to look/think about this. Richard. > Richard. > > 2019-04-12 Richard Biener <rguent...@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. > > * gcc.dg/torture/pr88936-1.c: New testcase. > * gcc.dg/torture/pr88936-2.c: Likewise. > * gcc.dg/torture/pr88936-3.c: Likewise. > > Index: gcc/tree.c > =================================================================== > --- gcc/tree.c (revision 270306) > +++ gcc/tree.c (working copy) > @@ -9268,17 +9268,25 @@ get_type_static_bounds (const_tree type, > } > } > > +/* Return true if VAR is an automatic variable. */ > + > +bool > +auto_var_p (const_tree var) > +{ > + return ((((VAR_P (var) && ! DECL_EXTERNAL (var)) > + || TREE_CODE (var) == PARM_DECL) > + && ! TREE_STATIC (var)) > + || TREE_CODE (var) == RESULT_DECL); > +} > + > /* Return true if VAR is an automatic variable defined in function FN. */ > > bool > auto_var_in_fn_p (const_tree var, const_tree fn) > { > return (DECL_P (var) && DECL_CONTEXT (var) == fn > - && ((((VAR_P (var) && ! DECL_EXTERNAL (var)) > - || TREE_CODE (var) == PARM_DECL) > - && ! TREE_STATIC (var)) > - || TREE_CODE (var) == LABEL_DECL > - || TREE_CODE (var) == RESULT_DECL)); > + && (auto_var_p (var) > + || TREE_CODE (var) == LABEL_DECL)); > } > > /* Subprogram of following function. Called by walk_tree. > Index: gcc/tree.h > =================================================================== > --- gcc/tree.h (revision 270306) > +++ gcc/tree.h (working copy) > @@ -4893,6 +4893,7 @@ extern bool stdarg_p (const_tree); > extern bool prototype_p (const_tree); > extern bool is_typedef_decl (const_tree x); > extern bool typedef_variant_p (const_tree); > +extern bool auto_var_p (const_tree); > extern bool auto_var_in_fn_p (const_tree, const_tree); > extern tree build_low_bits_mask (tree, unsigned); > extern bool tree_nop_conversion_p (const_tree, const_tree); > Index: gcc/tree-ssa-structalias.c > =================================================================== > --- gcc/tree-ssa-structalias.c (revision 270306) > +++ gcc/tree-ssa-structalias.c (working copy) > @@ -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, > 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 f > && (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 +8095,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 > Index: gcc/testsuite/gcc.dg/torture/pr88936-1.c > =================================================================== > --- gcc/testsuite/gcc.dg/torture/pr88936-1.c (nonexistent) > +++ gcc/testsuite/gcc.dg/torture/pr88936-1.c (working copy) > @@ -0,0 +1,27 @@ > +/* { dg-do run } */ > +/* { dg-additional-options "-fipa-pta" } */ > + > +static long bug (long depth, long * v) > +{ > + if (depth == 0) > + { > + *v = 0; > + return 1; > + } > + > + long r = 1; > + long val = bug(depth - 1, &r); > + return 2 * r + val; > +} > + > +static long ff (long depth) > +{ > + return bug(depth, (long*)0); > +} > + > +int main() > +{ > + if (ff(1) != 1) > + __builtin_abort (); > + return 0; > +} > Index: gcc/testsuite/gcc.dg/torture/pr88936-2.c > =================================================================== > --- gcc/testsuite/gcc.dg/torture/pr88936-2.c (nonexistent) > +++ gcc/testsuite/gcc.dg/torture/pr88936-2.c (working copy) > @@ -0,0 +1,22 @@ > +/* { dg-do run } */ > +/* { dg-additional-options "-fipa-pta" } */ > + > +static int *p; > +void bar(int cnt) > +{ > + int i = 0; > + if (cnt == 0) > + { > + p = &i; > + bar (1); > + if (i != 1) > + __builtin_abort (); > + } > + else if (cnt == 1) > + *p = 1; > +} > +int main() > +{ > + bar (0); > + return 0; > +} > Index: gcc/testsuite/gcc.dg/torture/pr88936-3.c > =================================================================== > --- gcc/testsuite/gcc.dg/torture/pr88936-3.c (nonexistent) > +++ gcc/testsuite/gcc.dg/torture/pr88936-3.c (working copy) > @@ -0,0 +1,21 @@ > +/* { dg-do run } */ > +/* { dg-additional-options "-fipa-pta" } */ > + > +static int *p; > +void bar(int cnt) > +{ > + if (cnt == 0) > + { > + p = &cnt; > + bar (1); > + if (cnt != 1) > + __builtin_abort (); > + } > + else if (cnt == 1) > + *p = 1; > +} > +int main() > +{ > + bar (0); > + return 0; > +} > -- Richard Biener <rguent...@suse.de> SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imendörffer, Mary Higgins, Sri Rasiah; HRB 21284 (AG Nürnberg)