Commit 7d7e7aca by Jeff Law Committed by Jeff Law

[PATCH][PR tree-optimization/68198] Avoid CFG explosion due to threading

	PR tree-optimization/68198
	* tree-ssa-threadupdate.c (valid_jump_thread_path): Distinguish
	between threading a multi-way branch and a thread path that contains
	a multi-way branch.  Disallow the case where a path contains a
	multi-way branch and does not thread a multi-way branch.
	(thread_through_all_blocks): Update comment.

        PR tree-optimization/68198
	* gcc.dg/tree-ssa/pr66752-3.c: Update expected output for VRP1.
	* gcc.dg/tree-ssa/pr68198.c: New test.

From-SVN: r230586
parent 3ebf5a30
2015-11-18 Jeff Law <law@redhat.com>
PR tree-optimization/68198
* tree-ssa-threadupdate.c (valid_jump_thread_path): Distinguish
between threading a multi-way branch and a thread path that contains
a multi-way branch. Disallow the case where a path contains a
multi-way branch and does not thread a multi-way branch.
(thread_through_all_blocks): Update comment.
2015-11-18 Joseph Myers <joseph@codesourcery.com> 2015-11-18 Joseph Myers <joseph@codesourcery.com>
PR c/65083 PR c/65083
2015-11-18 Jeff Law <law@redhat.com>
PR tree-optimization/68198
* gcc.dg/tree-ssa/pr66752-3.c: Update expected output for VRP1.
* gcc.dg/tree-ssa/pr68198.c: New test.
2015-11-18 Steven G. Kargl <kargl@gcc.gnu.org> 2015-11-18 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/59910 PR fortran/59910
......
...@@ -32,8 +32,10 @@ foo (int N, int c, int b, int *a) ...@@ -32,8 +32,10 @@ foo (int N, int c, int b, int *a)
pt--; pt--;
} }
/* There are 3 FSM jump threading opportunities. */ /* There are 3 FSM jump threading opportunities, one of which will
/* { dg-final { scan-tree-dump-times "FSM" 3 "vrp1"} } */ get cancelled. */
/* { dg-final { scan-tree-dump-times "Registering FSM" 3 "vrp1"} } */
/* { dg-final { scan-tree-dump-times "Cancelling FSM" 1 "vrp1"} } */
/* There should be no assignments or references to FLAG. */ /* There should be no assignments or references to FLAG. */
/* { dg-final { scan-tree-dump-not "flag" "optimized"} } */ /* { dg-final { scan-tree-dump-not "flag" "optimized"} } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
extern void abort (void);
typedef union tree_node *tree;
union tree_node
{
int code;
tree chain;
int omp_code;
}
bitmap_head;
extern int c_omp_predetermined_sharing (tree);
tree
c_finish_omp_clauses (tree clauses)
{
tree c, t, *pc = &clauses;
for (pc = &clauses, c = clauses; c; c = *pc)
{
unsigned char remove = 0;
switch (((c->omp_code)))
{
case 1:
if (t->code != 42)
remove = 1;
switch (c_omp_predetermined_sharing (t))
{
case 2:
abort ();
}
}
if (remove)
*pc = c->chain;
}
}
/* There are 3 FSM jump threading opportunities, two of which will
get cancelled. */
/* { dg-final { scan-tree-dump-times "Registering FSM" 3 "vrp1"} } */
/* { dg-final { scan-tree-dump-times "Cancelling FSM" 2 "vrp1"} } */
...@@ -2370,11 +2370,13 @@ static bool ...@@ -2370,11 +2370,13 @@ static bool
valid_jump_thread_path (vec<jump_thread_edge *> *path) valid_jump_thread_path (vec<jump_thread_edge *> *path)
{ {
unsigned len = path->length (); unsigned len = path->length ();
bool multiway_branch = false; bool threaded_multiway_branch = false;
bool multiway_branch_in_path = false;
bool threaded_through_latch = false; bool threaded_through_latch = false;
/* Check that the path is connected and see if there's a multi-way /* Check that the path is connected and see if there's a multi-way
branch on the path. */ branch on the path and whether or not a multi-way branch
is threaded. */
for (unsigned int j = 0; j < len - 1; j++) for (unsigned int j = 0; j < len - 1; j++)
{ {
edge e = (*path)[j]->e; edge e = (*path)[j]->e;
...@@ -2394,7 +2396,12 @@ valid_jump_thread_path (vec<jump_thread_edge *> *path) ...@@ -2394,7 +2396,12 @@ valid_jump_thread_path (vec<jump_thread_edge *> *path)
threaded_through_latch = true; threaded_through_latch = true;
gimple *last = last_stmt (e->dest); gimple *last = last_stmt (e->dest);
multiway_branch |= (last && gimple_code (last) == GIMPLE_SWITCH); if (j == len - 2)
threaded_multiway_branch
|= (last && gimple_code (last) == GIMPLE_SWITCH);
else
multiway_branch_in_path
|= (last && gimple_code (last) == GIMPLE_SWITCH);
} }
/* If we are trying to thread through the loop latch to a block in the /* If we are trying to thread through the loop latch to a block in the
...@@ -2402,8 +2409,33 @@ valid_jump_thread_path (vec<jump_thread_edge *> *path) ...@@ -2402,8 +2409,33 @@ valid_jump_thread_path (vec<jump_thread_edge *> *path)
irreducible loop. We avoid that unless the jump thread has a multi-way irreducible loop. We avoid that unless the jump thread has a multi-way
branch, in which case we have deemed it worth losing other branch, in which case we have deemed it worth losing other
loop optimizations later if we can eliminate the multi-way branch. */ loop optimizations later if we can eliminate the multi-way branch. */
if (!multiway_branch && threaded_through_latch) if (!threaded_multiway_branch && threaded_through_latch)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file,
"Thread through latch without threading a multiway "
"branch.\n");
dump_jump_thread_path (dump_file, *path, false);
}
return false; return false;
}
/* When there is a multi-way branch on the path, then threading can
explode the CFG due to duplicating the edges for that multi-way
branch. So like above, only allow a multi-way branch on the path
if we actually thread a multi-way branch. */
if (!threaded_multiway_branch && multiway_branch_in_path)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file,
"Thread through multiway branch without threading "
"a multiway branch.\n");
dump_jump_thread_path (dump_file, *path, false);
}
return false;
}
return true; return true;
} }
...@@ -2494,11 +2526,8 @@ thread_through_all_blocks (bool may_peel_loop_headers) ...@@ -2494,11 +2526,8 @@ thread_through_all_blocks (bool may_peel_loop_headers)
/* Do not jump-thread twice from the same block. */ /* Do not jump-thread twice from the same block. */
if (bitmap_bit_p (threaded_blocks, entry->src->index) if (bitmap_bit_p (threaded_blocks, entry->src->index)
/* Verify that the jump thread path is still valid: a /* We may not want to realize this jump thread path
previous jump-thread may have changed the CFG, and for various reasons. So check it first. */
invalidated the current path or the requested jump
thread might create irreducible loops which should
generally be avoided. */
|| !valid_jump_thread_path (path)) || !valid_jump_thread_path (path))
{ {
/* Remove invalid FSM jump-thread paths. */ /* Remove invalid FSM jump-thread paths. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment