diff mbox

[PR62167] Fix tail-merge pass for dead type-unsafe code

Message ID 546B7A81.6030508@mentor.com
State New
Headers show

Commit Message

Tom de Vries Nov. 18, 2014, 4:57 p.m. UTC
Richard,

this (trunk) patch fixes PR62167.

The patch fixes a problem that triggers with the test-case on the 4.8 branch, 
when tail-merge makes a dead type-unsafe load alive.

I'm not able to reproduce this bug on 4.9 and trunk with the same test-case. On 
those branches, the tail-merge already does not happen.

The reason for the difference is as follows: With 4.8 the two phi arguments of 
the phi in the tail block are value-numbered identically:
...
SCC consists of: p_14
Value numbering p_14 stmt = p_14 = MEM[(struct head *)_13].first;
Setting value number of p_14 to p_14 (changed)

SCC consists of: p_15
Value numbering p_15 stmt = p_15 = _13->next;
Setting value number of p_15 to p_14 (changed)
...

With 4.9 (and trunk), that's not the case:
...
SCC consists of: p_14
Value numbering p_14 stmt = p_14 = MEM[(struct head *)&heads][k.1_9].first;
Setting value number of p_14 to p_14 (changed)

SCC consists of: p_15
Value numbering p_15 stmt = p_15 = _13->next;
Setting value number of p_15 to p_15 (changed)
...

I'm not sure the bug triggers on trunk and 4.9, but I see no reason why it could 
not trigger, so I'd prefer to apply the patch to 4.9 and trunk as well.

The patch introduces an xfail for pr51879-12.c. I can follow up with a patch to 
improve upon that, but I think that's better limited to trunk only.

Bootstrapped and reg-tested on x86_64/trunk.

OK for trunk/stage3, 4.8, 4.9?

Thanks,
- Tom

Comments

Jeff Law Nov. 18, 2014, 10:53 p.m. UTC | #1
On 11/18/14 09:57, Tom de Vries wrote:
> Richard,
>
> this (trunk) patch fixes PR62167.
>
> The patch fixes a problem that triggers with the test-case on the 4.8
> branch, when tail-merge makes a dead type-unsafe load alive.
>
> I'm not able to reproduce this bug on 4.9 and trunk with the same
> test-case. On those branches, the tail-merge already does not happen.
>
> The reason for the difference is as follows: With 4.8 the two phi
> arguments of the phi in the tail block are value-numbered identically:
> ...
> SCC consists of: p_14
> Value numbering p_14 stmt = p_14 = MEM[(struct head *)_13].first;
> Setting value number of p_14 to p_14 (changed)
>
> SCC consists of: p_15
> Value numbering p_15 stmt = p_15 = _13->next;
> Setting value number of p_15 to p_14 (changed)
> ...
>
> With 4.9 (and trunk), that's not the case:
> ...
> SCC consists of: p_14
> Value numbering p_14 stmt = p_14 = MEM[(struct head *)&heads][k.1_9].first;
> Setting value number of p_14 to p_14 (changed)
>
> SCC consists of: p_15
> Value numbering p_15 stmt = p_15 = _13->next;
> Setting value number of p_15 to p_15 (changed)
> ...
>
> I'm not sure the bug triggers on trunk and 4.9, but I see no reason why
> it could not trigger, so I'd prefer to apply the patch to 4.9 and trunk
> as well.
>
> The patch introduces an xfail for pr51879-12.c. I can follow up with a
> patch to improve upon that, but I think that's better limited to trunk
> only.
>
> Bootstrapped and reg-tested on x86_64/trunk.
So instead of simply disabling for anything with virtual operands, 
shouldn't instead we be comparing the virtual operands and alias 
information?  Seems to me that if we did that properly, this would "just 
work".  Right?


jeff
Richard Biener Nov. 19, 2014, 8:48 a.m. UTC | #2
On Tue, 18 Nov 2014, Tom de Vries wrote:

