diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2013-10-09 14:11:30 +0000 |
---|---|---|
committer | Andrew Macleod <amacleod@gcc.gnu.org> | 2013-10-09 14:11:30 +0000 |
commit | c1bf2a39b394782f6f1ff14cdf35fd806ec303dd (patch) | |
tree | 5f0d797d661ee8ba11c4c05d7c09c7138fad2499 /gcc/tree-cfg.c | |
parent | 428e041efefedff5d94d49e62482861ef215620d (diff) | |
download | gcc-c1bf2a39b394782f6f1ff14cdf35fd806ec303dd.zip gcc-c1bf2a39b394782f6f1ff14cdf35fd806ec303dd.tar.gz gcc-c1bf2a39b394782f6f1ff14cdf35fd806ec303dd.tar.bz2 |
tree-flow.h: Remove all remaining prototypes...
* tree-flow.h: Remove all remaining prototypes, enums and structs that
are not related to tree-cfg.c.
* tree-ssa-address.h: New file. Relocate prototypes.
* tree-ssa-address.c: (struct mem_address): Relocate from tree-flow.h.
(addr_for_mem_ref): New. Combine call to get_address_description and
return addr_for_mem_ref.
* expr.c (expand_expr_real_1): Use new addr_for_mem_ref routine.
* tree-ssa-live.h: Adjust prototypes.
* passes.c: Include tree-ssa-live.h.
* gimple-pretty-print.h (gimple_dump_bb): Add prototype.
* graphite.c (graphite_transform_loops): Make static.
(graphite_transforms, gate_graphite_transforms, pass_data_graphite,
make_pass_graphite, pass_data_graphite_transforms,
make_pass_graphite_transforms): Relocate here from tree-ssa-loop.c.
* ipa-pure-const.c (warn_function_noreturn): Make static.
(execute_warn_function_noreturn, gate_warn_function_noreturn,
class pass_warn_function_noreturn, make_pass_warn_function_noreturn):
Relocate from tree-cfg.c
* tree-cfg.c (tree_node_can_be_shared, gimple_empty_block_p): Make
static.
(execute_warn_function_noreturn, gate_warn_function_noreturn,
class pass_warn_function_noreturn, make_pass_warn_function_noreturn):
Move to ipa-pure-const.c.
(execute_fixup_cfg, class pass_fixup_cfg, make_pass_fixup_cfg): Relocate
from tree-optimize.c.
* tree-optimize.c (execute_fixup_cfg, class pass_fixup_cfg,
make_pass_fixup_cfg): Move to tree-cfg.c.
* tree-chrec.h: (enum ev_direction): Relocate here from tree-flow.h.
Relocate some prototypes.
* tree-data-ref.h (tree_check_data_deps) Add prototype.
* tree-dump.c (dump_function_to_file): Remove prototype.
Add tree-flow.h to the include file.
* tree-dump.h: Remove prototype.
* tree-parloops.h: New File. Add prototypes.
* tree-parloops.c (gate_tree_parallelize_loops, tree_parallelize_loops,
pass_data_parallelize_loops, make_pass_parallelize_loops): Relocate
from tree-ssa-loop.c.
* tree-predcom.c (run_tree_predictive_commoning,
gate_tree_predictive_commoning, pass_data_predcom, make_pass_predcom):
Relocate here from tree-ssa-loop.c.
* tree-ssa-dom.c (tree_ssa_dominator_optimize) Don't call
ssa_name_values.release ().
* tree-ssa-threadedge.h: New File. Relocate prototypes here.
(ssa_name_values): Relocate from tree-flow.h.
* tree-ssa.h: Include tree-ssa-threadedge.h and tree-ssa-address.h.
* tree-ssa-loop.c (run_tree_predictive_commoning,
gate_tree_predictive_commoning, pass_data_predcom, make_pass_predcom,
graphite_transforms, gate_graphite_transforms, pass_data_graphite,
make_pass_graphite, pass_data_graphite_transforms,
make_pass_graphite_transforms, gate_tree_parallelize_loops,
tree_parallelize_loops, pass_data_parallelize_loops,
make_pass_parallelize_loops): Move to other files.
* tree-vectorizer.h (lpeel_tree_duplicate_loop_to_edge_cfg): Prototype
moved here.
* tree.h: Remove prototypes from tree-address.c.
From-SVN: r203320
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r-- | gcc/tree-cfg.c | 201 |
1 files changed, 143 insertions, 58 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index ed20d57..de66d07 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "pointer-set.h" #include "tree-inline.h" #include "target.h" +#include "tree-ssa-live.h" /* This file contains functions for building the Control Flow Graph (CFG) for a function tree. */ @@ -4449,7 +4450,7 @@ verify_gimple_in_seq (gimple_seq stmts) /* Return true when the T can be shared. */ -bool +static bool tree_node_can_be_shared (tree t) { if (IS_TYPE_OR_DECL_P (t) @@ -5459,7 +5460,7 @@ gimple_move_block_after (basic_block bb, basic_block after) /* Return TRUE if block BB has no executable statements, otherwise return FALSE. */ -bool +static bool gimple_empty_block_p (basic_block bb) { /* BB must have no executable statements. */ @@ -8106,62 +8107,6 @@ make_pass_warn_function_return (gcc::context *ctxt) return new pass_warn_function_return (ctxt); } -/* Emit noreturn warnings. */ - -static unsigned int -execute_warn_function_noreturn (void) -{ - if (!TREE_THIS_VOLATILE (current_function_decl) - && EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 0) - warn_function_noreturn (current_function_decl); - return 0; -} - -static bool -gate_warn_function_noreturn (void) -{ - return warn_suggest_attribute_noreturn; -} - -namespace { - -const pass_data pass_data_warn_function_noreturn = -{ - GIMPLE_PASS, /* type */ - "*warn_function_noreturn", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - true, /* has_gate */ - true, /* has_execute */ - TV_NONE, /* tv_id */ - PROP_cfg, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ -}; - -class pass_warn_function_noreturn : public gimple_opt_pass -{ -public: - pass_warn_function_noreturn (gcc::context *ctxt) - : gimple_opt_pass (pass_data_warn_function_noreturn, ctxt) - {} - - /* opt_pass methods: */ - bool gate () { return gate_warn_function_noreturn (); } - unsigned int execute () { return execute_warn_function_noreturn (); } - -}; // class pass_warn_function_noreturn - -} // anon namespace - -gimple_opt_pass * -make_pass_warn_function_noreturn (gcc::context *ctxt) -{ - return new pass_warn_function_noreturn (ctxt); -} - - /* Walk a gimplified function and warn for functions whose return value is ignored and attribute((warn_unused_result)) is set. This is done before inlining, so we don't have to worry about that. */ @@ -8278,6 +8223,146 @@ make_pass_warn_unused_result (gcc::context *ctxt) return new pass_warn_unused_result (ctxt); } +/* IPA passes, compilation of earlier functions or inlining + might have changed some properties, such as marked functions nothrow, + pure, const or noreturn. + Remove redundant edges and basic blocks, and create new ones if necessary. + + This pass can't be executed as stand alone pass from pass manager, because + in between inlining and this fixup the verify_flow_info would fail. */ + +unsigned int +execute_fixup_cfg (void) +{ + basic_block bb; + gimple_stmt_iterator gsi; + int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0; + gcov_type count_scale; + edge e; + edge_iterator ei; + + count_scale + = GCOV_COMPUTE_SCALE (cgraph_get_node (current_function_decl)->count, + ENTRY_BLOCK_PTR->count); + + ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count; + EXIT_BLOCK_PTR->count = apply_scale (EXIT_BLOCK_PTR->count, + count_scale); + + FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) + e->count = apply_scale (e->count, count_scale); + + FOR_EACH_BB (bb) + { + bb->count = apply_scale (bb->count, count_scale); + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + tree decl = is_gimple_call (stmt) + ? gimple_call_fndecl (stmt) + : NULL; + if (decl) + { + int flags = gimple_call_flags (stmt); + if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE)) + { + if (gimple_purge_dead_abnormal_call_edges (bb)) + todo |= TODO_cleanup_cfg; + + if (gimple_in_ssa_p (cfun)) + { + todo |= TODO_update_ssa | TODO_cleanup_cfg; + update_stmt (stmt); + } + } + + if (flags & ECF_NORETURN + && fixup_noreturn_call (stmt)) + todo |= TODO_cleanup_cfg; + } + + if (maybe_clean_eh_stmt (stmt) + && gimple_purge_dead_eh_edges (bb)) + todo |= TODO_cleanup_cfg; + } + + FOR_EACH_EDGE (e, ei, bb->succs) + e->count = apply_scale (e->count, count_scale); + + /* If we have a basic block with no successors that does not + end with a control statement or a noreturn call end it with + a call to __builtin_unreachable. This situation can occur + when inlining a noreturn call that does in fact return. */ + if (EDGE_COUNT (bb->succs) == 0) + { + gimple stmt = last_stmt (bb); + if (!stmt + || (!is_ctrl_stmt (stmt) + && (!is_gimple_call (stmt) + || (gimple_call_flags (stmt) & ECF_NORETURN) == 0))) + { + stmt = gimple_build_call + (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0); + gimple_stmt_iterator gsi = gsi_last_bb (bb); + gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); + } + } + } + if (count_scale != REG_BR_PROB_BASE) + compute_function_frequency (); + + /* We just processed all calls. */ + if (cfun->gimple_df) + vec_free (MODIFIED_NORETURN_CALLS (cfun)); + + /* Dump a textual representation of the flowgraph. */ + if (dump_file) + gimple_dump_cfg (dump_file, dump_flags); + + if (current_loops + && (todo & TODO_cleanup_cfg)) + loops_state_set (LOOPS_NEED_FIXUP); + + return todo; +} + +namespace { + +const pass_data pass_data_fixup_cfg = +{ + GIMPLE_PASS, /* type */ + "*free_cfg_annotations", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + false, /* has_gate */ + true, /* has_execute */ + TV_NONE, /* tv_id */ + PROP_cfg, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ +}; + +class pass_fixup_cfg : public gimple_opt_pass +{ +public: + pass_fixup_cfg (gcc::context *ctxt) + : gimple_opt_pass (pass_data_fixup_cfg, ctxt) + {} + + /* opt_pass methods: */ + opt_pass * clone () { return new pass_fixup_cfg (m_ctxt); } + unsigned int execute () { return execute_fixup_cfg (); } + +}; // class pass_fixup_cfg + +} // anon namespace + +gimple_opt_pass * +make_pass_fixup_cfg (gcc::context *ctxt) +{ + return new pass_fixup_cfg (ctxt); +} /* Garbage collection support for edge_def. */ |