From 893479def2f2b98d16e7311fe3bfff58ed003467 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Wed, 22 Oct 2014 14:26:56 +0000 Subject: [PATCH] cfgbuild.h: New. 2014-10-22 Andrew MacLeod * cfgbuild.h: New. Add prototypes for cfgbuild.c. * cfgcleanup.h: New. Add prototypes for cfgcleanup.c. * cfgloopmanip.h: New. Add prototypes for cfgloopmanip.c. * dominance.h: New. Add prototypes for dominance.c. * cfgloop.h: Move some prototypes/enum to cfgloopmanip.h and include it. * cfghooks.h: (struct profile_record) Relocate here. Relocate 2 prototypes from basic-block.h. * basic-block.h: Move prototypes and struct to new header files. Include cfgbuild.h, cfgcleanup.h, and dominance.h. * rtl.h: Move a few prototypes to new header files. * cfgcleanup.c (merge_memattrs): Make static. * genopinit.c (main): Add predict.h to list of includes. * predict.h: Update prototype list to match predict.c. * predict.c (maybe_hot_count_p): Export. (cgraph_edge::maybe_hot_p): Move to cgraph.c. (cgraph_node::optimize_for_size_p): Move to cgraph.h. * cgraph.h (cgraph_node::optimize_for_size_p): Relocate here. * cgraph.c (cgraph_edge::maybe_hot_p): Relocate here. * profile.h: Adjust prototypes. * ifcvt.h: New. Relocate struct ce_if_block here. * ifcvt.c: Include ifcvt.h. * config/frv/frv.c: Include ifcvt.h. * config/frv/frv-protos.h: Add 'struct' to ce_if_block * parameters. From-SVN: r216559 --- gcc/ChangeLog | 26 ++++++ gcc/basic-block.h | 174 +----------------------------------- gcc/cfgbuild.h | 28 ++++++ gcc/cfgcleanup.c | 2 +- gcc/cfgcleanup.h | 34 +++++++ gcc/cfghooks.h | 34 +++++++ gcc/cfgloop.h | 42 +-------- gcc/cfgloopmanip.h | 63 +++++++++++++ gcc/cgraph.c | 34 +++++++ gcc/cgraph.h | 13 +++ gcc/config/frv/frv-protos.h | 12 +-- gcc/config/frv/frv.c | 1 + gcc/dominance.h | 78 ++++++++++++++++ gcc/genopinit.c | 1 + gcc/ifcvt.c | 1 + gcc/ifcvt.h | 43 +++++++++ gcc/predict.c | 48 ---------- gcc/predict.h | 45 ++++++++-- gcc/profile.h | 8 +- gcc/rtl.h | 9 -- 20 files changed, 409 insertions(+), 287 deletions(-) create mode 100644 gcc/cfgbuild.h create mode 100644 gcc/cfgcleanup.h create mode 100644 gcc/cfgloopmanip.h create mode 100644 gcc/dominance.h create mode 100644 gcc/ifcvt.h diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e34b6980110..be45d7ecd2b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2014-10-22 Andrew MacLeod + + * cfgbuild.h: New. Add prototypes for cfgbuild.c. + * cfgcleanup.h: New. Add prototypes for cfgcleanup.c. + * cfgloopmanip.h: New. Add prototypes for cfgloopmanip.c. + * dominance.h: New. Add prototypes for dominance.c. + * cfgloop.h: Move some prototypes/enum to cfgloopmanip.h and include it. + * cfghooks.h: (struct profile_record) Relocate here. + Relocate 2 prototypes from basic-block.h. + * basic-block.h: Move prototypes and struct to new header files. + Include cfgbuild.h, cfgcleanup.h, and dominance.h. + * rtl.h: Move a few prototypes to new header files. + * cfgcleanup.c (merge_memattrs): Make static. + * genopinit.c (main): Add predict.h to list of includes. + * predict.h: Update prototype list to match predict.c. + * predict.c (maybe_hot_count_p): Export. + (cgraph_edge::maybe_hot_p): Move to cgraph.c. + (cgraph_node::optimize_for_size_p): Move to cgraph.h. + * cgraph.h (cgraph_node::optimize_for_size_p): Relocate here. + * cgraph.c (cgraph_edge::maybe_hot_p): Relocate here. + * profile.h: Adjust prototypes. + * ifcvt.h: New. Relocate struct ce_if_block here. + * ifcvt.c: Include ifcvt.h. + * config/frv/frv.c: Include ifcvt.h. + * config/frv/frv-protos.h: Add 'struct' to ce_if_block * parameters. + 2014-10-22 Richard Sandiford * lra.c (lra): Remove call to recog_init. diff --git a/gcc/basic-block.h b/gcc/basic-block.h index a82db077619..7731c79952e 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -33,6 +33,9 @@ along with GCC; see the file COPYING3. If not see #include "cfg.h" #include "cfganal.h" #include "lcm.h" +#include "cfgbuild.h" +#include "cfgcleanup.h" +#include "dominance.h" /* Use gcov_type to hold basic block counters. Should be at least 64bit. Although a counter cannot be negative, we use a signed @@ -85,38 +88,6 @@ enum cfg_edge_flags { #define EDGE_COMPLEX \ (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_PRESERVE) -/* Structure to gather statistic about profile consistency, per pass. - An array of this structure, indexed by pass static number, is allocated - in passes.c. The structure is defined here so that different CFG modes - can do their book-keeping via CFG hooks. - - For every field[2], field[0] is the count before the pass runs, and - field[1] is the post-pass count. This allows us to monitor the effect - of each individual pass on the profile consistency. - - This structure is not supposed to be used by anything other than passes.c - and one CFG hook per CFG mode. */ -struct profile_record -{ - /* The number of basic blocks where sum(freq) of the block's predecessors - doesn't match reasonably well with the incoming frequency. */ - int num_mismatched_freq_in[2]; - /* Likewise for a basic block's successors. */ - int num_mismatched_freq_out[2]; - /* The number of basic blocks where sum(count) of the block's predecessors - doesn't match reasonably well with the incoming frequency. */ - int num_mismatched_count_in[2]; - /* Likewise for a basic block's successors. */ - int num_mismatched_count_out[2]; - /* A weighted cost of the run-time of the function body. */ - gcov_type time[2]; - /* A weighted cost of the size of the function body. */ - int size[2]; - /* True iff this pass actually was run. */ - bool run; -}; - - struct GTY(()) rtl_bb_info { /* The first insn of the block is embedded into bb->il.x. */ /* The last insn of the block. */ @@ -249,15 +220,6 @@ enum cfg_bb_flags #define BB_COPY_PARTITION(dstbb, srcbb) \ BB_SET_PARTITION (dstbb, BB_PARTITION (srcbb)) -/* State of dominance information. */ - -enum dom_state -{ - DOM_NONE, /* Not computed at all. */ - DOM_NO_FAST_QUERY, /* The data is OK, but the fast query data are not usable. */ - DOM_OK /* Everything is ok. */ -}; - /* What sort of profiling information we have. */ enum profile_status_d { @@ -383,31 +345,6 @@ struct GTY(()) control_flow_graph { /* The two blocks that are always in the cfg. */ #define NUM_FIXED_BLOCKS (2) - -extern edge redirect_edge_succ_nodup (edge, basic_block); - -/* Structure to group all of the information to process IF-THEN and - IF-THEN-ELSE blocks for the conditional execution support. This - needs to be in a public file in case the IFCVT macros call - functions passing the ce_if_block data structure. */ - -struct ce_if_block -{ - basic_block test_bb; /* First test block. */ - basic_block then_bb; /* THEN block. */ - basic_block else_bb; /* ELSE block or NULL. */ - basic_block join_bb; /* Join THEN/ELSE blocks. */ - basic_block last_test_bb; /* Last bb to hold && or || tests. */ - int num_multiple_test_blocks; /* # of && and || basic blocks. */ - int num_and_and_blocks; /* # of && blocks. */ - int num_or_or_blocks; /* # of || blocks. */ - int num_multiple_test_insns; /* # of insns in && and || blocks. */ - int and_and_p; /* Complex test is &&. */ - int num_then_insns; /* # of insns in THEN block. */ - int num_else_insns; /* # of insns in ELSE block. */ - int pass; /* Pass number. */ -}; - /* The base value for branch probability notes and edge probabilities. */ #define REG_BR_PROB_BASE 10000 @@ -649,97 +586,6 @@ ei_cond (edge_iterator ei, edge *p) #define CLEANUP_CFGLAYOUT 32 /* Do cleanup in cfglayout mode. */ #define CLEANUP_CFG_CHANGED 64 /* The caller changed the CFG. */ -extern void dump_flow_info (FILE *, int); - -/* In predict.c */ -extern bool maybe_hot_count_p (struct function *, gcov_type); -extern bool maybe_hot_bb_p (struct function *, const_basic_block); -extern bool maybe_hot_edge_p (edge); -extern bool probably_never_executed_bb_p (struct function *, const_basic_block); -extern bool probably_never_executed_edge_p (struct function *, edge); -extern bool optimize_bb_for_size_p (const_basic_block); -extern bool optimize_bb_for_speed_p (const_basic_block); -extern bool optimize_edge_for_size_p (edge); -extern bool optimize_edge_for_speed_p (edge); -extern bool optimize_loop_for_size_p (struct loop *); -extern bool optimize_loop_for_speed_p (struct loop *); -extern bool optimize_loop_nest_for_size_p (struct loop *); -extern bool optimize_loop_nest_for_speed_p (struct loop *); -extern bool gimple_predicted_by_p (const_basic_block, enum br_predictor); -extern bool rtl_predicted_by_p (const_basic_block, enum br_predictor); -extern void gimple_predict_edge (edge, enum br_predictor, int); -extern void rtl_predict_edge (edge, enum br_predictor, int); -extern void predict_edge_def (edge, enum br_predictor, enum prediction); -extern void guess_outgoing_edge_probabilities (basic_block); -extern void remove_predictions_associated_with_edge (edge); -extern bool edge_probability_reliable_p (const_edge); -extern bool br_prob_note_reliable_p (const_rtx); -extern bool predictable_edge_p (edge); - -/* In cfgbuild.c. */ -extern void find_many_sub_basic_blocks (sbitmap); -extern void rtl_make_eh_edge (sbitmap, basic_block, rtx); - -enum replace_direction { dir_none, dir_forward, dir_backward, dir_both }; - -/* In cfgcleanup.c. */ -extern bool cleanup_cfg (int); -extern int flow_find_cross_jump (basic_block, basic_block, rtx_insn **, - rtx_insn **, enum replace_direction*); -extern int flow_find_head_matching_sequence (basic_block, basic_block, - rtx_insn **, rtx_insn **, int); - -extern bool delete_unreachable_blocks (void); - -extern bool inside_basic_block_p (const rtx_insn *); -extern bool control_flow_insn_p (const rtx_insn *); -extern rtx_insn *get_last_bb_insn (basic_block); - -/* In dominance.c */ - -enum cdi_direction -{ - CDI_DOMINATORS = 1, - CDI_POST_DOMINATORS = 2 -}; - -extern enum dom_state dom_info_state (function *, enum cdi_direction); -extern enum dom_state dom_info_state (enum cdi_direction); -extern void set_dom_info_availability (enum cdi_direction, enum dom_state); -extern bool dom_info_available_p (function *, enum cdi_direction); -extern bool dom_info_available_p (enum cdi_direction); -extern void calculate_dominance_info (enum cdi_direction); -extern void free_dominance_info (function *, enum cdi_direction); -extern void free_dominance_info (enum cdi_direction); -extern basic_block nearest_common_dominator (enum cdi_direction, - basic_block, basic_block); -extern basic_block nearest_common_dominator_for_set (enum cdi_direction, - bitmap); -extern void set_immediate_dominator (enum cdi_direction, basic_block, - basic_block); -extern basic_block get_immediate_dominator (enum cdi_direction, basic_block); -extern bool dominated_by_p (enum cdi_direction, const_basic_block, const_basic_block); -extern vec get_dominated_by (enum cdi_direction, basic_block); -extern vec get_dominated_by_region (enum cdi_direction, - basic_block *, - unsigned); -extern vec get_dominated_to_depth (enum cdi_direction, - basic_block, int); -extern vec get_all_dominated_blocks (enum cdi_direction, - basic_block); -extern void add_to_dominance_info (enum cdi_direction, basic_block); -extern void delete_from_dominance_info (enum cdi_direction, basic_block); -basic_block recompute_dominator (enum cdi_direction, basic_block); -extern void redirect_immediate_dominators (enum cdi_direction, basic_block, - basic_block); -extern void iterate_fix_dominators (enum cdi_direction, - vec , bool); -extern void verify_dominators (enum cdi_direction); -extern basic_block first_dom_son (enum cdi_direction, basic_block); -extern basic_block next_dom_son (enum cdi_direction, basic_block); -unsigned bb_dom_dfs_in (enum cdi_direction, basic_block); -unsigned bb_dom_dfs_out (enum cdi_direction, basic_block); - #include "cfghooks.h" /* Return true if BB is in a transaction. */ @@ -794,20 +640,6 @@ find_fallthru_edge (vec *edges) return e; } -/* In cfgloopmanip.c. */ -extern edge mfb_kj_edge; -extern bool mfb_keep_just (edge); - -/* In cfgexpand.c. */ -extern void rtl_profile_for_bb (basic_block); -extern void rtl_profile_for_edge (edge); -extern void default_rtl_profile (void); - -/* In profile.c. */ -typedef struct gcov_working_set_info gcov_working_set_t; -extern gcov_working_set_t *find_working_set (unsigned pct_times_10); -extern void add_working_set (gcov_working_set_t *); - /* Check tha probability is sane. */ static inline void diff --git a/gcc/cfgbuild.h b/gcc/cfgbuild.h new file mode 100644 index 00000000000..373361919c2 --- /dev/null +++ b/gcc/cfgbuild.h @@ -0,0 +1,28 @@ +/* Control flow graph building header file. + Copyright (C) 2014 Free Software Foundation, Inc. + +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 +. */ + +#ifndef GCC_CFGBUILD_H +#define GCC_CFGBUILD_H + +extern bool inside_basic_block_p (const rtx_insn *); +extern bool control_flow_insn_p (const rtx_insn *); +extern void rtl_make_eh_edge (sbitmap, basic_block, rtx); +extern void find_many_sub_basic_blocks (sbitmap); + +#endif /* GCC_CFGBUILD_H */ diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 41e2fd2671f..f4f5aa13c1b 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -872,7 +872,7 @@ merge_blocks_move (edge e, basic_block b, basic_block c, int mode) /* Removes the memory attributes of MEM expression if they are not equal. */ -void +static void merge_memattrs (rtx x, rtx y) { int i; diff --git a/gcc/cfgcleanup.h b/gcc/cfgcleanup.h new file mode 100644 index 00000000000..cb5c8a6d531 --- /dev/null +++ b/gcc/cfgcleanup.h @@ -0,0 +1,34 @@ +/* Control flow optimization header file. + Copyright (C) 2014 Free Software Foundation, Inc. + +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 +. */ + + +#ifndef GCC_CFGCLEANUP_H +#define GCC_CFGCLEANUP_H + +enum replace_direction { dir_none, dir_forward, dir_backward, dir_both }; + +extern int flow_find_cross_jump (basic_block, basic_block, rtx_insn **, + rtx_insn **, enum replace_direction*); +extern int flow_find_head_matching_sequence (basic_block, basic_block, + rtx_insn **, rtx_insn **, int); +extern bool delete_unreachable_blocks (void); +extern void delete_dead_jumptables (void); +extern bool cleanup_cfg (int); + +#endif /* GCC_CFGCLEANUP_H */ diff --git a/gcc/cfghooks.h b/gcc/cfghooks.h index 6a91bd96c6c..06a06db4c5a 100644 --- a/gcc/cfghooks.h +++ b/gcc/cfghooks.h @@ -23,6 +23,38 @@ along with GCC; see the file COPYING3. If not see /* Only basic-block.h includes this. */ +/* Structure to gather statistic about profile consistency, per pass. + An array of this structure, indexed by pass static number, is allocated + in passes.c. The structure is defined here so that different CFG modes + can do their book-keeping via CFG hooks. + + For every field[2], field[0] is the count before the pass runs, and + field[1] is the post-pass count. This allows us to monitor the effect + of each individual pass on the profile consistency. + + This structure is not supposed to be used by anything other than passes.c + and one CFG hook per CFG mode. */ +struct profile_record +{ + /* The number of basic blocks where sum(freq) of the block's predecessors + doesn't match reasonably well with the incoming frequency. */ + int num_mismatched_freq_in[2]; + /* Likewise for a basic block's successors. */ + int num_mismatched_freq_out[2]; + /* The number of basic blocks where sum(count) of the block's predecessors + doesn't match reasonably well with the incoming frequency. */ + int num_mismatched_count_in[2]; + /* Likewise for a basic block's successors. */ + int num_mismatched_count_out[2]; + /* A weighted cost of the run-time of the function body. */ + gcov_type time[2]; + /* A weighted cost of the size of the function body. */ + int size[2]; + /* True iff this pass actually was run. */ + bool run; +}; + + struct cfg_hooks { /* Name of the corresponding ir. */ @@ -156,9 +188,11 @@ struct cfg_hooks extern void verify_flow_info (void); extern void dump_bb (FILE *, basic_block, int, int); extern void dump_bb_for_graph (pretty_printer *, basic_block); +extern void dump_flow_info (FILE *, int); extern edge redirect_edge_and_branch (edge, basic_block); extern basic_block redirect_edge_and_branch_force (edge, basic_block); +extern edge redirect_edge_succ_nodup (edge, basic_block); extern bool can_remove_branch_p (const_edge); extern void remove_branch (edge); extern void remove_edge (edge); diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index f54ac1dcbd9..83c9905bc02 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "hard-reg-set.h" #include "input.h" #include "function.h" +#include "cfgloopmanip.h" /* Structure to hold decision about unrolling/peeling. */ enum lpt_dec @@ -271,8 +272,6 @@ void rescan_loop_exit (edge, bool, bool); /* Loop data structure manipulation/querying. */ extern void flow_loop_tree_node_add (struct loop *, struct loop *); extern void flow_loop_tree_node_remove (struct loop *); -extern void place_new_loop (struct function *, struct loop *); -extern void add_loop (struct loop *, struct loop *); extern bool flow_loop_nested_p (const struct loop *, const struct loop *); extern bool flow_bb_inside_loop_p (const struct loop *, const_basic_block); extern struct loop * find_common_loop (struct loop *, struct loop *); @@ -310,15 +309,6 @@ extern void remove_bb_from_loops (basic_block); extern void cancel_loop_tree (struct loop *); extern void delete_loop (struct loop *); -enum -{ - CP_SIMPLE_PREHEADERS = 1, - CP_FALLTHRU_PREHEADERS = 2 -}; - -basic_block create_preheader (struct loop *, int); -extern void create_preheaders (int); -extern void force_single_succ_latches (void); extern void verify_loop_structure (void); @@ -328,37 +318,8 @@ gcov_type expected_loop_iterations_unbounded (const struct loop *); extern unsigned expected_loop_iterations (const struct loop *); extern rtx doloop_condition_get (rtx); - -/* Loop manipulation. */ -extern bool can_duplicate_loop_p (const struct loop *loop); - -#define DLTHE_FLAG_UPDATE_FREQ 1 /* Update frequencies in - duplicate_loop_to_header_edge. */ -#define DLTHE_RECORD_COPY_NUMBER 2 /* Record copy number in the aux - field of newly create BB. */ -#define DLTHE_FLAG_COMPLETTE_PEEL 4 /* Update frequencies expecting - a complete peeling. */ - -extern edge create_empty_if_region_on_edge (edge, tree); -extern struct loop *create_empty_loop_on_edge (edge, tree, tree, tree, tree, - tree *, tree *, struct loop *); -extern struct loop * duplicate_loop (struct loop *, struct loop *); -extern void copy_loop_info (struct loop *loop, struct loop *target); -extern void duplicate_subloops (struct loop *, struct loop *); -extern bool duplicate_loop_to_header_edge (struct loop *, edge, - unsigned, sbitmap, edge, - vec *, int); -extern struct loop *loopify (edge, edge, - basic_block, edge, edge, bool, - unsigned, unsigned); -struct loop * loop_version (struct loop *, void *, - basic_block *, unsigned, unsigned, unsigned, bool); -extern bool remove_path (edge); -extern void unloop (struct loop *, bool *, bitmap); -extern void scale_loop_frequencies (struct loop *, int, int); void mark_loop_for_removal (loop_p); - /* Induction variable analysis. */ /* The description of induction variable. The things are a bit complicated @@ -742,7 +703,6 @@ enum extern void doloop_optimize_loops (void); extern void move_loop_invariants (void); -extern void scale_loop_profile (struct loop *loop, int scale, gcov_type iteration_bound); extern vec get_loop_hot_path (const struct loop *loop); /* Returns the outermost loop of the loop nest that contains LOOP.*/ diff --git a/gcc/cfgloopmanip.h b/gcc/cfgloopmanip.h new file mode 100644 index 00000000000..cbf8e7cdf36 --- /dev/null +++ b/gcc/cfgloopmanip.h @@ -0,0 +1,63 @@ +/* Loop manipulation header. + Copyright (C) 2014 Free Software Foundation, Inc. + +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 +. */ + +#ifndef GCC_CFGLOOPMANIP_H +#define GCC_CFGLOOPMANIP_H + +enum +{ + CP_SIMPLE_PREHEADERS = 1, + CP_FALLTHRU_PREHEADERS = 2 +}; + +#define DLTHE_FLAG_UPDATE_FREQ 1 /* Update frequencies in + duplicate_loop_to_header_edge. */ +#define DLTHE_RECORD_COPY_NUMBER 2 /* Record copy number in the aux + field of newly create BB. */ +#define DLTHE_FLAG_COMPLETTE_PEEL 4 /* Update frequencies expecting + a complete peeling. */ +extern edge mfb_kj_edge; + +extern bool remove_path (edge); +extern void place_new_loop (struct function *, struct loop *); +extern void add_loop (struct loop *, struct loop *); +extern void scale_loop_frequencies (struct loop *, int, int); +extern void scale_loop_profile (struct loop *, int, gcov_type); +extern edge create_empty_if_region_on_edge (edge, tree); +extern struct loop *create_empty_loop_on_edge (edge, tree, tree, tree, tree, + tree *, tree *, struct loop *); +extern struct loop *loopify (edge, edge, + basic_block, edge, edge, bool, + unsigned, unsigned); +extern void unloop (struct loop *, bool *, bitmap); +extern void copy_loop_info (struct loop *loop, struct loop *target); +extern struct loop * duplicate_loop (struct loop *, struct loop *); +extern void duplicate_subloops (struct loop *, struct loop *); +extern bool can_duplicate_loop_p (const struct loop *loop); +extern bool duplicate_loop_to_header_edge (struct loop *, edge, + unsigned, sbitmap, edge, + vec *, int); +extern bool mfb_keep_just (edge); +basic_block create_preheader (struct loop *, int); +extern void create_preheaders (int); +extern void force_single_succ_latches (void); +struct loop * loop_version (struct loop *, void *, + basic_block *, unsigned, unsigned, unsigned, bool); + +#endif /* GCC_CFGLOOPMANIP_H */ diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 6536233430d..e6af33dcb4c 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -64,6 +64,8 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "expr.h" #include "tree-dfa.h" +#include "profile.h" +#include "params.h" /* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about this. */ #include "tree-pass.h" @@ -2310,6 +2312,38 @@ cgraph_edge::cannot_lead_to_return_p (void) return callee->cannot_return_p (); } +/* Return true if the call can be hot. */ + +bool +cgraph_edge::maybe_hot_p (void) +{ + if (profile_info && flag_branch_probabilities + && !maybe_hot_count_p (NULL, count)) + return false; + if (caller->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED + || (callee + && callee->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)) + return false; + if (caller->frequency > NODE_FREQUENCY_UNLIKELY_EXECUTED + && (callee + && callee->frequency <= NODE_FREQUENCY_EXECUTED_ONCE)) + return false; + if (optimize_size) return false; + if (caller->frequency == NODE_FREQUENCY_HOT) + return true; + if (caller->frequency == NODE_FREQUENCY_EXECUTED_ONCE + && frequency < CGRAPH_FREQ_BASE * 3 / 2) + return false; + if (flag_guess_branch_prob) + { + if (PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION) == 0 + || frequency <= (CGRAPH_FREQ_BASE + / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))) + return false; + } + return true; +} + /* Return true when function can be removed from callgraph if all direct calls are eliminated. */ diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 2a55e171f98..be1f10e4165 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -2708,6 +2708,19 @@ cgraph_node::mark_force_output (void) gcc_checking_assert (!global.inlined_to); } +/* Return true if function should be optimized for size. */ + +inline bool +cgraph_node::optimize_for_size_p (void) +{ + if (optimize_size) + return true; + if (frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED) + return true; + else + return false; +} + inline symtab_node * symtab_node::get_create (tree node) { if (TREE_CODE (node) == VAR_DECL) diff --git a/gcc/config/frv/frv-protos.h b/gcc/config/frv/frv-protos.h index 927acd132bc..7bf8c7a991c 100644 --- a/gcc/config/frv/frv-protos.h +++ b/gcc/config/frv/frv-protos.h @@ -62,14 +62,14 @@ extern rtx frv_split_abs (rtx *); extern void frv_split_double_load (rtx, rtx); extern void frv_split_double_store (rtx, rtx); #ifdef BB_HEAD -extern void frv_ifcvt_init_extra_fields (ce_if_block *); -extern void frv_ifcvt_modify_tests (ce_if_block *, rtx *, rtx *); +extern void frv_ifcvt_init_extra_fields (struct ce_if_block *); +extern void frv_ifcvt_modify_tests (struct ce_if_block *, rtx *, rtx *); extern void frv_ifcvt_modify_multiple_tests - (ce_if_block *, basic_block, + (struct ce_if_block *, basic_block, rtx *, rtx *); -extern rtx frv_ifcvt_modify_insn (ce_if_block *, rtx, rtx); -extern void frv_ifcvt_modify_final (ce_if_block *); -extern void frv_ifcvt_modify_cancel (ce_if_block *); +extern rtx frv_ifcvt_modify_insn (struct ce_if_block *, rtx, rtx); +extern void frv_ifcvt_modify_final (struct ce_if_block *); +extern void frv_ifcvt_modify_cancel (struct ce_if_block *); #endif extern enum reg_class frv_secondary_reload_class (enum reg_class, diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index 4ae6d29239e..e2cfb12c60a 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -57,6 +57,7 @@ along with GCC; see the file COPYING3. If not see #include "df.h" #include "dumpfile.h" #include "builtins.h" +#include "ifcvt.h" #ifndef FRV_INLINE #define FRV_INLINE inline diff --git a/gcc/dominance.h b/gcc/dominance.h new file mode 100644 index 00000000000..0c83ba56892 --- /dev/null +++ b/gcc/dominance.h @@ -0,0 +1,78 @@ +/* Calculate (post)dominators header file. + Copyright (C) 2014 Free Software Foundation, Inc. + + 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 + . */ + +#ifndef GCC_DOMINANCE_H +#define GCC_DOMINANCE_H + +enum cdi_direction +{ + CDI_DOMINATORS = 1, + CDI_POST_DOMINATORS = 2 +}; + +/* State of dominance information. */ + +enum dom_state +{ + DOM_NONE, /* Not computed at all. */ + DOM_NO_FAST_QUERY, /* The data is OK, but the fast query data are not usable. */ + DOM_OK /* Everything is ok. */ +}; + +extern void calculate_dominance_info (enum cdi_direction); +extern void free_dominance_info (function *, enum cdi_direction); +extern void free_dominance_info (enum cdi_direction); +extern basic_block get_immediate_dominator (enum cdi_direction, basic_block); +extern void set_immediate_dominator (enum cdi_direction, basic_block, + basic_block); +extern vec get_dominated_by (enum cdi_direction, basic_block); +extern vec get_dominated_by_region (enum cdi_direction, + basic_block *, + unsigned); +extern vec get_dominated_to_depth (enum cdi_direction, + basic_block, int); +extern vec get_all_dominated_blocks (enum cdi_direction, + basic_block); +extern void redirect_immediate_dominators (enum cdi_direction, basic_block, + basic_block); +extern basic_block nearest_common_dominator (enum cdi_direction, + basic_block, basic_block); +extern basic_block nearest_common_dominator_for_set (enum cdi_direction, + bitmap); +extern bool dominated_by_p (enum cdi_direction, const_basic_block, + const_basic_block); +unsigned bb_dom_dfs_in (enum cdi_direction, basic_block); +unsigned bb_dom_dfs_out (enum cdi_direction, basic_block); +extern void verify_dominators (enum cdi_direction); +basic_block recompute_dominator (enum cdi_direction, basic_block); +extern void iterate_fix_dominators (enum cdi_direction, + vec , bool); +extern void add_to_dominance_info (enum cdi_direction, basic_block); +extern void delete_from_dominance_info (enum cdi_direction, basic_block); +extern basic_block first_dom_son (enum cdi_direction, basic_block); +extern basic_block next_dom_son (enum cdi_direction, basic_block); +extern enum dom_state dom_info_state (function *, enum cdi_direction); +extern enum dom_state dom_info_state (enum cdi_direction); +extern void set_dom_info_availability (enum cdi_direction, enum dom_state); +extern bool dom_info_available_p (function *, enum cdi_direction); +extern bool dom_info_available_p (enum cdi_direction); + + + +#endif /* GCC_DOMINANCE_H */ diff --git a/gcc/genopinit.c b/gcc/genopinit.c index ef7f674d09b..7be502626e3 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -408,6 +408,7 @@ main (int argc, char **argv) "#include \"stor-layout.h\"\n" "#include \"calls.h\"\n" "#include \"rtl.h\"\n" + "#include \"predict.h\"\n" "#include \"tm_p.h\"\n" "#include \"flags.h\"\n" "#include \"insn-config.h\"\n" diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 949d2b40ba5..a28f5c13992 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -47,6 +47,7 @@ #include "df.h" #include "dbgcnt.h" #include "shrink-wrap.h" +#include "ifcvt.h" #ifndef HAVE_conditional_move #define HAVE_conditional_move 0 diff --git a/gcc/ifcvt.h b/gcc/ifcvt.h new file mode 100644 index 00000000000..54d831d8870 --- /dev/null +++ b/gcc/ifcvt.h @@ -0,0 +1,43 @@ +/* If-conversion header file. + Copyright (C) 2014 Free Software Foundation, Inc. + + 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 + . */ + +#ifndef GCC_IFCVT_H +#define GCC_IFCVT_H + +/* Structure to group all of the information to process IF-THEN and + IF-THEN-ELSE blocks for the conditional execution support. */ + +struct ce_if_block +{ + basic_block test_bb; /* First test block. */ + basic_block then_bb; /* THEN block. */ + basic_block else_bb; /* ELSE block or NULL. */ + basic_block join_bb; /* Join THEN/ELSE blocks. */ + basic_block last_test_bb; /* Last bb to hold && or || tests. */ + int num_multiple_test_blocks; /* # of && and || basic blocks. */ + int num_and_and_blocks; /* # of && blocks. */ + int num_or_or_blocks; /* # of || blocks. */ + int num_multiple_test_insns; /* # of insns in && and || blocks. */ + int and_and_p; /* Complex test is &&. */ + int num_then_insns; /* # of insns in THEN block. */ + int num_else_insns; /* # of insns in ELSE block. */ + int pass; /* Pass number. */ +}; + +#endif /* GCC_IFCVT_H */ diff --git a/gcc/predict.c b/gcc/predict.c index 96c7661aebe..ec0c16926d9 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -190,39 +190,6 @@ maybe_hot_bb_p (struct function *fun, const_basic_block bb) return maybe_hot_frequency_p (fun, bb->frequency); } -/* Return true if the call can be hot. */ - -bool -cgraph_edge::maybe_hot_p (void) -{ - if (profile_info && flag_branch_probabilities - && !maybe_hot_count_p (NULL, count)) - return false; - if (caller->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED - || (callee - && callee->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)) - return false; - if (caller->frequency > NODE_FREQUENCY_UNLIKELY_EXECUTED - && (callee - && callee->frequency <= NODE_FREQUENCY_EXECUTED_ONCE)) - return false; - if (optimize_size) - return false; - if (caller->frequency == NODE_FREQUENCY_HOT) - return true; - if (caller->frequency == NODE_FREQUENCY_EXECUTED_ONCE - && frequency < CGRAPH_FREQ_BASE * 3 / 2) - return false; - if (flag_guess_branch_prob) - { - if (PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION) == 0 - || frequency <= (CGRAPH_FREQ_BASE - / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))) - return false; - } - return true; -} - /* Return true in case BB can be CPU intensive and should be optimized for maximal performance. */ @@ -234,8 +201,6 @@ maybe_hot_edge_p (edge e) return maybe_hot_frequency_p (cfun, EDGE_FREQUENCY (e)); } - - /* Return true if profile COUNT and FREQUENCY, or function FUN static node frequency reflects never being executed. */ @@ -304,19 +269,6 @@ probably_never_executed_edge_p (struct function *fun, edge e) return probably_never_executed (fun, e->count, EDGE_FREQUENCY (e)); } -/* Return true if function should be optimized for size. */ - -bool -cgraph_node::optimize_for_size_p (void) -{ - if (optimize_size) - return true; - if (frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED) - return true; - else - return false; -} - /* Return true when current function should always be optimized for size. */ bool diff --git a/gcc/predict.h b/gcc/predict.h index 20b495896d4..61a5d1c46f1 100644 --- a/gcc/predict.h +++ b/gcc/predict.h @@ -45,17 +45,48 @@ enum prediction TAKEN }; +extern gcov_type get_hot_bb_threshold (void); +extern void set_hot_bb_threshold (gcov_type); +extern bool maybe_hot_count_p (struct function *, gcov_type); +extern bool maybe_hot_bb_p (struct function *, const_basic_block); +extern bool maybe_hot_edge_p (edge); +extern bool probably_never_executed_bb_p (struct function *, const_basic_block); +extern bool probably_never_executed_edge_p (struct function *, edge); +extern bool optimize_function_for_size_p (struct function *); +extern bool optimize_function_for_speed_p (struct function *); +extern bool optimize_bb_for_size_p (const_basic_block); +extern bool optimize_bb_for_speed_p (const_basic_block); +extern bool optimize_edge_for_size_p (edge); +extern bool optimize_edge_for_speed_p (edge); +extern bool optimize_insn_for_size_p (void); +extern bool optimize_insn_for_speed_p (void); +extern bool optimize_loop_for_size_p (struct loop *); +extern bool optimize_loop_for_speed_p (struct loop *); +extern bool optimize_loop_nest_for_speed_p (struct loop *); +extern bool optimize_loop_nest_for_size_p (struct loop *); +extern bool predictable_edge_p (edge); +extern void rtl_profile_for_bb (basic_block); +extern void rtl_profile_for_edge (edge); +extern void default_rtl_profile (void); +extern bool rtl_predicted_by_p (const_basic_block, enum br_predictor); +extern bool gimple_predicted_by_p (const_basic_block, enum br_predictor); +extern bool edge_probability_reliable_p (const_edge); +extern bool br_prob_note_reliable_p (const_rtx); extern void predict_insn_def (rtx_insn *, enum br_predictor, enum prediction); -extern int counts_to_freqs (void); +extern void rtl_predict_edge (edge, enum br_predictor, int); +extern void gimple_predict_edge (edge, enum br_predictor, int); +extern void remove_predictions_associated_with_edge (edge); +extern void predict_edge_def (edge, enum br_predictor, enum prediction); +extern void invert_br_probabilities (rtx); +extern void guess_outgoing_edge_probabilities (basic_block); +extern void tree_estimate_probability (void); extern void handle_missing_profiles (void); +extern int counts_to_freqs (void); +extern bool expensive_function_p (int); extern void estimate_bb_frequencies (bool); -extern const char *predictor_name (enum br_predictor); -extern tree build_predict_expr (enum br_predictor, enum prediction); -extern void tree_estimate_probability (void); extern void compute_function_frequency (void); +extern tree build_predict_expr (enum br_predictor, enum prediction); +extern const char *predictor_name (enum br_predictor); extern void rebuild_frequencies (void); -extern bool optimize_function_for_size_p (struct function *); -extern bool optimize_function_for_speed_p (struct function *); - #endif /* GCC_PREDICT_H */ diff --git a/gcc/profile.h b/gcc/profile.h index 12759647912..c34a0c74c47 100644 --- a/gcc/profile.h +++ b/gcc/profile.h @@ -37,6 +37,10 @@ struct edge_profile_info #define EDGE_INFO(e) ((struct edge_profile_info *) (e)->aux) +typedef struct gcov_working_set_info gcov_working_set_t; +extern gcov_working_set_t *find_working_set (unsigned pct_times_10); +extern void add_working_set (gcov_working_set_t *); + /* Smoothes the initial assigned basic block and edge counts using a minimum cost flow algorithm. */ extern void mcf_smooth_cfg (void); @@ -52,8 +56,4 @@ extern void get_working_sets (void); profile.c. */ extern const struct gcov_ctr_summary *profile_info; -/* In predict.c. */ -extern gcov_type get_hot_bb_threshold (void); -extern void set_hot_bb_threshold (gcov_type); - #endif /* PROFILE_H */ diff --git a/gcc/rtl.h b/gcc/rtl.h index 2c614c328b6..ddd39c920cc 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -3388,9 +3388,6 @@ extern void dump_combine_stats (FILE *); extern void dump_combine_total_stats (FILE *); extern rtx make_compound_operation (rtx, enum rtx_code); -/* In cfgcleanup.c */ -extern void delete_dead_jumptables (void); - /* In sched-rgn.c. */ extern void schedule_insns (void); @@ -3531,10 +3528,6 @@ extern int stack_regs_mentioned (const_rtx insn); /* In toplev.c */ extern GTY(()) rtx stack_limit_rtx; -/* In predict.c */ -extern void invert_br_probabilities (rtx); -extern bool expensive_function_p (int); - /* In var-tracking.c */ extern unsigned int variable_tracking_main (void); @@ -3577,8 +3570,6 @@ extern void insn_locations_init (void); extern void insn_locations_finalize (void); extern void set_curr_insn_location (location_t); extern location_t curr_insn_location (void); -extern bool optimize_insn_for_size_p (void); -extern bool optimize_insn_for_speed_p (void); /* rtl-error.c */ extern void _fatal_insn_not_found (const_rtx, const char *, int, const char *) -- 2.30.2