summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-threadupdate.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-threadupdate.c')
-rw-r--r--gcc/tree-ssa-threadupdate.c124
1 files changed, 57 insertions, 67 deletions
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index 1a52e4702fa..c0476b48a1c 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -1,5 +1,5 @@
/* Thread edges through blocks and update the control flow and SSA graphs.
- Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ Copyright (C) 2004-2014 Free Software Foundation, Inc.
This file is part of GCC.
@@ -421,27 +421,22 @@ create_edge_and_update_destination_phis (struct redirection_data *rd,
e->probability = REG_BR_PROB_BASE;
e->count = bb->count;
- /* We have to copy path -- which means creating a new vector as well
- as all the jump_thread_edge entries. */
- if (rd->path->last ()->e->aux)
- {
- vec<jump_thread_edge *> *path = THREAD_PATH (rd->path->last ()->e);
- vec<jump_thread_edge *> *copy = new vec<jump_thread_edge *> ();
+ /* We used to copy the thread path here. That was added in 2007
+ and dutifully updated through the representation changes in 2013.
- /* Sadly, the elements of the vector are pointers and need to
- be copied as well. */
- for (unsigned int i = 0; i < path->length (); i++)
- {
- jump_thread_edge *x
- = new jump_thread_edge ((*path)[i]->e, (*path)[i]->type);
- copy->safe_push (x);
- }
- e->aux = (void *)copy;
- }
- else
- {
- e->aux = NULL;
- }
+ In 2013 we added code to thread from an interior node through
+ the backedge to another interior node. That runs after the code
+ to thread through loop headers from outside the loop.
+
+ The latter may delete edges in the CFG, including those
+ which appeared in the jump threading path we copied here. Thus
+ we'd end up using a dangling pointer.
+
+ After reviewing the 2007/2011 code, I can't see how anything
+ depended on copying the AUX field and clearly copying the jump
+ threading path is problematical due to embedded edge pointers.
+ It has been removed. */
+ e->aux = NULL;
/* If there are any PHI nodes at the destination of the outgoing edge
from the duplicate block, then we will need to add a new argument
@@ -1417,7 +1412,7 @@ mark_threaded_blocks (bitmap threaded_blocks)
{
EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
{
- bb = BASIC_BLOCK (i);
+ bb = BASIC_BLOCK_FOR_FN (cfun, i);
if (EDGE_COUNT (bb->preds) > 1
&& !redirection_block_p (bb))
{
@@ -1447,51 +1442,39 @@ mark_threaded_blocks (bitmap threaded_blocks)
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);
+ basic_block bb = BASIC_BLOCK_FOR_FN (cfun, 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++)
+ for (unsigned int i = 0, crossed_headers = 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)
+ basic_block dest = (*path)[i]->e->dest;
+ crossed_headers += (dest == dest->loop_father->header);
+ if (crossed_headers > 1)
{
- /* 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))
{
- /* 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))
- {
- delete_jump_thread_path (path);
- e->aux = NULL;
- }
- break;
- }
- else
- {
- second_father = (*path)[i]->e->dest->loop_father;
+ delete_jump_thread_path (path);
+ e->aux = NULL;
}
+ break;
}
}
}
@@ -1517,7 +1500,7 @@ mark_threaded_blocks (bitmap threaded_blocks)
we have to iterate on those rather than the threaded_edges vector. */
EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
{
- bb = BASIC_BLOCK (i);
+ bb = BASIC_BLOCK_FOR_FN (cfun, i);
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (e->aux)
@@ -1597,7 +1580,7 @@ thread_through_all_blocks (bool may_peel_loop_headers)
loop structure. */
EXECUTE_IF_SET_IN_BITMAP (threaded_blocks, 0, i, bi)
{
- basic_block bb = BASIC_BLOCK (i);
+ basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
if (EDGE_COUNT (bb->preds) > 0)
retval |= thread_block (bb, true);
@@ -1636,7 +1619,7 @@ thread_through_all_blocks (bool may_peel_loop_headers)
ahead and thread it, else ignore it. */
basic_block bb;
edge e;
- FOR_EACH_BB (bb)
+ FOR_EACH_BB_FN (bb, cfun)
{
/* If we do end up threading here, we can remove elements from
BB->preds. Thus we can not use the FOR_EACH_EDGE iterator. */
@@ -1676,13 +1659,20 @@ thread_through_all_blocks (bool may_peel_loop_headers)
{
struct loop *loop = (*path)[0]->e->dest->loop_father;
- retval |= thread_block ((*path)[0]->e->dest, false);
- e->aux = NULL;
-
- /* This jump thread likely totally scrambled this loop.
- So arrange for it to be fixed up. */
- loop->header = NULL;
- loop->latch = NULL;
+ if (thread_block ((*path)[0]->e->dest, false))
+ {
+ /* This jump thread likely totally scrambled this loop.
+ So arrange for it to be fixed up. */
+ loop->header = NULL;
+ loop->latch = NULL;
+ e->aux = NULL;
+ }
+ else
+ {
+ delete_jump_thread_path (path);
+ e->aux = NULL;
+ ei_next (&ei);
+ }
}
}
else