X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fcfg.c;h=6604b02192cb24e4c5eb38e09ddff0d89cec360d;hb=2300c332eb046581a8135dabf66b9e85afec65b7;hp=d4d00a48424fa96bac34c5bd10534996a796ce2a;hpb=04a90bec0962d8033af1178899f1bf3501ff062e;p=gcc.git diff --git a/gcc/cfg.c b/gcc/cfg.c index d4d00a48424..6604b02192c 100644 --- a/gcc/cfg.c +++ b/gcc/cfg.c @@ -1,5 +1,5 @@ /* Control flow graph manipulation code for GNU compiler. - Copyright (C) 1987-2013 Free Software Foundation, Inc. + Copyright (C) 1987-2016 Free Software Foundation, Inc. This file is part of GCC. @@ -49,13 +49,12 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" -#include "obstack.h" -#include "ggc.h" -#include "hash-table.h" -#include "alloc-pool.h" +#include "backend.h" +#include "hard-reg-set.h" #include "tree.h" -#include "basic-block.h" +#include "cfghooks.h" #include "df.h" +#include "cfganal.h" #include "cfgloop.h" /* FIXME: For struct loop. */ #include "dumpfile.h" @@ -68,13 +67,13 @@ void init_flow (struct function *the_fun) { if (!the_fun->cfg) - the_fun->cfg = ggc_alloc_cleared_control_flow_graph (); + the_fun->cfg = ggc_cleared_alloc (); n_edges_for_fn (the_fun) = 0; ENTRY_BLOCK_PTR_FOR_FN (the_fun) - = ggc_alloc_cleared_basic_block_def (); + = ggc_cleared_alloc (); ENTRY_BLOCK_PTR_FOR_FN (the_fun)->index = ENTRY_BLOCK; EXIT_BLOCK_PTR_FOR_FN (the_fun) - = ggc_alloc_cleared_basic_block_def (); + = ggc_cleared_alloc (); EXIT_BLOCK_PTR_FOR_FN (the_fun)->index = EXIT_BLOCK; ENTRY_BLOCK_PTR_FOR_FN (the_fun)->next_bb = EXIT_BLOCK_PTR_FOR_FN (the_fun); @@ -86,35 +85,35 @@ init_flow (struct function *the_fun) without actually removing it from the pred/succ arrays. */ static void -free_edge (edge e) +free_edge (function *fn, edge e) { - n_edges_for_fn (cfun)--; + n_edges_for_fn (fn)--; ggc_free (e); } /* Free the memory associated with the edge structures. */ void -clear_edges (void) +clear_edges (struct function *fn) { basic_block bb; edge e; edge_iterator ei; - FOR_EACH_BB_FN (bb, cfun) + FOR_EACH_BB_FN (bb, fn) { FOR_EACH_EDGE (e, ei, bb->succs) - free_edge (e); + free_edge (fn, e); vec_safe_truncate (bb->succs, 0); vec_safe_truncate (bb->preds, 0); } - FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs) - free_edge (e); - vec_safe_truncate (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds, 0); - vec_safe_truncate (ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs, 0); + FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (fn)->succs) + free_edge (fn, e); + vec_safe_truncate (EXIT_BLOCK_PTR_FOR_FN (fn)->preds, 0); + vec_safe_truncate (ENTRY_BLOCK_PTR_FOR_FN (fn)->succs, 0); - gcc_assert (!n_edges_for_fn (cfun)); + gcc_assert (!n_edges_for_fn (fn)); } /* Allocate memory for basic_block. */ @@ -123,7 +122,7 @@ basic_block alloc_block (void) { basic_block bb; - bb = ggc_alloc_cleared_basic_block_def (); + bb = ggc_cleared_alloc (); return bb; } @@ -261,7 +260,7 @@ edge unchecked_make_edge (basic_block src, basic_block dst, int flags) { edge e; - e = ggc_alloc_cleared_edge_def (); + e = ggc_cleared_alloc (); n_edges_for_fn (cfun)++; e->src = src; @@ -348,7 +347,7 @@ remove_edge_raw (edge e) disconnect_src (e); disconnect_dest (e); - free_edge (e); + free_edge (cfun, e); } /* Redirect an edge's successor from one block to another. */ @@ -387,7 +386,7 @@ clear_bb_flags (void) { basic_block bb; - FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, next_bb) + FOR_ALL_BB_FN (bb, cfun) bb->flags &= BB_FLAGS_TO_PRESERVE; } @@ -413,20 +412,31 @@ check_bb_profile (basic_block bb, FILE * file, int indent, int flags) if (bb != EXIT_BLOCK_PTR_FOR_FN (fun)) { + bool found = false; FOR_EACH_EDGE (e, ei, bb->succs) - sum += e->probability; - if (EDGE_COUNT (bb->succs) && abs (sum - REG_BR_PROB_BASE) > 100) - fprintf (file, "%s%sInvalid sum of outgoing probabilities %.1f%%\n", - (flags & TDF_COMMENT) ? ";; " : "", s_indent, - sum * 100.0 / REG_BR_PROB_BASE); - lsum = 0; - FOR_EACH_EDGE (e, ei, bb->succs) - lsum += e->count; - if (EDGE_COUNT (bb->succs) - && (lsum - bb->count > 100 || lsum - bb->count < -100)) - fprintf (file, "%s%sInvalid sum of outgoing counts %i, should be %i\n", - (flags & TDF_COMMENT) ? ";; " : "", s_indent, - (int) lsum, (int) bb->count); + { + if (!(e->flags & EDGE_EH)) + found = true; + sum += e->probability; + } + /* Only report mismatches for non-EH control flow. If there are only EH + edges it means that the BB ends by noreturn call. Here the control + flow may just terminate. */ + if (found) + { + if (EDGE_COUNT (bb->succs) && abs (sum - REG_BR_PROB_BASE) > 100) + fprintf (file, "%s%sInvalid sum of outgoing probabilities %.1f%%\n", + (flags & TDF_COMMENT) ? ";; " : "", s_indent, + sum * 100.0 / REG_BR_PROB_BASE); + lsum = 0; + FOR_EACH_EDGE (e, ei, bb->succs) + lsum += e->count; + if (EDGE_COUNT (bb->succs) + && (lsum - bb->count > 100 || lsum - bb->count < -100)) + fprintf (file, "%s%sInvalid sum of outgoing counts %i, should be %i\n", + (flags & TDF_COMMENT) ? ";; " : "", s_indent, + (int) lsum, (int) bb->count); + } } if (bb != ENTRY_BLOCK_PTR_FOR_FN (fun)) { @@ -486,7 +496,7 @@ dump_edge_info (FILE *file, edge e, int flags, int do_succ) if (e->count && do_details) { fputs (" count:", file); - fprintf (file, HOST_WIDEST_INT_PRINT_DEC, e->count); + fprintf (file, "%" PRId64, e->count); } if (e->flags && do_details) @@ -734,8 +744,8 @@ dump_bb_info (FILE *outf, basic_block bb, int indent, int flags, if (flags & TDF_DETAILS) { struct function *fun = DECL_STRUCT_FUNCTION (current_function_decl); - fprintf (outf, ", count " HOST_WIDEST_INT_PRINT_DEC, - (HOST_WIDEST_INT) bb->count); + fprintf (outf, ", count " "%" PRId64, + (int64_t) bb->count); fprintf (outf, ", freq %i", bb->frequency); if (maybe_hot_bb_p (fun, bb)) fputs (", maybe hot", outf); @@ -743,11 +753,10 @@ dump_bb_info (FILE *outf, basic_block bb, int indent, int flags, fputs (", probably never executed", outf); } fputc ('\n', outf); - if (TDF_DETAILS) - check_bb_profile (bb, outf, indent, flags); if (flags & TDF_DETAILS) { + check_bb_profile (bb, outf, indent, flags); if (flags & TDF_COMMENT) fputs (";; ", outf); fprintf (outf, "%s prev block ", s_indent); @@ -962,7 +971,7 @@ scale_bbs_frequencies_int (basic_block *bbs, int nbbs, int num, int den) /* numbers smaller than this value are safe to multiply without getting 64bit overflow. */ -#define MAX_SAFE_MULTIPLIER (1 << (sizeof (HOST_WIDEST_INT) * 4 - 1)) +#define MAX_SAFE_MULTIPLIER (1 << (sizeof (int64_t) * 4 - 1)) /* Multiply all frequencies of basic blocks in array BBS of length NBBS by NUM/DEN, in gcov_type arithmetic. More accurate than previous @@ -1016,49 +1025,57 @@ struct htab_bb_copy_original_entry int index2; }; -struct bb_copy_hasher : typed_noop_remove +struct bb_copy_hasher : nofree_ptr_hash { - typedef htab_bb_copy_original_entry value_type; - typedef htab_bb_copy_original_entry compare_type; - static inline hashval_t hash (const value_type *); - static inline bool equal (const value_type *existing, - const compare_type * candidate); + static inline hashval_t hash (const htab_bb_copy_original_entry *); + static inline bool equal (const htab_bb_copy_original_entry *existing, + const htab_bb_copy_original_entry * candidate); }; inline hashval_t -bb_copy_hasher::hash (const value_type *data) +bb_copy_hasher::hash (const htab_bb_copy_original_entry *data) { return data->index1; } inline bool -bb_copy_hasher::equal (const value_type *data, const compare_type *data2) +bb_copy_hasher::equal (const htab_bb_copy_original_entry *data, + const htab_bb_copy_original_entry *data2) { return data->index1 == data2->index1; } /* Data structures used to maintain mapping between basic blocks and copies. */ -static hash_table bb_original; -static hash_table bb_copy; +static hash_table *bb_original; +static hash_table *bb_copy; /* And between loops and copies. */ -static hash_table loop_copy; -static alloc_pool original_copy_bb_pool; - +static hash_table *loop_copy; +static object_allocator *original_copy_bb_pool; /* Initialize the data structures to maintain mapping between blocks and its copies. */ void initialize_original_copy_tables (void) { - gcc_assert (!original_copy_bb_pool); - original_copy_bb_pool - = create_alloc_pool ("original_copy", - sizeof (struct htab_bb_copy_original_entry), 10); - bb_original.create (10); - bb_copy.create (10); - loop_copy.create (10); + original_copy_bb_pool = new object_allocator + ("original_copy"); + bb_original = new hash_table (10); + bb_copy = new hash_table (10); + loop_copy = new hash_table (10); +} + +/* Reset the data structures to maintain mapping between blocks and + its copies. */ + +void +reset_original_copy_tables (void) +{ + gcc_assert (original_copy_bb_pool); + bb_original->empty (); + bb_copy->empty (); + loop_copy->empty (); } /* Free the data structures to maintain mapping between blocks and @@ -1067,17 +1084,20 @@ void free_original_copy_tables (void) { gcc_assert (original_copy_bb_pool); - bb_copy.dispose (); - bb_original.dispose (); - loop_copy.dispose (); - free_alloc_pool (original_copy_bb_pool); + delete bb_copy; + bb_copy = NULL; + delete bb_original; + bb_original = NULL; + delete loop_copy; + loop_copy = NULL; + delete original_copy_bb_pool; original_copy_bb_pool = NULL; } /* Removes the value associated with OBJ from table TAB. */ static void -copy_original_table_clear (hash_table tab, unsigned obj) +copy_original_table_clear (hash_table *tab, unsigned obj) { htab_bb_copy_original_entry **slot; struct htab_bb_copy_original_entry key, *elt; @@ -1086,20 +1106,20 @@ copy_original_table_clear (hash_table tab, unsigned obj) return; key.index1 = obj; - slot = tab.find_slot (&key, NO_INSERT); + slot = tab->find_slot (&key, NO_INSERT); if (!slot) return; elt = *slot; - tab.clear_slot (slot); - pool_free (original_copy_bb_pool, elt); + tab->clear_slot (slot); + original_copy_bb_pool->remove (elt); } /* Sets the value associated with OBJ in table TAB to VAL. Do nothing when data structures are not initialized. */ static void -copy_original_table_set (hash_table tab, +copy_original_table_set (hash_table *tab, unsigned obj, unsigned val) { struct htab_bb_copy_original_entry **slot; @@ -1109,11 +1129,10 @@ copy_original_table_set (hash_table tab, return; key.index1 = obj; - slot = tab.find_slot (&key, INSERT); + slot = tab->find_slot (&key, INSERT); if (!*slot) { - *slot = (struct htab_bb_copy_original_entry *) - pool_alloc (original_copy_bb_pool); + *slot = original_copy_bb_pool->allocate (); (*slot)->index1 = obj; } (*slot)->index2 = val; @@ -1137,7 +1156,7 @@ get_bb_original (basic_block bb) gcc_assert (original_copy_bb_pool); key.index1 = bb->index; - entry = bb_original.find (&key); + entry = bb_original->find (&key); if (entry) return BASIC_BLOCK_FOR_FN (cfun, entry->index2); else @@ -1162,7 +1181,7 @@ get_bb_copy (basic_block bb) gcc_assert (original_copy_bb_pool); key.index1 = bb->index; - entry = bb_copy.find (&key); + entry = bb_copy->find (&key); if (entry) return BASIC_BLOCK_FOR_FN (cfun, entry->index2); else @@ -1192,7 +1211,7 @@ get_loop_copy (struct loop *loop) gcc_assert (original_copy_bb_pool); key.index1 = loop->num; - entry = loop_copy.find (&key); + entry = loop_copy->find (&key); if (entry) return get_loop (cfun, entry->index2); else