[PATCH] Track pure function call uses separately
Richard Guenther
rguenther@suse.de
Fri Jun 27 12:42:00 GMT 2008
On Fri, 27 Jun 2008, Richard Guenther wrote:
> On Thu, 26 Jun 2008, Daniel Berlin wrote:
>
>> On Thu, Jun 26, 2008 at 12:34 PM, Richard Guenther <rguenther@suse.de>
>> wrote:
>>>
>>> This adds the ability (on top of
>>> http://gcc.gnu.org/ml/gcc-patches/2008-06/msg01432.html - PING for that)
>>
>> I thought I okayed that one on IRC.
>> I will do so explicitly in a moment.
>
> We have one "little" problem. If we re-enable field-sensitive PTA
> then the transitive closure we use for computing the ESCAPED set
> is no longer equivalent to the reachability, which we really need
> to compute. Consider
>
> struct Foo {
> int *p;
> int *q;
> };
>
> void __attribute__((noinline))
> bar (int **x)
> {
> struct Foo *f = (struct Foo *)x;
> *(f->q) = 0;
> }
>
> int foo(void)
> {
> struct Foo f;
> int i = 1, j = 2;
> f.p = &i;
> f.q = &j;
> bar(&f.p);
> return j;
> }
>
> extern void abort (void);
> int main()
> {
> if (foo () != 0)
> abort ();
> }
>
> where in foo we end up with
>
> ESCAPED = *ESCAPED
> derefaddrtmp.30 = &ESCAPED
> *ESCAPED = derefaddrtmp.30
> derefaddrtmp.31 = &NONLOCAL
> *ESCAPED = derefaddrtmp.31
> f = &i
> f.q = &j
> ESCAPED = &f
>
> and the solution
>
> ESCAPED = { ESCAPED NONLOCAL f i }
> f = { ESCAPED NONLOCAL i }
> f.q = { j }
>
> while f.q and j should also be escaped and f.q pointing to
> ESCAPED NONLOCAL as well.
>
> So what we would need here is a special deref constraint that
> dereferences all subvars and use that for the ESCAPED = *ESCAPED
> constraint. Where can this be implemented? I guess the solver
> itself doesn't know about subvariables, but at constraint generation
> time we cannot fix this either. Computing the reachability after
> PTA does also not work because then the PTA results would be wrong
> again.
>
> Ideas? It looks like we would need to add constraints on-the-fly
> during solving - is this possible at all? (can you hint me at
> where I would need to add those?)
Ok, I have it "working" with something like the following.
Basically we need to treat 'reachability vars' specially, for
ESCAPED this is constraints of the form
ESCAPED = x
(in the solution propagation propagate using set_union_all_fields)
ESCAPED = &x
initially add all fields of x to ESCAPED. Probably better done by
collapsing x - the solution of x will get all of ESCAPED through
the *ESCAPED = ESCAPED constraint anyway, so no point in processing
the fields of x separately. (Ideally we would collapse during
solving, but that doesn't look easily doable(?))
ESCAPED = *ESCAPED
I hacked do_sd_constraint to handle this special case - we need
to add all fields the solution in ESCAPED can reach.
So, it gets somewhat ugly, and of course I am not sure that
variable unification will not get in our way ... (when exactly
are two variables unified?)
Thanks,
Richard.
Index: trunk/gcc/tree-ssa-structalias.c
===================================================================
--- trunk.orig/gcc/tree-ssa-structalias.c 2008-06-27 14:32:22.000000000 +0200
+++ trunk/gcc/tree-ssa-structalias.c 2008-06-27 14:24:27.000000000 +0200
@@ -262,6 +262,7 @@ struct variable_info
typedef struct variable_info *varinfo_t;
static varinfo_t first_vi_for_offset (varinfo_t, unsigned HOST_WIDE_INT);
+static varinfo_t lookup_vi_for_tree (tree);
/* Pool of variable info structures. */
static alloc_pool variable_info_pool;
@@ -1114,7 +1115,18 @@ build_succ_graph (void)
/* x = &y */
gcc_assert (find (get_varinfo_fc (rhs.var)->id)
== get_varinfo_fc (rhs.var)->id);
- bitmap_set_bit (get_varinfo (lhsvar)->solution, rhsvar);
+ if (lhs.var == escaped_id)
+ {
+ /* We might want to simply collapse the rhs variable at this
+ point.
+ ??? This would need to happen at the point we generate
+ the constraint. */
+ varinfo_t vi = lookup_vi_for_tree (get_varinfo_fc (rhs.var)->decl);
+ for (; vi != NULL; vi = vi->next)
+ bitmap_set_bit (get_varinfo (lhsvar)->solution, vi->id);
+ }
+ else
+ bitmap_set_bit (get_varinfo (lhsvar)->solution, rhsvar);
}
else if (lhsvar > anything_id
&& lhsvar != rhsvar && lhs.offset == 0 && rhs.offset == 0)
@@ -1400,13 +1412,45 @@ do_sd_constraint (constraint_graph_t gra
unsigned int j;
bitmap_iterator bi;
- if (bitmap_bit_p (delta, anything_id))
- {
- flag = !bitmap_bit_p (sol, anything_id);
- if (flag)
- bitmap_set_bit (sol, anything_id);
- goto done;
- }
+ if (bitmap_bit_p (delta, anything_id))
+ {
+ flag = !bitmap_bit_p (sol, anything_id);
+ if (flag)
+ bitmap_set_bit (sol, anything_id);
+ goto done;
+ }
+
+ /* For x = *ESCAPED we interpret the deref as dereferencing all fields
+ of the ESCAPED solution variables.
+ ??? The question is if this works reliably if subvars are
+ collapsed. We might not see the original variable in delta and thus
+ not reach other fields. */
+ if (c->rhs.var == escaped_id)
+ {
+ EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
+ {
+ varinfo_t v = lookup_vi_for_tree (get_varinfo (j)->decl);
+
+ /* Only process one field as representative. */
+ if (v != get_varinfo (j)
+ && bitmap_bit_p (delta, v->id))
+ continue;
+
+ for (; v != NULL; v = v->next)
+ {
+ unsigned int t = find (v->id);
+
+ /* Adding edges from the special vars is pointless.
+ They don't have sets that can change. */
+ if (get_varinfo (t)->is_special_var)
+ flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
+ else if (add_graph_edge (graph, lhs, t))
+ flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
+ }
+ }
+ goto done;
+ }
+
/* For each variable j in delta (Sol(y)), add
an edge in the graph from j to x, and union Sol(j) into Sol(x). */
EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
@@ -1564,6 +1608,30 @@ do_complex_constraint (constraint_graph_
}
}
+static bool
+set_union_all_fields (bitmap tmp, bitmap pts)
+{
+ bitmap_iterator bi;
+ unsigned i;
+ bool flag = false;
+
+ /* For each variable in pts add all its decls variables to tmp. */
+ EXECUTE_IF_SET_IN_BITMAP (pts, 0, i, bi)
+ {
+ varinfo_t vi = lookup_vi_for_tree (get_varinfo (i)->decl);
+ if (vi != get_varinfo (i)
+ && bitmap_bit_p (pts, vi->id))
+ continue;
+ for (; vi != NULL; vi = vi->next)
+ {
+ flag |= bitmap_bit_p (tmp, vi->id);
+ bitmap_set_bit (tmp, vi->id);
+ }
+ }
+
+ return flag;
+}
+
/* Initialize and return a new SCC info structure. */
static struct scc_info *
@@ -2378,7 +2446,12 @@ solve_graph (constraint_graph_t graph)
if (to == i)
continue;
- flag = set_union_with_increment (tmp, pts, 0);
+ /* If this is a copy to the reachability set
+ ESCAPED, process it specially. */
+ if (to == escaped_id)
+ flag = set_union_all_fields (tmp, pts);
+ else
+ flag = set_union_with_increment (tmp, pts, 0);
if (flag)
{
More information about the Gcc-patches
mailing list