[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
This commit is contained in:
Jeff Law 2015-11-18 17:33:27 -07:00 committed by Jeff Law
parent 3ebf5a30cf
commit 7d7e7aca3b
5 changed files with 101 additions and 12 deletions

View File

@ -1,3 +1,12 @@
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>
PR c/65083

View File

@ -1,3 +1,9 @@
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>
PR fortran/59910

View File

@ -32,8 +32,10 @@ foo (int N, int c, int b, int *a)
pt--;
}
/* There are 3 FSM jump threading opportunities. */
/* { dg-final { scan-tree-dump-times "FSM" 3 "vrp1"} } */
/* There are 3 FSM jump threading opportunities, one of which will
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. */
/* { dg-final { scan-tree-dump-not "flag" "optimized"} } */

View File

@ -0,0 +1,43 @@
/* { 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"} } */

View File

@ -2370,11 +2370,13 @@ static bool
valid_jump_thread_path (vec<jump_thread_edge *> *path)
{
unsigned len = path->length ();
bool multiway_branch = false;
bool threaded_multiway_branch = false;
bool multiway_branch_in_path = false;
bool threaded_through_latch = false;
/* 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++)
{
edge e = (*path)[j]->e;
@ -2394,7 +2396,12 @@ valid_jump_thread_path (vec<jump_thread_edge *> *path)
threaded_through_latch = true;
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
@ -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
branch, in which case we have deemed it worth losing other
loop optimizations later if we can eliminate the multi-way branch. */
if (!multiway_branch && threaded_through_latch)
return false;
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;
}
/* 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;
}
@ -2494,11 +2526,8 @@ thread_through_all_blocks (bool may_peel_loop_headers)
/* Do not jump-thread twice from the same block. */
if (bitmap_bit_p (threaded_blocks, entry->src->index)
/* Verify that the jump thread path is still valid: a
previous jump-thread may have changed the CFG, and
invalidated the current path or the requested jump
thread might create irreducible loops which should
generally be avoided. */
/* We may not want to realize this jump thread path
for various reasons. So check it first. */
|| !valid_jump_thread_path (path))
{
/* Remove invalid FSM jump-thread paths. */