diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2687d4e6de1..810590c5e13 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2010-11-26 Richard Guenther + + PR lto/46648 + * gimple.c (gtc_visit): Do not return true for members of an + SCC still being processed but the current lattice value of + the member. Treat SCC members comparison state as lattice, + starting at equal, eventually dropping to unequal. + (gimple_types_compatible_p_1): Likewise. + 2010-11-26 Richard Guenther PR middle-end/46559 diff --git a/gcc/gimple.c b/gcc/gimple.c index 851e30ffbda..67c80e327c3 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -3515,27 +3515,23 @@ gtc_visit (tree t1, tree t2, enum gtc_mode mode, if ((slot = pointer_map_contains (sccstate, p)) != NULL) cstate = (struct sccs *)*slot; + /* Not yet visited. DFS recurse. */ if (!cstate) { - bool res; - /* Not yet visited. DFS recurse. */ - res = gimple_types_compatible_p_1 (t1, t2, mode, p, - sccstack, sccstate, sccstate_obstack); - if (!cstate) - cstate = (struct sccs *)* pointer_map_contains (sccstate, p); + gimple_types_compatible_p_1 (t1, t2, mode, p, + sccstack, sccstate, sccstate_obstack); + cstate = (struct sccs *)* pointer_map_contains (sccstate, p); state->low = MIN (state->low, cstate->low); - /* If the type is no longer on the SCC stack and thus is not part - of the parents SCC, return its state. Otherwise we will - ignore this pair and assume equality. */ - if (!cstate->on_sccstack) - return res; } + /* If the type is still on the SCC stack adjust the parents low. */ if (cstate->dfsnum < state->dfsnum && cstate->on_sccstack) state->low = MIN (cstate->dfsnum, state->low); - /* We are part of our parents SCC, skip this entry and return true. */ - return true; + /* Return the current lattice value. We start with an equality + assumption so types part of a SCC will be optimistically + treated equal unless proven otherwise. */ + return cstate->u.same_p; } /* Worker for gimple_types_compatible. @@ -3559,6 +3555,9 @@ gimple_types_compatible_p_1 (tree t1, tree t2, enum gtc_mode mode, state->dfsnum = gtc_next_dfs_num++; state->low = state->dfsnum; state->on_sccstack = true; + /* Start with an equality assumption. As we DFS recurse into child + SCCs this assumption may get revisited. */ + state->u.same_p = 1; /* If their attributes are not the same they can't be the same type. */ if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2))) @@ -3822,22 +3821,22 @@ different_types: /* Common exit path for types that are compatible. */ same_types: - state->u.same_p = 1; - goto pop; + gcc_assert (state->u.same_p == 1); pop: if (state->low == state->dfsnum) { type_pair_t x; - /* Pop off the SCC and set its cache values. */ + /* Pop off the SCC and set its cache values to the final + comparison result. */ do { struct sccs *cstate; x = VEC_pop (type_pair_t, *sccstack); cstate = (struct sccs *)*pointer_map_contains (sccstate, x); cstate->on_sccstack = false; - x->same_p[mode] = cstate->u.same_p; + x->same_p[mode] = state->u.same_p; } while (x != p); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 57a7b42cb39..80706c08d1d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2010-11-26 Richard Guenther + + PR lto/46648 + * gcc.dg/lto/20101125-1_0.c: New testcase. + * gcc.dg/lto/20101125-1_1.c: Likewise. + 2010-11-22 Bud Davis * arith_divide_no_check.f diff --git a/gcc/testsuite/gcc.dg/lto/20101125-1_0.c b/gcc/testsuite/gcc.dg/lto/20101125-1_0.c new file mode 100644 index 00000000000..662dd243dc7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/20101125-1_0.c @@ -0,0 +1,24 @@ +/* { dg-lto-do link } */ + +struct X { + int i; +}; + +struct W { + struct U *p; + struct X *q; +}; + +struct U { + struct W a[1]; +}; + +void foo(struct U *ptr) +{ + ptr->a[0].p = 0; +} + +int main(void) +{ + return 0; +} diff --git a/gcc/testsuite/gcc.dg/lto/20101125-1_1.c b/gcc/testsuite/gcc.dg/lto/20101125-1_1.c new file mode 100644 index 00000000000..2924e3f26be --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/20101125-1_1.c @@ -0,0 +1,17 @@ +struct X { + char i; +}; + +struct W { + struct U *p; + struct X *q; +}; + +struct U { + struct W a[1]; +}; + +void bar(struct U *ptr) +{ + ptr->a[0].p = 0; +}