/* Thread edges through blocks and update the control flow and SSA graphs.
- Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation,
+ Inc.
This file is part of GCC.
#include "tm.h"
#include "tree.h"
#include "flags.h"
-#include "rtl.h"
#include "tm_p.h"
-#include "ggc.h"
#include "basic-block.h"
#include "output.h"
-#include "expr.h"
#include "function.h"
-#include "diagnostic.h"
#include "tree-flow.h"
#include "tree-dump.h"
#include "tree-pass.h"
7. Put the duplicated resources in B and all the B' blocks into SSA form.
Note that block duplication can be minimized by first collecting the
- the set of unique destination blocks that the incoming edges should
+ set of unique destination blocks that the incoming edges should
be threaded to. Block duplication can be further minimized by using
B instead of creating B' for one destination if all edges into B are
going to be threaded to a successor of B.
static void
remove_ctrl_stmt_and_useless_edges (basic_block bb, basic_block dest_bb)
{
- block_stmt_iterator bsi;
+ gimple_stmt_iterator gsi;
edge e;
edge_iterator ei;
- bsi = bsi_last (bb);
+ gsi = gsi_last_bb (bb);
/* If the duplicate ends with a control statement, then remove it.
Note that if we are duplicating the template block rather than the
original basic block, then the duplicate might not have any real
statements in it. */
- if (!bsi_end_p (bsi)
- && bsi_stmt (bsi)
- && (TREE_CODE (bsi_stmt (bsi)) == COND_EXPR
- || TREE_CODE (bsi_stmt (bsi)) == GOTO_EXPR
- || TREE_CODE (bsi_stmt (bsi)) == SWITCH_EXPR))
- bsi_remove (&bsi, true);
+ if (!gsi_end_p (gsi)
+ && gsi_stmt (gsi)
+ && (gimple_code (gsi_stmt (gsi)) == GIMPLE_COND
+ || gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
+ || gimple_code (gsi_stmt (gsi)) == GIMPLE_SWITCH))
+ gsi_remove (&gsi, true);
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
create_edge_and_update_destination_phis (struct redirection_data *rd)
{
edge e = make_edge (rd->dup_block, rd->outgoing_edge->dest, EDGE_FALLTHRU);
- tree phi;
+ gimple_stmt_iterator gsi;
rescan_loop_exit (e, true, false);
e->probability = REG_BR_PROB_BASE;
from the duplicate block, then we will need to add a new argument
to them. The argument should have the same value as the argument
associated with the outgoing edge stored in RD. */
- for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
+ for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
{
+ gimple phi = gsi_stmt (gsi);
+ source_location locus;
int indx = rd->outgoing_edge->dest_idx;
- add_phi_arg (phi, PHI_ARG_DEF (phi, indx), e);
+
+ locus = gimple_phi_arg_location (phi, indx);
+ add_phi_arg (phi, gimple_phi_arg_def (phi, indx), e, locus);
}
}
remove_ctrl_stmt_and_useless_edges (local_info->bb,
rd->outgoing_edge->dest);
- /* And fixup the flags on the single remaining edge. */
+ /* Fixup the flags on the single remaining edge. */
single_succ_edge (local_info->bb)->flags
&= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL);
single_succ_edge (local_info->bb)->flags |= EDGE_FALLTHRU;
+
+ /* And adjust count and frequency on BB. */
+ local_info->bb->count = e->count;
+ local_info->bb->frequency = EDGE_FREQUENCY (e);
}
}
is one, this is equivalent to a "forwarder" block. */
static bool
-redirection_block_p (const_basic_block bb)
+redirection_block_p (basic_block bb)
{
- const_block_stmt_iterator bsi;
+ gimple_stmt_iterator gsi;
/* Advance to the first executable statement. */
- bsi = cbsi_start (bb);
- while (!cbsi_end_p (bsi)
- && (TREE_CODE (cbsi_stmt (bsi)) == LABEL_EXPR
- || IS_EMPTY_STMT (cbsi_stmt (bsi))))
- cbsi_next (&bsi);
+ gsi = gsi_start_bb (bb);
+ while (!gsi_end_p (gsi)
+ && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
+ || is_gimple_debug (gsi_stmt (gsi))
+ || gimple_nop_p (gsi_stmt (gsi))))
+ gsi_next (&gsi);
/* Check if this is an empty block. */
- if (cbsi_end_p (bsi))
+ if (gsi_end_p (gsi))
return true;
/* Test that we've reached the terminating control statement. */
- return cbsi_stmt (bsi)
- && (TREE_CODE (cbsi_stmt (bsi)) == COND_EXPR
- || TREE_CODE (cbsi_stmt (bsi)) == GOTO_EXPR
- || TREE_CODE (cbsi_stmt (bsi)) == SWITCH_EXPR);
+ return gsi_stmt (gsi)
+ && (gimple_code (gsi_stmt (gsi)) == GIMPLE_COND
+ || gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
+ || gimple_code (gsi_stmt (gsi)) == GIMPLE_SWITCH);
}
/* BB is a block which ends with a COND_EXPR or SWITCH_EXPR and when BB
basic_block bb = e->dest;
edge eto = (edge) e->aux;
struct redirection_data rd;
- struct local_info local_info;
e->aux = NULL;
/* Otherwise, we need to create a copy. */
update_bb_profile_for_threading (bb, EDGE_FREQUENCY (e), e->count, eto);
- local_info.bb = bb;
rd.outgoing_edge = eto;
create_block_for_threading (bb, &rd);
else
tgt_bb = split_edge (tgt_edge);
}
-
+
if (latch->aux)
{
/* First handle the case latch edge is redirected. */
loop->header = latch->dest;
loop->latch = latch->src;
}
-
+
return true;
fail:
/* If optimizing for size, only thread through block if we don't have
to duplicate it or it's an otherwise empty redirection block. */
- if (optimize_size)
+ if (optimize_function_for_size_p (cfun))
{
EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
{
retval |= thread_through_loop_header (loop, may_peel_loop_headers);
}
- if (dump_file && (dump_flags & TDF_STATS))
- fprintf (dump_file, "\nJumps threaded: %lu\n",
- thread_stats.num_threaded_edges);
+ statistics_counter_event (cfun, "Jumps threaded",
+ thread_stats.num_threaded_edges);
free_original_copy_tables ();
threading opportunities discovered by a pass and update the CFG
and SSA form all at once.
- E is the edge we can thread, E2 is the new target edge. ie, we
+ E is the edge we can thread, E2 is the new target edge, i.e., we
are effectively recording that E->dest can be changed to E2->dest
after fixing the SSA graph. */