aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfganal.c
diff options
context:
space:
mode:
authorsteven <steven@138bc75d-0d04-0410-961f-82ee72b054a4>2012-07-08 10:06:14 +0000
committersteven <steven@138bc75d-0d04-0410-961f-82ee72b054a4>2012-07-08 10:06:14 +0000
commit4a020a8c3dfec7d26c2e1f9c55286390c5fad76d (patch)
tree6449db5e8557f01213c64b681cc559f5835d3636 /gcc/cfganal.c
parent50a8e74cf0f8c34ef9e6023e6114d044b20a588b (diff)
gcc/
* basic-block.h: Re-group most prototypes per file. (struct edge_list): Remove num_blocks field. (dump_bb_info): Adjust prototypes. (dump_reg_info): Move prototype to regs.h. * function.h: Do not include tree.h. Include vec.h, vecir.h, input.h and machmode.h to compensate. (function_name): New prototype. * gimple.h: Include tree.h to compensate for basic-block.h change. * langhooks.h: Note that tree.h is only necessary for enum tree_code. * regs.h (dump_reg_info): Prototype here. * regset.h: Adjust file reference in comment. (debug_regset): Remove prototype. * rtl.h: Include flags.h for flag_var_tracking_assignments. (MAY_HAVE_DEBUG_INSNS): Define as flag_var_tracking_assignments instead of no-longer-available tree.h's MAY_HAVE_DEBUG_STMTS. (dump_reg_info, dump_flow_info): Remove prototypes. * bb-reorder.c (set_edge_can_fallthru_flag): Move from cfganal.c to here, the only user. Make static. (reorder_basic_blocks): Call dump_reg_info before dump_flow_info. * cfg.c: Do not include tm.h, tree.h, rtl.h, hard-reg-set.h, regs.h, flags.h, function.h, except.h, diagnostic-core.h, tm_p.h, timevar.h, tree-pass.h, cfgloop.h, and tree-flow.h. Include basic-block.h, the first header I'd expect to be included. (reg_obstack): Move to df-core.c. (free_edge): Remove bogus ATTRIBUTE_UNUSED. (remove_edge_raw): Do not call tree-ssa's redirect_edge_var_map_clear. (redirect_edge_succ_nodup): Move to cfghooks.c. (dump_regset, debug_regset): Move to df-core.c. (dump_bb_info): Move to cfgrtl.c. (dump_reg_info): Move to regstat.c. (dump_flow_info): Move to cfgrtl.c. (debug_flow_info): Likewise. (dump_edge_info): Do not look at cfun, a CFG without cfun is nonsense. * cfganal.c: Do not include tm.h, rtl.h, obstack.h, hard-reg-set.h, insn-config.h, recog.h, diagnostic-core.h, tm_p.h, and cfgloop.h. (flow_active_insn_p, forwarder_block_p, can_fallthru, could_fall_through): Move to cfgrtl.c. (set_edge_can_fallthru_flag): Moved to bb-reorder.c. (create_edge_list): Do not set edge_list's removed num_blocks. (print_edge_list): Look at n_basic_blocks instead of num_blocks. (flow_nodes_print): Remove. (flow_edge_list_print): Remove. (inverted_post_order_compute): Use FOR_ALL_BB. *cfgrtl.c (dump_flow_info): Moved from cfg.c. Do not call dump_reg_info. (debug_flow_info): Moved from cfg.c (dump_bb_info): Moved from cfg.c. Take 'verbose' argument to avoid looking at TDF_* flags from tree-pass.h. (flow_active_insn_p, forwarder_block_p, can_fallthru, could_fall_through): Moved from cfganal.c. (print_rtl_with_bb): Adjust dump_bb_info calls. * cfghooks.c (redirect_edge_succ_nodup): Moved from cfg.c. (remove_edge): Call redirect_edge_var_map_clear if IR_GIMPLE. (cfgcleanup.c): Look at MAY_HAVE_DEBUG_INSNS, not MAY_HAVE_DEBUG_STMTS. * cselib.c: Include tree.h with a FIXME. * df-core.c (reg_obstack): Moved from cfg.c. (dump_regset): Likewise. (debug_regset): Likewise. Make a DEBUG_FUNCTION. * final.c (compute_alignments): Call dump_reg_info before dump_flow_info. * function.c (function_name): New function. (current_function_name): Use it. * ifcvt.c (rest_of_handle_if_conversion): Call dump_reg_info before dump_flow_info. * ira-conflicts.c: Include tree.h with a note. * regstat.c (dump_reg_info): Moved here from cfg.c. * loop-init.c: Include regs.h instead of hard-reg-set.h. (rtl_loop_init): Call dump_reg_info before dump_flow_info. (rtl_loop_done): Likewise. * mcf.c: Include tree.h before langhooks.h. * predict.c (maybe_hot_count_p): Assert we have cfun. (probably_never_executed_bb_p): Likewise. * profile.c (compute_branch_probabilities): Use gimple_dump_cfg instead of dump_flow_info. * sched-deps.c: Include tree.h with a FIXME. (call_may_noreturn_p): Add FIXME note why this function has to look at function decls instead of function decl flags. * sched-vis.c: Include tree.h with a FIXME. (print_rtl_slim): Adjust dump_bb_info uses. * statistics.c (statistics_fini_pass_2): Use current_function_name to avoid including tree.h. (statistics_counter_event): Use function_name for the same reason. (statistics_histogram_event): Likewise. * tracer.c (tracer): Remove bogus gcc_assert. Use brief_dump_cfg instead of dump_flow_info. * var-tracking.c (variable_tracking_main_1): Call dump_reg_info before dump_flow_info. * doc/cfg.texi: Update CFG documentation. * Makefile.in (RTL_H): Depend on FLAGS_H. (GIMPLE_H): Depend on TREE_H. (FUNCTION_H): Depend on VEC_H, vecir.h, INPUT_H and MACHMODE_H, but no longer on TREE_H. (C_COMMON_H): Depend on TREE_H. (cselib.o, cse.o, cfganal.o, loop-init.o, ira-conflicts.o, sched-deps.o, sched-vis.o): Fixup dependencies. c-family/ * c-common.h: Include tree.h. cp/ * decl.c (cp_finish_decl): Add FIXME at add_local_decl call site. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@189359 138bc75d-0d04-0410-961f-82ee72b054a4
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 d361ff08f98..c906e17e358 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. */