On Tue, 17 Jan 2012, Jakub Jelinek wrote: > Hi! > > We tail merge > a = bar (7); > with > *x = bar (7); > completely ignoring the case that the lhs are different. > IMHO we can't merge if one of the calls has lhs and the other doesn't, > or if both calls have non-SSA_NAME lhs and they aren't equal (this case). > If both calls have SSA_NAME lhs, I can see why it might be nice to tail > merge both if the calls have the same argument same destination even when > the lhs don't valueize the same (sccvn will value number the same just > pure/const calls, right), but I don't see how it can actually work, > the SSA_NAMEs will be used somewhere later on in the BB or in the PHI, > and there we compare vn_valueize anyway. We'd need to somehow mark > those two SSA_NAMEs as equivalent for further VN. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. Thanks, Richard. > 2012-01-17 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/51877 > * tree-ssa-tail-merge.c (gimple_equal_p): Don't return true whenever > call arguments and fndecls compare equal, instead return false if they > don't. Return true only if lhs1 and lhs2 are either both NULL, or > both SSA_NAMEs that are valueized the same, or they satisfy > operand_equal_p. > > * gcc.c-torture/execute/pr51877.c: New test. > > --- gcc/tree-ssa-tail-merge.c.jj 2011-12-12 22:10:26.000000000 +0100 > +++ gcc/tree-ssa-tail-merge.c 2012-01-17 08:28:56.903471558 +0100 > @@ -1071,14 +1071,18 @@ gimple_equal_p (same_succ same_succ, gim > equal = false; > break; > } > - if (equal) > - return true; > + if (!equal) > + return false; > > lhs1 = gimple_get_lhs (s1); > lhs2 = gimple_get_lhs (s2); > - return (lhs1 != NULL_TREE && lhs2 != NULL_TREE > - && TREE_CODE (lhs1) == SSA_NAME && TREE_CODE (lhs2) == SSA_NAME > - && vn_valueize (lhs1) == vn_valueize (lhs2)); > + if (lhs1 == NULL_TREE && lhs2 == NULL_TREE) > + return true; > + if (lhs1 == NULL_TREE || lhs2 == NULL_TREE) > + return false; > + if (TREE_CODE (lhs1) == SSA_NAME && TREE_CODE (lhs2) == SSA_NAME) > + return vn_valueize (lhs1) == vn_valueize (lhs2); > + return operand_equal_p (lhs1, lhs2, 0); > > case GIMPLE_ASSIGN: > lhs1 = gimple_get_lhs (s1); > --- gcc/testsuite/gcc.c-torture/execute/pr51877.c.jj 2012-01-17 > 08:36:31.012781551 +0100 > +++ gcc/testsuite/gcc.c-torture/execute/pr51877.c 2012-01-17 > 08:35:26.000000000 +0100 > @@ -0,0 +1,50 @@ > +/* PR tree-optimization/51877 */ > + > +extern void abort (void); > +struct A { int a; char b[32]; } a, b; > + > +__attribute__((noinline, noclone)) > +struct A > +bar (int x) > +{ > + struct A r; > + static int n; > + r.a = ++n; > + __builtin_memset (r.b, 0, sizeof (r.b)); > + r.b[0] = x; > + return r; > +} > + > +__attribute__((noinline, noclone)) > +void > +baz (void) > +{ > + asm volatile ("" : : : "memory"); > +} > + > +__attribute__((noinline, noclone)) > +void > +foo (struct A *x, int y) > +{ > + if (y == 6) > + a = bar (7); > + else > + *x = bar (7); > + baz (); > +} > + > +int > +main () > +{ > + a = bar (3); > + b = bar (4); > + if (a.a != 1 || a.b[0] != 3 || b.a != 2 || b.b[0] != 4) > + abort (); > + foo (&b, 0); > + if (a.a != 1 || a.b[0] != 3 || b.a != 3 || b.b[0] != 7) > + abort (); > + foo (&b, 6); > + if (a.a != 4 || a.b[0] != 7 || b.a != 3 || b.b[0] != 7) > + abort (); > + return 0; > +} > > Jakub > > -- Richard Guenther <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer