/* Thread edges through blocks and update the control flow and SSA graphs.
- Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
static hashval_t
redirection_data_hash (const void *p)
{
- edge e = ((struct redirection_data *)p)->outgoing_edge;
+ edge e = ((const struct redirection_data *)p)->outgoing_edge;
return e->dest->index;
}
static int
redirection_data_eq (const void *p1, const void *p2)
{
- edge e1 = ((struct redirection_data *)p1)->outgoing_edge;
- edge e2 = ((struct redirection_data *)p2)->outgoing_edge;
+ edge e1 = ((const struct redirection_data *)p1)->outgoing_edge;
+ edge e2 = ((const struct redirection_data *)p2)->outgoing_edge;
return e1 == e2;
}
edge e = make_edge (rd->dup_block, rd->outgoing_edge->dest, EDGE_FALLTHRU);
tree phi;
+ rescan_loop_exit (e, true, false);
e->probability = REG_BR_PROB_BASE;
e->count = rd->dup_block->count;
e->aux = rd->outgoing_edge->aux;
is one, this is equivalent to a "forwarder" block. */
static bool
-redirection_block_p (basic_block bb)
+redirection_block_p (const_basic_block bb)
{
- block_stmt_iterator bsi;
+ const_block_stmt_iterator bsi;
/* Advance to the first executable statement. */
- bsi = bsi_start (bb);
- while (!bsi_end_p (bsi)
- && (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR
- || IS_EMPTY_STMT (bsi_stmt (bsi))))
- bsi_next (&bsi);
+ 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);
/* Check if this is an empty block. */
- if (bsi_end_p (bsi))
+ if (cbsi_end_p (bsi))
return true;
/* Test that we've reached the terminating control statement. */
- return bsi_stmt (bsi)
- && (TREE_CODE (bsi_stmt (bsi)) == COND_EXPR
- || TREE_CODE (bsi_stmt (bsi)) == GOTO_EXPR
- || TREE_CODE (bsi_stmt (bsi)) == SWITCH_EXPR);
+ 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);
}
/* BB is a block which ends with a COND_EXPR or SWITCH_EXPR and when BB
/* If we thread the latch of the loop to its exit, the loop ceases to
exist. Make sure we do not restrict ourselves in order to preserve
this loop. */
- if (current_loops && loop->header == bb)
+ if (loop->header == bb)
{
e = loop_latch_edge (loop);
- e2 = e->aux;
+ e2 = (edge) e->aux;
if (e2 && loop_exit_edge_p (loop, e2))
{
efficient lookups. */
FOR_EACH_EDGE (e, ei, bb->preds)
{
- e2 = e->aux;
+ e2 = (edge) e->aux;
if (!e2
/* If NOLOOP_ONLY is true, we only allow threading through the
header of a loop to exit edges. */
|| (noloop_only
- && current_loops
&& bb == bb->loop_father->header
&& !loop_exit_edge_p (bb->loop_father, e2)))
{
}
update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
- e->count, e->aux);
+ e->count, (edge) e->aux);
/* Insert the outgoing edge into the hash table if it is not
already in the hash table. */
DO_NOT_DUPLICATE attribute. */
if (all)
{
- edge e = EDGE_PRED (bb, 0)->aux;
+ edge e = (edge) EDGE_PRED (bb, 0)->aux;
lookup_redirection_data (e, NULL, NO_INSERT)->do_not_duplicate = true;
}
+ /* We do not update dominance info. */
+ free_dominance_info (CDI_DOMINATORS);
+
/* Now create duplicates of BB.
Note that for a block with a high outgoing degree we can waste
thread_single_edge (edge e)
{
basic_block bb = e->dest;
- edge eto = e->aux;
+ edge eto = (edge) e->aux;
struct redirection_data rd;
struct local_info local_info;
/* If BB has just a single predecessor, we should only remove the
control statements at its end, and successors except for ETO. */
remove_ctrl_stmt_and_useless_edges (bb, eto->dest);
+
+ /* And fixup the flags on the single remaining edge. */
+ eto->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL);
+ eto->flags |= EDGE_FALLTHRU;
+
return bb;
}
static basic_block dbds_ce_stop;
static bool
-dbds_continue_enumeration_p (basic_block bb, void *stop)
+dbds_continue_enumeration_p (const_basic_block bb, const void *stop)
{
- return (bb != (basic_block) stop
+ return (bb != (const_basic_block) stop
&& bb != dbds_ce_stop);
}
if (latch->aux)
{
- tgt_edge = latch->aux;
+ tgt_edge = (edge) latch->aux;
tgt_bb = tgt_edge->dest;
}
else if (!may_peel_loop_headers
goto fail;
}
- tgt_edge = e->aux;
+ tgt_edge = (edge) e->aux;
atgt_bb = tgt_edge->dest;
if (!tgt_bb)
tgt_bb = atgt_bb;
struct loop *loop;
loop_iterator li;
+ /* We must know about loops in order to preserve them. */
+ gcc_assert (current_loops != NULL);
+
if (threaded_edges == NULL)
return false;
/* Then perform the threading through loop headers. We start with the
innermost loop, so that the changes in cfg we perform won't affect
further threading. */
- if (current_loops)
+ FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
{
- FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
- {
- if (!loop->header
- || !bitmap_bit_p (threaded_blocks, loop->header->index))
- continue;
+ if (!loop->header
+ || !bitmap_bit_p (threaded_blocks, loop->header->index))
+ continue;
- retval |= thread_through_loop_header (loop, may_peel_loop_headers);
- }
+ retval |= thread_through_loop_header (loop, may_peel_loop_headers);
}
- if (retval)
- free_dominance_info (CDI_DOMINATORS);
-
if (dump_file && (dump_flags & TDF_STATS))
fprintf (dump_file, "\nJumps threaded: %lu\n",
thread_stats.num_threaded_edges);
VEC_free (edge, heap, threaded_edges);
threaded_edges = NULL;
+ if (retval)
+ loops_state_set (LOOPS_NEED_FIXUP);
+
return retval;
}