diff options
author | Jeff Law <law@redhat.com> | 2013-10-11 14:31:25 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2013-10-11 14:31:25 -0600 |
commit | ef3cfba23d0f9c518cc71ff053994e77e80f1d1a (patch) | |
tree | df0943cec3572628c3fbfa0e8b03d172da3a36a1 /gcc | |
parent | 6e8b7d9cd6c483e85dc243ac4edf561ca7d8f7ef (diff) | |
download | gcc-ef3cfba23d0f9c518cc71ff053994e77e80f1d1a.zip gcc-ef3cfba23d0f9c518cc71ff053994e77e80f1d1a.tar.gz gcc-ef3cfba23d0f9c518cc71ff053994e77e80f1d1a.tar.bz2 |
re PR tree-optimization/58640 (wrong code (segfaults) at -O3 on x86_64-linux-gnu)
PR tree-optimization/58640
* tree-ssa-threadupdate.c (mark_threaded_blocks): Truncate jump threading
paths that cross over two loop entry points.
* gcc.c-torture/execute/pr58640.c: New test.
From-SVN: r203463
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr58640.c | 32 | ||||
-rw-r--r-- | gcc/tree-ssa-threadupdate.c | 62 |
4 files changed, 104 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 41e29dc..9f4e297 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2013-10-11 Jeff Law <law@redhat.com> + + PR tree-optimization/58640 + * tree-ssa-threadupdate.c (mark_threaded_blocks): Truncate jump threading + paths that cross over two loop entry points. + 2013-10-11 Bill Schmidt <wschmidt@linux.vnet.ibm.com> * config/rs6000/vsx.md (*vsx_le_perm_load_v2di): Generalize to diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 87ff2a7..bb2ede4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2013-10-11 Jeff Law <law@redhat.com> + + * gcc.c-torture/execute/pr58640.c: New test. + 2013-10-11 Paolo Carlini <paolo.carlini@oracle.com> PR c++/58633 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58640.c b/gcc/testsuite/gcc.c-torture/execute/pr58640.c new file mode 100644 index 0000000..7786b8d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr58640.c @@ -0,0 +1,32 @@ +int a, b, c, d = 1, e; + +static signed char +foo () +{ + int f, g = a; + + for (f = 1; f < 3; f++) + for (; b < 1; b++) + { + if (d) + for (c = 0; c < 4; c++) + for (f = 0; f < 3; f++) + { + for (e = 0; e < 1; e++) + a = g; + if (f) + break; + } + else if (f) + continue; + return 0; + } + return 0; +} + +int +main () +{ + foo (); + exit (0); +} diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index 2adea1b..3e34567 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -1354,6 +1354,68 @@ mark_threaded_blocks (bitmap threaded_blocks) else bitmap_copy (threaded_blocks, tmp); + /* Look for jump threading paths which cross multiple loop headers. + + The code to thread through loop headers will change the CFG in ways + that break assumptions made by the loop optimization code. + + We don't want to blindly cancel the requests. We can instead do better + by trimming off the end of the jump thread path. */ + EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi) + { + basic_block bb = BASIC_BLOCK (i); + FOR_EACH_EDGE (e, ei, bb->preds) + { + if (e->aux) + { + vec<jump_thread_edge *> *path = THREAD_PATH (e); + + /* Basically we're looking for a situation where we can see + 3 or more loop structures on a jump threading path. */ + + struct loop *first_father = (*path)[0]->e->src->loop_father; + struct loop *second_father = NULL; + for (unsigned int i = 0; i < path->length (); i++) + { + /* See if this is a loop father we have not seen before. */ + if ((*path)[i]->e->dest->loop_father != first_father + && (*path)[i]->e->dest->loop_father != second_father) + { + /* We've already seen two loop fathers, so we + need to trim this jump threading path. */ + if (second_father != NULL) + { + /* Trim from entry I onwards. */ + for (unsigned int j = i; j < path->length (); j++) + delete (*path)[j]; + path->truncate (i); + + /* Now that we've truncated the path, make sure + what's left is still valid. We need at least + two edges on the path and the last edge can not + be a joiner. This should never happen, but let's + be safe. */ + if (path->length () < 2 + || (path->last ()->type + == EDGE_COPY_SRC_JOINER_BLOCK)) + { + for (unsigned int i = 0; i < path->length (); i++) + delete (*path)[i]; + path->release (); + e->aux = NULL; + } + break; + } + else + { + second_father = (*path)[i]->e->dest->loop_father; + } + } + } + } + } + } + BITMAP_FREE (tmp); } |