diff mbox

[PR81192] Don't tail-merge blocks from different loops

Message ID c886dba1-c509-2066-4171-1b7d84c8d53b@mentor.com
State New
Headers show

Commit Message

Tom de Vries July 2, 2017, 10:49 p.m. UTC
[ was: Re: [PATCH, PR81192] Fix sigsegv in find_same_succ_bb ]

On 07/03/2017 12:26 AM, Tom de Vries wrote:
> [ Trying again with before.svg instead of before.pdf ]
> 
> Hi,
> 
> consider this test-case:
> ...
> unsigned a;
> int b, c;
> 
> static int
> fn1 (int p1, int p2)
> {
>    return p1 > 2147483647 - p2 ? p1 : p1 + p2;
> }
> 
> void
> fn2 (void)
> {
>    int j;
>    a = 30;
>    for (; a;)
>      for (; c; b = fn1 (j, 1))
>        ;
> }
> ...
> 
> When compiling the test-case with -Os, just before tail-merge it looks 
> as in before.svg.
> 
> During tail-merge, it runs into a sigsegv.
> 
> What happens is the following:
> - tail-merge decides to merge blocks 4 and 6, and removes block 6.

As pointed out in the PR, blocks 4 and 6 belong to different loops, and 
shouldn't be merged.

There is a test 'bb->loop_father->latch == bb' in find_same_succ_bb that 
is supposed to keep the two blocks from merging, but the test is not 
working for this example because the latch field is not defined (because 
the loop has in fact two latches).

This patch prevents blocks from different loops to be merged by testing 
for bb->loop_father->num equivalence in tail-merge.

It also removes the unreliable test for 'bb->loop_father->latch == bb' 
in find_same_succ_bb.

Bootstrapped and reg-tested on x86_64.

OK for trunk and gcc-[567]-branch?

Thanks,
- Tom

Comments

Richard Biener July 3, 2017, 7:01 a.m. UTC | #1
On Mon, 3 Jul 2017, Tom de Vries wrote:

> [ was: Re: [PATCH, PR81192] Fix sigsegv in find_same_succ_bb ]
> 
> On 07/03/2017 12:26 AM, Tom de Vries wrote:
> > [ Trying again with before.svg instead of before.pdf ]
> > 
> > Hi,
> > 
> > consider this test-case:
> > ...
> > unsigned a;
> > int b, c;
> > 
> > static int
> > fn1 (int p1, int p2)
> > {
> >    return p1 > 2147483647 - p2 ? p1 : p1 + p2;
> > }
> > 
> > void
> > fn2 (void)
> > {
> >    int j;
> >    a = 30;
> >    for (; a;)
> >      for (; c; b = fn1 (j, 1))
> >        ;
> > }
> > ...
> > 
> > When compiling the test-case with -Os, just before tail-merge it looks as in
> > before.svg.
> > 
> > During tail-merge, it runs into a sigsegv.
> > 
> > What happens is the following:
> > - tail-merge decides to merge blocks 4 and 6, and removes block 6.
> 
> As pointed out in the PR, blocks 4 and 6 belong to different loops, and
> shouldn't be merged.
> 
> There is a test 'bb->loop_father->latch == bb' in find_same_succ_bb that is
> supposed to keep the two blocks from merging, but the test is not working for
> this example because the latch field is not defined (because the loop has in
> fact two latches).
> 
> This patch prevents blocks from different loops to be merged by testing for
> bb->loop_father->num equivalence in tail-merge.

You can compare bb->loop_father directly.

> It also removes the unreliable test for 'bb->loop_father->latch == bb' in
> find_same_succ_bb.
> 
> Bootstrapped and reg-tested on x86_64.
> 
> OK for trunk and gcc-[567]-branch?

Ok for trunk with the above change, as we do not have any wrong-code/ICE
testcase that fails on branches I'd not backport this.  Maybe to the
GCC 7 branch but certainly not farther.

Thanks,
Richard.

> Thanks,
> - Tom
> 
>
diff mbox

Patch

Don't tail-merge blocks from different loops

2017-06-30  Tom de Vries  <tom@codesourcery.com>

	PR tree-optimization/81192
	* tree-ssa-tail-merge.c (same_succ_hash): Use bb->loop_father->num in
	hash.
	(same_succ::equal): Don't find bbs to be equal if bb->loop_father->num
	differs.
	(find_same_succ_bb): Remove obsolete test on bb->loop_father->latch.

	* gcc.dg/pr81192.c: Update.

---
 gcc/testsuite/gcc.dg/pr81192.c |  2 +-
 gcc/tree-ssa-tail-merge.c      | 15 ++++++---------
 2 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/pr81192.c b/gcc/testsuite/gcc.dg/pr81192.c
index 57eb478..8b3a77a 100644
--- a/gcc/testsuite/gcc.dg/pr81192.c
+++ b/gcc/testsuite/gcc.dg/pr81192.c
@@ -19,4 +19,4 @@  fn2 (void)
       ;
 }
 
-/* { dg-final { scan-tree-dump-times "(?n)find_duplicates: <bb .*> duplicate of <bb .*>" 1 "pre" } } */
+/* { dg-final { scan-tree-dump-not "(?n)find_duplicates: <bb .*> duplicate of <bb .*>" "pre" } } */
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index bb8a308..0865e86 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -479,6 +479,8 @@  same_succ_hash (const same_succ *e)
   hstate.add_int (size);
   BB_SIZE (bb) = size;
 
+  hstate.add_int (bb->loop_father->num);
+
   for (i = 0; i < e->succ_flags.length (); ++i)
     {
       flags = e->succ_flags[i];
@@ -568,6 +570,9 @@  same_succ::equal (const same_succ *e1, const same_succ *e2)
   if (BB_SIZE (bb1) != BB_SIZE (bb2))
     return 0;
 
+  if (bb1->loop_father->num != bb2->loop_father->num)
+    return 0;
+
   gsi1 = gsi_start_nondebug_bb (bb1);
   gsi2 = gsi_start_nondebug_bb (bb2);
   gsi_advance_fw_nondebug_nonlocal (&gsi1);
@@ -695,15 +700,7 @@  find_same_succ_bb (basic_block bb, same_succ **same_p)
   edge_iterator ei;
   edge e;
 
-  if (bb == NULL
-      /* Be conservative with loop structure.  It's not evident that this test
-	 is sufficient.  Before tail-merge, we've just called
-	 loop_optimizer_finalize, and LOOPS_MAY_HAVE_MULTIPLE_LATCHES is now
-	 set, so there's no guarantee that the loop->latch value is still valid.
-	 But we assume that, since we've forced LOOPS_HAVE_SIMPLE_LATCHES at the
-	 start of pre, we've kept that property intact throughout pre, and are
-	 keeping it throughout tail-merge using this test.  */
-      || bb->loop_father->latch == bb)
+  if (bb == NULL)
     return;
   bitmap_set_bit (same->bbs, bb->index);
   FOR_EACH_EDGE (e, ei, bb->succs)