Commit b06cbaac by Jeff Law Committed by Jeff Law

tree-ssa-threadupdate.c: Include ssa-iterators.h

	* tree-ssa-threadupdate.c: Include ssa-iterators.h
	(copy_phi_arg_into_existing_phi): New function.
	(any_remaining_duplicated_blocks): Likewise.
	(ssa_fix_duplicate_block_edges): Handle multiple duplicated
	blocks on a jump threading path.

From-SVN: r205004
parent 01ccc98e
2013-11-19 Jeff Law <law@redhat.com> 2013-11-19 Jeff Law <law@redhat.com>
* tree-ssa-threadupdate.c: Include ssa-iterators.h
(copy_phi_arg_into_existing_phi): New function.
(any_remaining_duplicated_blocks): Likewise.
(ssa_fix_duplicate_block_edges): Handle multiple duplicated
blocks on a jump threading path.
* tree-ssa-threadupdate.c (thread_through_loop_header): Do not * tree-ssa-threadupdate.c (thread_through_loop_header): Do not
thread through a joiner which has the latch edge. thread through a joiner which has the latch edge.
...@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-phinodes.h" #include "tree-phinodes.h"
#include "tree-ssa.h" #include "tree-ssa.h"
#include "tree-ssa-threadupdate.h" #include "tree-ssa-threadupdate.h"
#include "ssa-iterators.h"
#include "dumpfile.h" #include "dumpfile.h"
#include "cfgloop.h" #include "cfgloop.h"
#include "hash-table.h" #include "hash-table.h"
...@@ -337,6 +338,31 @@ lookup_redirection_data (edge e, enum insert_option insert) ...@@ -337,6 +338,31 @@ lookup_redirection_data (edge e, enum insert_option insert)
} }
} }
/* Similar to copy_phi_args, except that the PHI arg exists, it just
does not have a value associated with it. */
static void
copy_phi_arg_into_existing_phi (edge src_e, edge tgt_e)
{
int src_idx = src_e->dest_idx;
int tgt_idx = tgt_e->dest_idx;
/* Iterate over each PHI in e->dest. */
for (gimple_stmt_iterator gsi = gsi_start_phis (src_e->dest),
gsi2 = gsi_start_phis (tgt_e->dest);
!gsi_end_p (gsi);
gsi_next (&gsi), gsi_next (&gsi2))
{
gimple src_phi = gsi_stmt (gsi);
gimple dest_phi = gsi_stmt (gsi2);
tree val = gimple_phi_arg_def (src_phi, src_idx);
source_location locus = gimple_phi_arg_location (src_phi, src_idx);
SET_PHI_ARG_DEF (dest_phi, tgt_idx, val);
gimple_phi_arg_set_location (dest_phi, tgt_idx, locus);
}
}
/* For each PHI in BB, copy the argument associated with SRC_E to TGT_E. */ /* For each PHI in BB, copy the argument associated with SRC_E to TGT_E. */
static void static void
...@@ -418,7 +444,23 @@ create_edge_and_update_destination_phis (struct redirection_data *rd, ...@@ -418,7 +444,23 @@ create_edge_and_update_destination_phis (struct redirection_data *rd,
copy_phi_args (e->dest, rd->path->last ()->e, e); copy_phi_args (e->dest, rd->path->last ()->e, e);
} }
/* Wire up the outgoing edges from the duplicate block and /* Look through PATH beginning at START and return TRUE if there are
any additional blocks that need to be duplicated. Otherwise,
return FALSE. */
static bool
any_remaining_duplicated_blocks (vec<jump_thread_edge *> *path,
unsigned int start)
{
for (unsigned int i = start + 1; i < path->length (); i++)
{
if ((*path)[i]->type == EDGE_COPY_SRC_JOINER_BLOCK
|| (*path)[i]->type == EDGE_COPY_SRC_BLOCK)
return true;
}
return false;
}
/* Wire up the outgoing edges from the duplicate blocks and
update any PHIs as needed. */ update any PHIs as needed. */
void void
ssa_fix_duplicate_block_edges (struct redirection_data *rd, ssa_fix_duplicate_block_edges (struct redirection_data *rd,
...@@ -427,37 +469,77 @@ ssa_fix_duplicate_block_edges (struct redirection_data *rd, ...@@ -427,37 +469,77 @@ ssa_fix_duplicate_block_edges (struct redirection_data *rd,
edge e = rd->incoming_edges->e; edge e = rd->incoming_edges->e;
vec<jump_thread_edge *> *path = THREAD_PATH (e); vec<jump_thread_edge *> *path = THREAD_PATH (e);
/* If we were threading through an joiner block, then we want for (unsigned int count = 0, i = 1; i < path->length (); i++)
to keep its control statement and redirect an outgoing edge. {
Else we want to remove the control statement & edges, then create /* If we were threading through an joiner block, then we want
a new outgoing edge. In both cases we may need to update PHIs. */ to keep its control statement and redirect an outgoing edge.
if ((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK) Else we want to remove the control statement & edges, then create
{ a new outgoing edge. In both cases we may need to update PHIs. */
edge victim; if ((*path)[i]->type == EDGE_COPY_SRC_JOINER_BLOCK)
edge e2; {
edge victim;
/* This updates the PHIs at the destination of the duplicate edge e2;
block. */
update_destination_phis (local_info->bb, rd->dup_blocks[0]); /* This updates the PHIs at the destination of the duplicate
block. */
/* Find the edge from the duplicate block to the block we're update_destination_phis (local_info->bb, rd->dup_blocks[count]);
threading through. That's the edge we want to redirect. */
victim = find_edge (rd->dup_blocks[0], (*path)[1]->e->dest); /* Find the edge from the duplicate block to the block we're
e2 = redirect_edge_and_branch (victim, path->last ()->e->dest); threading through. That's the edge we want to redirect. */
e2->count = path->last ()->e->count; victim = find_edge (rd->dup_blocks[count], (*path)[i]->e->dest);
/* If we redirected the edge, then we need to copy PHI arguments /* If there are no remaining blocks on the path to duplicate,
at the target. If the edge already existed (e2 != victim case), then redirect VICTIM to the final destination of the jump
then the PHIs in the target already have the correct arguments. */ threading path. */
if (e2 == victim) if (!any_remaining_duplicated_blocks (path, i))
copy_phi_args (e2->dest, path->last ()->e, e2); {
} e2 = redirect_edge_and_branch (victim, path->last ()->e->dest);
else e2->count = path->last ()->e->count;
{ /* If we redirected the edge, then we need to copy PHI arguments
remove_ctrl_stmt_and_useless_edges (rd->dup_blocks[0], NULL); at the target. If the edge already existed (e2 != victim
create_edge_and_update_destination_phis (rd, rd->dup_blocks[0]); case), then the PHIs in the target already have the correct
arguments. */
if (e2 == victim)
copy_phi_args (e2->dest, path->last ()->e, e2);
}
else
{
/* Redirect VICTIM to the next duplicated block in the path. */
e2 = redirect_edge_and_branch (victim, rd->dup_blocks[count + 1]);
/* We need to update the PHIs in the next duplicated block. We
want the new PHI args to have the same value as they had
in the source of the next duplicate block.
Thus, we need to know which edge we traversed into the
source of the duplicate. Furthermore, we may have
traversed many edges to reach the source of the duplicate.
Walk through the path starting at element I until we
hit an edge marked with EDGE_COPY_SRC_BLOCK. We want
the edge from the prior element. */
for (unsigned int j = i + 1; j < path->length (); j++)
{
if ((*path)[j]->type == EDGE_COPY_SRC_BLOCK)
{
copy_phi_arg_into_existing_phi ((*path)[j - 1]->e, e2);
break;
}
}
}
count++;
}
else if ((*path)[i]->type == EDGE_COPY_SRC_BLOCK)
{
remove_ctrl_stmt_and_useless_edges (rd->dup_blocks[count], NULL);
create_edge_and_update_destination_phis (rd, rd->dup_blocks[count]);
if (count == 1)
single_succ_edge (rd->dup_blocks[1])->aux = NULL;
count++;
}
} }
} }
/* Hash table traversal callback routine to create duplicate blocks. */ /* Hash table traversal callback routine to create duplicate blocks. */
int int
......
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