[ was: Re: [PATCH, PR81192] Don't tail-merge blocks from different loops ]
On 07/03/2017 12:49 AM, 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.
While working on this PR, I used print_graph_cfg in tail-merge, which I
noticed changes the choice in merging blocks. I tracked this down to:
- mark_dfs_back_edges changing the EDGE_DFS_BACK flag on some edges, and
- tail-merge requiring identical edge flags (apart from the true/false
flags, which are dealt with explicitly).
This is similar to PR69468 which notices the same about EDGE_EXECUTABLE.
This patch allows more tail-merging by ignoring both EDGE_DFS_BACK and
EDGE_EXECUTABLE. Consequently, in this example the two latch bbs (of the
same loop) bb4 and bb7 are merged.
Bootstrapped and reg-tested on x86_64.
OK for trunk?
Thanks,
- Tom
Ignore EDGE_{DFS_BACK,EXECUTABLE} in tail-merge
2017-06-30 Tom de Vries <t...@codesourcery.com>
PR tree-optimization/69468
* tree-ssa-tail-merge.c (ignore_edge_flags): New constant.
(find_same_succ_bb): Handle ignore_edge_flags.
* gcc.dg/pr81192.c: Update.
---
gcc/testsuite/gcc.dg/pr81192.c | 2 +-
gcc/tree-ssa-tail-merge.c | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/gcc/testsuite/gcc.dg/pr81192.c b/gcc/testsuite/gcc.dg/pr81192.c
index 8b3a77a..57eb478 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-not "(?n)find_duplicates: <bb .*> duplicate of <bb .*>" "pre" } } */
+/* { dg-final { scan-tree-dump-times "(?n)find_duplicates: <bb .*> duplicate of <bb .*>" 1 "pre" } } */
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 0865e86..6f199de 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -207,6 +207,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-eh.h"
#include "tree-cfgcleanup.h"
+const int ignore_edge_flags = EDGE_DFS_BACK | EDGE_EXECUTABLE;
+
/* Describes a group of bbs with the same successors. The successor bbs are
cached in succs, and the successor edge flags are cached in succ_flags.
If a bb has the EDGE_TRUE/FALSE_VALUE flags swapped compared to succ_flags,
@@ -707,7 +709,7 @@ find_same_succ_bb (basic_block bb, same_succ **same_p)
{
int index = e->dest->index;
bitmap_set_bit (same->succs, index);
- same_succ_edge_flags[index] = e->flags;
+ same_succ_edge_flags[index] = (e->flags & ~ignore_edge_flags);
}
EXECUTE_IF_SET_IN_BITMAP (same->succs, 0, j, bj)
same->succ_flags.safe_push (same_succ_edge_flags[j]);