When simplifying the points-to-set comparison I failed to realize we don't expand ESCAPED special vars. The following does that for the only interesting one (NONLOCAL).
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Will apply to trunk and 4.9 branch if that succeeds. Richard. 2014-07-07 Richard Biener <rguent...@suse.de> PR tree-optimization/61681 * tree-ssa-structalias.c (find_what_var_points_to): Expand NONLOCAL inside ESCAPED. * gcc.dg/torture/pr61681.c: New testcase. Index: gcc/tree-ssa-structalias.c =================================================================== --- gcc/tree-ssa-structalias.c (revision 212323) +++ gcc/tree-ssa-structalias.c (working copy) @@ -6106,6 +6106,10 @@ find_what_var_points_to (varinfo_t orig_ pt->ipa_escaped = 1; else pt->escaped = 1; + /* Expand some special vars of ESCAPED in-place here. */ + varinfo_t evi = get_varinfo (find (escaped_id)); + if (bitmap_bit_p (evi->solution, nonlocal_id)) + pt->nonlocal = 1; } else if (vi->id == nonlocal_id) pt->nonlocal = 1; Index: gcc/testsuite/gcc.dg/torture/pr61681.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr61681.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr61681.c (working copy) @@ -0,0 +1,37 @@ +/* { dg-do run } */ + +extern void abort (void); + +int a = 1, *e = &a, **f = &e, *l, *p, j; +static int b; +long d; +short g; + +void +fn1 (int *p) +{ + int m; + if (!(*p & j)) + { + int *n = &m; + for (d = 6; d; d--) + { + for (g = 0; g < 1; g++) + { + n = l = *f; + b = *p; + } + *n = 0; + } + } +} + +int +main () +{ + p = *f; + fn1 (p); + if (b != 0) + abort (); + return 0; +}