diff options
author | steven <steven@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-07-08 10:06:14 +0000 |
---|---|---|
committer | steven <steven@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-07-08 10:06:14 +0000 |
commit | 4a020a8c3dfec7d26c2e1f9c55286390c5fad76d (patch) | |
tree | 6449db5e8557f01213c64b681cc559f5835d3636 /gcc/cfganal.c | |
parent | 50a8e74cf0f8c34ef9e6023e6114d044b20a588b (diff) | |
download | gcc-4a020a8c3dfec7d26c2e1f9c55286390c5fad76d.tar.gz |
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.c | 198 |
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. */ |