> Richard,
> 
> this (trunk) patch fixes PR62167.
> 
> The patch fixes a problem that triggers with the test-case on the 4.8 branch,
> when tail-merge makes a dead type-unsafe load alive.
> 
> I'm not able to reproduce this bug on 4.9 and trunk with the same test-case.
> On those branches, the tail-merge already does not happen.
> 
> The reason for the difference is as follows: With 4.8 the two phi arguments of
> the phi in the tail block are value-numbered identically:
> ...
> SCC consists of: p_14
> Value numbering p_14 stmt = p_14 = MEM[(struct head *)_13].first;
> Setting value number of p_14 to p_14 (changed)
> 
> SCC consists of: p_15
> Value numbering p_15 stmt = p_15 = _13->next;
> Setting value number of p_15 to p_14 (changed)
> ...
> 
> With 4.9 (and trunk), that's not the case:
> ...
> SCC consists of: p_14
> Value numbering p_14 stmt = p_14 = MEM[(struct head *)&heads][k.1_9].first;
> Setting value number of p_14 to p_14 (changed)
> 
> SCC consists of: p_15
> Value numbering p_15 stmt = p_15 = _13->next;
> Setting value number of p_15 to p_15 (changed)
> ...
> 
> I'm not sure the bug triggers on trunk and 4.9, but I see no reason why it
> could not trigger, so I'd prefer to apply the patch to 4.9 and trunk as well.
> 
> The patch introduces an xfail for pr51879-12.c. I can follow up with a patch
> to improve upon that, but I think that's better limited to trunk only.

Yeah.

> Bootstrapped and reg-tested on x86_64/trunk.
> 
> OK for trunk/stage3, 4.8, 4.9?

Ok.  Note that this goes well with disabling the (re-)use of 
value-numbering in tail-merging (which causes me quite some headaches...).
On trunk it shouldn't be necessary as much as it was earlier as we now
fully propagate constants and copies during FRE/PRE elimination.

Thanks,
Richard.
Richard Biener Nov. 19, 2014, 9:34 a.m. UTC | #3
On Tue, 18 Nov 2014, Jeff Law wrote:

> On 11/18/14 09:57, Tom de Vries wrote:
> > Richard,
> > 
> > this (trunk) patch fixes PR62167.
> > 
> > The patch fixes a problem that triggers with the test-case on the 4.8
> > branch, when tail-merge makes a dead type-unsafe load alive.
> > 
> > I'm not able to reproduce this bug on 4.9 and trunk with the same
> > test-case. On those branches, the tail-merge already does not happen.
> > 
> > The reason for the difference is as follows: With 4.8 the two phi
> > arguments of the phi in the tail block are value-numbered identically:
> > ...
> > SCC consists of: p_14
> > Value numbering p_14 stmt = p_14 = MEM[(struct head *)_13].first;
> > Setting value number of p_14 to p_14 (changed)
> > 
> > SCC consists of: p_15
> > Value numbering p_15 stmt = p_15 = _13->next;
> > Setting value number of p_15 to p_14 (changed)
> > ...
> > 
> > With 4.9 (and trunk), that's not the case:
> > ...
> > SCC consists of: p_14
> > Value numbering p_14 stmt = p_14 = MEM[(struct head *)&heads][k.1_9].first;
> > Setting value number of p_14 to p_14 (changed)
> > 
> > SCC consists of: p_15
> > Value numbering p_15 stmt = p_15 = _13->next;
> > Setting value number of p_15 to p_15 (changed)
> > ...
> > 
> > I'm not sure the bug triggers on trunk and 4.9, but I see no reason why
> > it could not trigger, so I'd prefer to apply the patch to 4.9 and trunk
> > as well.
> > 
> > The patch introduces an xfail for pr51879-12.c. I can follow up with a
> > patch to improve upon that, but I think that's better limited to trunk
> > only.
> > 
> > Bootstrapped and reg-tested on x86_64/trunk.
> So instead of simply disabling for anything with virtual operands, shouldn't
> instead we be comparing the virtual operands and alias information?  Seems to
> me that if we did that properly, this would "just work".  Right?

But that would simply use operand_equal_p () ....

Richard.
diff mbox

Patch

2014-11-17  Tom de Vries  <tom@codesourcery.com>

	PR tree-optimization/62167
	* tree-ssa-tail-merge.c (stmt_local_def): Handle statements with vuse
	conservatively.
	(gimple_equal_p): Don't use vn_valueize to compare for lhs equality of
	assigns.

	* gcc.dg/pr51879-12.c: Add xfails.
	* gcc.dg/pr62167-run.c: New test.
	* gcc.dg/pr62167.c: New test.
