diff options
author | Cary Coutant <ccoutant@google.com> | 2009-06-04 23:12:27 +0000 |
---|---|---|
committer | Cary Coutant <ccoutant@gcc.gnu.org> | 2009-06-04 16:12:27 -0700 |
commit | 6c52e687e487eb5bfc57399754d72e05845159d8 (patch) | |
tree | 62b2a3883be83cd19685457df195f788da6d5d99 /gcc/tree-cfg.c | |
parent | 535ff342b76110501c8673df1ae44db5e6ea55b4 (diff) | |
download | gcc-6c52e687e487eb5bfc57399754d72e05845159d8.zip gcc-6c52e687e487eb5bfc57399754d72e05845159d8.tar.gz gcc-6c52e687e487eb5bfc57399754d72e05845159d8.tar.bz2 |
basic-block.h (struct basic_block_def): Add discriminator field.
* basic-block.h (struct basic_block_def): Add discriminator field.
* dbxout.c (dbxout_source_line): Add new parameter. Change all
callers.
* debug.c (do_nothing_debug_hooks): Add additional entry.
(debug_nothing_int_charstar_int): New function.
* debug.h (struct gcc_debug_hooks): Add parameter to source_line
hook.
(debug_nothing_int_charstar_int): New declaration.
* dwarf2out.c (dwarf2out_source_line): Add new parameter. Write
discriminator value in .loc directive.
* final.c (last_discriminator): New variable.
(discriminator): New variable.
(final_start_function): Initialize above variables, pass current
discriminator to debug hook.
(notice_source_line): Check for discriminator change.
* gimple-pretty-print.c (dump_bb_header): Print discriminator value.
* sdbout.c (sdbout_source_line): New parameter.
* tree-cfg.c (struct locus_discrim_map): New structure type.
(discriminator_per_locus): New hash table.
(build_gimple_cfg): Allocate and free discriminator hash table.
(make_edges): Call assign_discriminator.
(locus_map_hash): New function.
(locus_map_eq): New function.
(next_discriminator_for_locus): New function.
(same_line_p): New function.
(assign_discriminator): New function.
(make_cond_expr_edges): Call assign_discriminator.
(make_gimple_switch_edges): Likewise.
(first_non_label_stmt): New function.
* vmsdbgout.c (vmsdbgout_source_line): Add new parameter. Change
all callers.
* xcoffout.c (xcoffout_source_line): Add new parameter.
* configure.ac (gcc_cv_as_discriminator): New configury check for
gas support for discriminator.
* configure: Regenerate.
* config.in: Regenerate.
From-SVN: r148191
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r-- | gcc/tree-cfg.c | 130 |
1 files changed, 128 insertions, 2 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 875dd8e..26a082d 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -82,6 +82,14 @@ static struct cfg_stats_d cfg_stats; /* Nonzero if we found a computed goto while building basic blocks. */ static bool found_computed_goto; +/* Hash table to store last discriminator assigned for each locus. */ +struct locus_discrim_map +{ + location_t locus; + int discriminator; +}; +static htab_t discriminator_per_locus; + /* Basic blocks and flowgraphs. */ static void make_blocks (gimple_seq); static void factor_computed_gotos (void); @@ -91,6 +99,9 @@ static void make_edges (void); static void make_cond_expr_edges (basic_block); static void make_gimple_switch_edges (basic_block); static void make_goto_expr_edges (basic_block); +static unsigned int locus_map_hash (const void *); +static int locus_map_eq (const void *, const void *); +static void assign_discriminator (location_t, basic_block); static edge gimple_redirect_edge_and_branch (edge, basic_block); static edge gimple_try_redirect_by_replacing_jump (edge, basic_block); static unsigned int split_critical_edges (void); @@ -100,6 +111,7 @@ static inline bool stmt_starts_bb_p (gimple, gimple); static int gimple_verify_flow_info (void); static void gimple_make_forwarder_block (edge); static void gimple_cfg2vcg (FILE *); +static gimple first_non_label_stmt (basic_block); /* Flowgraph optimization and cleanup. */ static void gimple_merge_blocks (basic_block, basic_block); @@ -193,8 +205,11 @@ build_gimple_cfg (gimple_seq seq) group_case_labels (); /* Create the edges of the flowgraph. */ + discriminator_per_locus = htab_create (13, locus_map_hash, locus_map_eq, + free); make_edges (); cleanup_dead_labels (); + htab_delete (discriminator_per_locus); /* Debugging dumps. */ @@ -650,7 +665,11 @@ make_edges (void) fallthru = true; if (fallthru) - make_edge (bb, bb->next_bb, EDGE_FALLTHRU); + { + make_edge (bb, bb->next_bb, EDGE_FALLTHRU); + if (last) + assign_discriminator (gimple_location (last), bb->next_bb); + } } if (root_omp_region) @@ -660,6 +679,91 @@ make_edges (void) fold_cond_expr_cond (); } +/* Trivial hash function for a location_t. ITEM is a pointer to + a hash table entry that maps a location_t to a discriminator. */ + +static unsigned int +locus_map_hash (const void *item) +{ + return ((const struct locus_discrim_map *) item)->locus; +} + +/* Equality function for the locus-to-discriminator map. VA and VB + point to the two hash table entries to compare. */ + +static int +locus_map_eq (const void *va, const void *vb) +{ + const struct locus_discrim_map *a = (const struct locus_discrim_map *) va; + const struct locus_discrim_map *b = (const struct locus_discrim_map *) vb; + return a->locus == b->locus; +} + +/* Find the next available discriminator value for LOCUS. The + discriminator distinguishes among several basic blocks that + share a common locus, allowing for more accurate sample-based + profiling. */ + +static int +next_discriminator_for_locus (location_t locus) +{ + struct locus_discrim_map item; + struct locus_discrim_map **slot; + + item.locus = locus; + item.discriminator = 0; + slot = (struct locus_discrim_map **) + htab_find_slot_with_hash (discriminator_per_locus, (void *) &item, + (hashval_t) locus, INSERT); + gcc_assert (slot); + if (*slot == HTAB_EMPTY_ENTRY) + { + *slot = XNEW (struct locus_discrim_map); + gcc_assert (*slot); + (*slot)->locus = locus; + (*slot)->discriminator = 0; + } + (*slot)->discriminator++; + return (*slot)->discriminator; +} + +/* Return TRUE if LOCUS1 and LOCUS2 refer to the same source line. */ + +static bool +same_line_p (location_t locus1, location_t locus2) +{ + expanded_location from, to; + + if (locus1 == locus2) + return true; + + from = expand_location (locus1); + to = expand_location (locus2); + + if (from.line != to.line) + return false; + if (from.file == to.file) + return true; + return (from.file != NULL + && to.file != NULL + && strcmp (from.file, to.file) == 0); +} + +/* Assign a unique discriminator value to block BB if it begins at the same + LOCUS as its predecessor block. */ + +static void +assign_discriminator (location_t locus, basic_block bb) +{ + gimple to_stmt; + + if (locus == 0 || bb->discriminator != 0) + return; + + to_stmt = first_non_label_stmt (bb); + if (to_stmt && same_line_p (locus, gimple_location (to_stmt))) + bb->discriminator = next_discriminator_for_locus (locus); +} /* Create the edges for a GIMPLE_COND starting at block BB. */ @@ -671,10 +775,13 @@ make_cond_expr_edges (basic_block bb) basic_block then_bb, else_bb; tree then_label, else_label; edge e; + location_t entry_locus; gcc_assert (entry); gcc_assert (gimple_code (entry) == GIMPLE_COND); + entry_locus = gimple_location (entry); + /* Entry basic blocks for each component. */ then_label = gimple_cond_true_label (entry); else_label = gimple_cond_false_label (entry); @@ -684,12 +791,14 @@ make_cond_expr_edges (basic_block bb) else_stmt = first_stmt (else_bb); e = make_edge (bb, then_bb, EDGE_TRUE_VALUE); + assign_discriminator (entry_locus, then_bb); e->goto_locus = gimple_location (then_stmt); if (e->goto_locus) e->goto_block = gimple_block (then_stmt); e = make_edge (bb, else_bb, EDGE_FALSE_VALUE); if (e) { + assign_discriminator (entry_locus, else_bb); e->goto_locus = gimple_location (else_stmt); if (e->goto_locus) e->goto_block = gimple_block (else_stmt); @@ -799,8 +908,11 @@ static void make_gimple_switch_edges (basic_block bb) { gimple entry = last_stmt (bb); + location_t entry_locus; size_t i, n; + entry_locus = gimple_location (entry); + n = gimple_switch_num_labels (entry); for (i = 0; i < n; ++i) @@ -808,6 +920,7 @@ make_gimple_switch_edges (basic_block bb) tree lab = CASE_LABEL (gimple_switch_label (entry, i)); basic_block label_bb = label_to_block (lab); make_edge (bb, label_bb, 0); + assign_discriminator (entry_locus, label_bb); } } @@ -880,8 +993,10 @@ make_goto_expr_edges (basic_block bb) if (simple_goto_p (goto_t)) { tree dest = gimple_goto_dest (goto_t); - edge e = make_edge (bb, label_to_block (dest), EDGE_FALLTHRU); + basic_block label_bb = label_to_block (dest); + edge e = make_edge (bb, label_bb, EDGE_FALLTHRU); e->goto_locus = gimple_location (goto_t); + assign_discriminator (e->goto_locus, label_bb); if (e->goto_locus) e->goto_block = gimple_block (goto_t); gsi_remove (&last, true); @@ -2690,6 +2805,17 @@ first_stmt (basic_block bb) return !gsi_end_p (i) ? gsi_stmt (i) : NULL; } +/* Return the first non-label statement in basic block BB. */ + +static gimple +first_non_label_stmt (basic_block bb) +{ + gimple_stmt_iterator i = gsi_start_bb (bb); + while (!gsi_end_p (i) && gimple_code (gsi_stmt (i)) == GIMPLE_LABEL) + gsi_next (&i); + return !gsi_end_p (i) ? gsi_stmt (i) : NULL; +} + /* Return the last statement in basic block BB. */ gimple |