diff options
author | Ben Cheng <bccheng@google.com> | 2013-03-28 11:14:20 -0700 |
---|---|---|
committer | Ben Cheng <bccheng@google.com> | 2013-03-28 12:40:33 -0700 |
commit | af0c51ac87ab2a87caa03fa108f0d164987a2764 (patch) | |
tree | 4b8b470f7c5b69642fdab8d0aa1fbc148d02196b /gcc-4.8/gcc/tree-optimize.c | |
parent | d87cae247d39ebf4f5a6bf25c932a14d2fdb9384 (diff) | |
download | toolchain_gcc-af0c51ac87ab2a87caa03fa108f0d164987a2764.tar.gz toolchain_gcc-af0c51ac87ab2a87caa03fa108f0d164987a2764.tar.bz2 toolchain_gcc-af0c51ac87ab2a87caa03fa108f0d164987a2764.zip |
[GCC 4.8] Initial check-in of GCC 4.8.0
Change-Id: I0719d8a6d0f69b367a6ab6f10eb75622dbf12771
Diffstat (limited to 'gcc-4.8/gcc/tree-optimize.c')
-rw-r--r-- | gcc-4.8/gcc/tree-optimize.c | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/gcc-4.8/gcc/tree-optimize.c b/gcc-4.8/gcc/tree-optimize.c new file mode 100644 index 000000000..3f69fb310 --- /dev/null +++ b/gcc-4.8/gcc/tree-optimize.c @@ -0,0 +1,234 @@ +/* Top-level control of tree optimizations. + Copyright (C) 2001-2013 Free Software Foundation, Inc. + Contributed by Diego Novillo <dnovillo@redhat.com> + +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 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +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 COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "tm_p.h" +#include "basic-block.h" +#include "flags.h" +#include "tree-flow.h" +#include "function.h" +#include "langhooks.h" +#include "diagnostic-core.h" +#include "toplev.h" +#include "flags.h" +#include "cgraph.h" +#include "tree-inline.h" +#include "tree-pass.h" +#include "ggc.h" +#include "cgraph.h" +#include "cfgloop.h" +#include "except.h" +#include "plugin.h" + + +/* Pass: cleanup the CFG just before expanding trees to RTL. + This is just a round of label cleanups and case node grouping + because after the tree optimizers have run such cleanups may + be necessary. */ + +static unsigned int +execute_cleanup_cfg_post_optimizing (void) +{ + unsigned int todo = 0; + if (cleanup_tree_cfg ()) + todo |= TODO_update_ssa; + maybe_remove_unreachable_handlers (); + cleanup_dead_labels (); + group_case_labels (); + if ((flag_compare_debug_opt || flag_compare_debug) + && flag_dump_final_insns) + { + FILE *final_output = fopen (flag_dump_final_insns, "a"); + + if (!final_output) + { + error ("could not open final insn dump file %qs: %m", + flag_dump_final_insns); + flag_dump_final_insns = NULL; + } + else + { + int save_unnumbered = flag_dump_unnumbered; + int save_noaddr = flag_dump_noaddr; + + flag_dump_noaddr = flag_dump_unnumbered = 1; + fprintf (final_output, "\n"); + dump_enumerated_decls (final_output, dump_flags | TDF_NOUID); + flag_dump_noaddr = save_noaddr; + flag_dump_unnumbered = save_unnumbered; + if (fclose (final_output)) + { + error ("could not close final insn dump file %qs: %m", + flag_dump_final_insns); + flag_dump_final_insns = NULL; + } + } + } + return todo; +} + +struct gimple_opt_pass pass_cleanup_cfg_post_optimizing = +{ + { + GIMPLE_PASS, + "optimized", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + NULL, /* gate */ + execute_cleanup_cfg_post_optimizing, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_TREE_CLEANUP_CFG, /* tv_id */ + PROP_cfg, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_remove_unused_locals /* todo_flags_finish */ + } +}; + +/* 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; + + if (ENTRY_BLOCK_PTR->count) + count_scale = ((cgraph_get_node (current_function_decl)->count + * REG_BR_PROB_BASE + ENTRY_BLOCK_PTR->count / 2) + / ENTRY_BLOCK_PTR->count); + else + count_scale = REG_BR_PROB_BASE; + + ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count; + EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale + + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; + + FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) + e->count = (e->count * count_scale + + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; + + FOR_EACH_BB (bb) + { + bb->count = (bb->count * count_scale + + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; + 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 = (e->count * count_scale + + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; + + /* 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); + + return todo; +} + +struct gimple_opt_pass pass_fixup_cfg = +{ + { + GIMPLE_PASS, + "*free_cfg_annotations", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + NULL, /* gate */ + execute_fixup_cfg, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_NONE, /* tv_id */ + PROP_cfg, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0 /* todo_flags_finish */ + } +}; |