---
 gcc/testsuite/gcc.dg/pr51879-12.c  |  4 +--
 gcc/testsuite/gcc.dg/pr62167-run.c | 47 +++++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/pr62167.c     | 50 ++++++++++++++++++++++++++++++++++++++
 gcc/tree-ssa-tail-merge.c          |  6 +++--
 4 files changed, 103 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr62167-run.c
 create mode 100644 gcc/testsuite/gcc.dg/pr62167.c

diff --git a/gcc/testsuite/gcc.dg/pr51879-12.c b/gcc/testsuite/gcc.dg/pr51879-12.c
index 8126505..85e2687 100644
--- a/gcc/testsuite/gcc.dg/pr51879-12.c
+++ b/gcc/testsuite/gcc.dg/pr51879-12.c
@@ -24,6 +24,6 @@  foo (int y)
   baz (a);
 }
 
-/* { dg-final { scan-tree-dump-times "bar \\(" 1 "pre"} } */
-/* { dg-final { scan-tree-dump-times "bar2 \\(" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-times "bar \\(" 1 "pre" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "bar2 \\(" 1 "pre" { xfail *-*-* } } } */
 /* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/pr62167-run.c b/gcc/testsuite/gcc.dg/pr62167-run.c
new file mode 100644
index 0000000..37214a3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr62167-run.c
@@ -0,0 +1,47 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-tail-merge" } */
+
+struct node
+{
+  struct node *next;
+  struct node *prev;
+};
+
+struct node node;
+
+struct head
+{
+  struct node *first;
+};
+
+struct head heads[5];
+
+int k = 2;
+
+struct head *head = &heads[2];
+
+int
+main ()
+{
+  struct node *p;
+
+  node.next = (void*)0;
+
+  node.prev = (void *)head;
+
+  head->first = &node;
+
+  struct node *n = head->first;
+
+  struct head *h = &heads[k];
+
+  heads[2].first = n->next;
+
+  if ((void*)n->prev == (void *)h)
+    p = h->first;
+  else
+    /* Dead tbaa-unsafe load from ((struct node *)&heads[2])->next.  */
+    p = n->prev->next;
+
+  return !(p == (void*)0);
+}
diff --git a/gcc/testsuite/gcc.dg/pr62167.c b/gcc/testsuite/gcc.dg/pr62167.c
new file mode 100644
index 0000000..f8c31a0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr62167.c
@@ -0,0 +1,50 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-tail-merge -fdump-tree-pre" } */
+
+struct node
+{
+  struct node *next;
+  struct node *prev;
+};
+
+struct node node;
+
+struct head
+{
+  struct node *first;
+};
+
+struct head heads[5];
+
+int k = 2;
+
+struct head *head = &heads[2];
+
+int
+main ()
+{
+  struct node *p;
+
+  node.next = (void*)0;
+
+  node.prev = (void *)head;
+
+  head->first = &node;
+
+  struct node *n = head->first;
+
+  struct head *h = &heads[k];
+
+  heads[2].first = n->next;
+
+  if ((void*)n->prev == (void *)h)
+    p = h->first;
+  else
+    /* Dead tbaa-unsafe load from ((struct node *)&heads[2])->next.  */
+    p = n->prev->next;
+
+  return !(p == (void*)0);
+}
+
+/* { dg-final { scan-tree-dump-not "Removing basic block" "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 303bd5e..1651985 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -326,7 +326,8 @@  stmt_local_def (gimple stmt)
 
   if (gimple_vdef (stmt) != NULL_TREE
       || gimple_has_side_effects (stmt)
-      || gimple_could_trap_p_1 (stmt, false, false))
+      || gimple_could_trap_p_1 (stmt, false, false)
+      || gimple_vuse (stmt) != NULL_TREE)
     return false;
 
   def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
@@ -1175,7 +1176,8 @@  gimple_equal_p (same_succ same_succ, gimple s1, gimple s2)
 						 gimple_assign_rhs1 (s2)));
       else if (TREE_CODE (lhs1) == SSA_NAME
 	       && TREE_CODE (lhs2) == SSA_NAME)
-	return vn_valueize (lhs1) == vn_valueize (lhs2);
+	return operand_equal_p (gimple_assign_rhs1 (s1),
+				gimple_assign_rhs1 (s2), 0);
       return false;
 
     case GIMPLE_COND:
-- 
1.9.1