aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfganal.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cfganal.c')
-rw-r--r--gcc/cfganal.c198
1 files changed, 6 insertions, 192 deletions
diff --git a/gcc/cfganal.c b/gcc/cfganal.c
index d361ff0..c906e17 100644
--- a/gcc/cfganal.c
+++ b/gcc/cfganal.c
@@ -1,7 +1,5 @@
/* Control flow graph analysis code for GNU compiler.
- Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 1987-2012 Free Software Foundation, Inc.
This file is part of GCC.
@@ -20,24 +18,16 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* This file contains various simple utilities to analyze the CFG. */
+
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "obstack.h"
-#include "hard-reg-set.h"
#include "basic-block.h"
-#include "insn-config.h"
-#include "recog.h"
-#include "diagnostic-core.h"
-#include "tm_p.h"
#include "vec.h"
#include "vecprim.h"
#include "bitmap.h"
#include "sbitmap.h"
#include "timevar.h"
-#include "cfgloop.h"
/* Store the data structures necessary for depth-first search. */
struct depth_first_search_dsS {
@@ -59,106 +49,6 @@ static void flow_dfs_compute_reverse_add_bb (depth_first_search_ds,
static basic_block flow_dfs_compute_reverse_execute (depth_first_search_ds,
basic_block);
static void flow_dfs_compute_reverse_finish (depth_first_search_ds);
-static bool flow_active_insn_p (const_rtx);
-
-/* Like active_insn_p, except keep the return value clobber around
- even after reload. */
-
-static bool
-flow_active_insn_p (const_rtx insn)
-{
- if (active_insn_p (insn))
- return true;
-
- /* A clobber of the function return value exists for buggy
- programs that fail to return a value. Its effect is to
- keep the return value from being live across the entire
- function. If we allow it to be skipped, we introduce the
- possibility for register lifetime confusion. */
- if (GET_CODE (PATTERN (insn)) == CLOBBER
- && REG_P (XEXP (PATTERN (insn), 0))
- && REG_FUNCTION_VALUE_P (XEXP (PATTERN (insn), 0)))
- return true;
-
- return false;
-}
-
-/* Return true if the block has no effect and only forwards control flow to
- its single destination. */
-
-bool
-forwarder_block_p (const_basic_block bb)
-{
- rtx insn;
-
- if (bb == EXIT_BLOCK_PTR || bb == ENTRY_BLOCK_PTR
- || !single_succ_p (bb))
- return false;
-
- /* Protect loop latches, headers and preheaders. */
- if (current_loops)
- {
- basic_block dest;
- if (bb->loop_father->header == bb)
- return false;
- dest = EDGE_SUCC (bb, 0)->dest;
- if (dest->loop_father->header == dest)
- return false;
- }
-
- for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn))
- if (INSN_P (insn) && flow_active_insn_p (insn))
- return false;
-
- return (!INSN_P (insn)
- || (JUMP_P (insn) && simplejump_p (insn))
- || !flow_active_insn_p (insn));
-}
-
-/* Return nonzero if we can reach target from src by falling through. */
-
-bool
-can_fallthru (basic_block src, basic_block target)
-{
- rtx insn = BB_END (src);
- rtx insn2;
- edge e;
- edge_iterator ei;
-
- if (target == EXIT_BLOCK_PTR)
- return true;
- if (src->next_bb != target)
- return 0;
- FOR_EACH_EDGE (e, ei, src->succs)
- if (e->dest == EXIT_BLOCK_PTR
- && e->flags & EDGE_FALLTHRU)
- return 0;
-
- insn2 = BB_HEAD (target);
- if (insn2 && !active_insn_p (insn2))
- insn2 = next_active_insn (insn2);
-
- /* ??? Later we may add code to move jump tables offline. */
- return next_active_insn (insn) == insn2;
-}
-
-/* Return nonzero if we could reach target from src by falling through,
- if the target was made adjacent. If we already have a fall-through
- edge to the exit block, we can't do that. */
-bool
-could_fall_through (basic_block src, basic_block target)
-{
- edge e;
- edge_iterator ei;
-
- if (target == EXIT_BLOCK_PTR)
- return true;
- FOR_EACH_EDGE (e, ei, src->succs)
- if (e->dest == EXIT_BLOCK_PTR
- && e->flags & EDGE_FALLTHRU)
- return 0;
- return true;
-}
/* Mark the back edges in DFS traversal.
Return nonzero if a loop (natural or otherwise) is present.
@@ -252,41 +142,6 @@ mark_dfs_back_edges (void)
return found;
}
-/* Set the flag EDGE_CAN_FALLTHRU for edges that can be fallthru. */
-
-void
-set_edge_can_fallthru_flag (void)
-{
- basic_block bb;
-
- FOR_EACH_BB (bb)
- {
- edge e;
- edge_iterator ei;
-
- FOR_EACH_EDGE (e, ei, bb->succs)
- {
- e->flags &= ~EDGE_CAN_FALLTHRU;
-
- /* The FALLTHRU edge is also CAN_FALLTHRU edge. */
- if (e->flags & EDGE_FALLTHRU)
- e->flags |= EDGE_CAN_FALLTHRU;
- }
-
- /* If the BB ends with an invertible condjump all (2) edges are
- CAN_FALLTHRU edges. */
- if (EDGE_COUNT (bb->succs) != 2)
- continue;
- if (!any_condjump_p (BB_END (bb)))
- continue;
- if (!invert_jump (BB_END (bb), JUMP_LABEL (BB_END (bb)), 0))
- continue;
- invert_jump (BB_END (bb), JUMP_LABEL (BB_END (bb)), 0);
- EDGE_SUCC (bb, 0)->flags |= EDGE_CAN_FALLTHRU;
- EDGE_SUCC (bb, 1)->flags |= EDGE_CAN_FALLTHRU;
- }
-}
-
/* Find unreachable blocks. An unreachable block will have 0 in
the reachable bit in block->flags. A nonzero value indicates the
block is reachable. */
@@ -357,23 +212,18 @@ create_edge_list (void)
struct edge_list *elist;
edge e;
int num_edges;
- int block_count;
basic_block bb;
edge_iterator ei;
- block_count = n_basic_blocks; /* Include the entry and exit blocks. */
-
- num_edges = 0;
-
/* Determine the number of edges in the flow graph by counting successor
edges on each basic block. */
+ num_edges = 0;
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
num_edges += EDGE_COUNT (bb->succs);
}
elist = XNEW (struct edge_list);
- elist->num_blocks = block_count;
elist->num_edges = num_edges;
elist->index_to_edge = XNEWVEC (edge, num_edges);
@@ -407,7 +257,7 @@ print_edge_list (FILE *f, struct edge_list *elist)
int x;
fprintf (f, "Compressed edge list, %d BBs + entry & exit, and %d edges\n",
- elist->num_blocks, elist->num_edges);
+ n_basic_blocks, elist->num_edges);
for (x = 0; x < elist->num_edges; x++)
{
@@ -459,7 +309,7 @@ verify_edge_list (FILE *f, struct edge_list *elist)
}
/* We've verified that all the edges are in the list, now lets make sure
- there are no spurious edges in the list. */
+ there are no spurious edges in the list. This is an expensive check! */
FOR_BB_BETWEEN (p, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
FOR_BB_BETWEEN (s, ENTRY_BLOCK_PTR->next_bb, NULL, next_bb)
@@ -531,42 +381,6 @@ find_edge_index (struct edge_list *edge_list, basic_block pred, basic_block succ
return (EDGE_INDEX_NO_EDGE);
}
-
-/* Dump the list of basic blocks in the bitmap NODES. */
-
-void
-flow_nodes_print (const char *str, const_sbitmap nodes, FILE *file)
-{
- unsigned int node = 0;
- sbitmap_iterator sbi;
-
- if (! nodes)
- return;
-
- fprintf (file, "%s { ", str);
- EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, node, sbi)
- fprintf (file, "%d ", node);
- fputs ("}\n", file);
-}
-
-/* Dump the list of edges in the array EDGE_LIST. */
-
-void
-flow_edge_list_print (const char *str, const edge *edge_list, int num_edges, FILE *file)
-{
- int i;
-
- if (! edge_list)
- return;
-
- fprintf (file, "%s { ", str);
- for (i = 0; i < num_edges; i++)
- fprintf (file, "%d->%d ", edge_list[i]->src->index,
- edge_list[i]->dest->index);
-
- fputs ("}\n", file);
-}
-
/* This routine will remove any fake predecessor edges for a basic block.
When the edge is removed, it is also removed from whatever successor
@@ -843,7 +657,7 @@ inverted_post_order_compute (int *post_order)
sbitmap_zero (visited);
/* Put all blocks that have no successor into the initial work list. */
- FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ FOR_ALL_BB (bb)
if (EDGE_COUNT (bb->succs) == 0)
{
/* Push the initial edge on to the stack. */