This patch backports r199154 from google-4_8 to google-4_9 Bootstrapped and passed regression test.
OK for google-4_9 branch? Thanks, Dehao
Index: gcc/final.c =================================================================== --- gcc/final.c (revision 210329) +++ gcc/final.c (working copy) @@ -125,9 +125,6 @@ static int last_linenum; /* Last discriminator written to assembly. */ static int last_discriminator; -/* Discriminator of current block. */ -static int discriminator; - /* Highest line number in current block. */ static int high_block_linenum; @@ -137,9 +134,10 @@ static int high_function_linenum; /* Filename of last NOTE. */ static const char *last_filename; -/* Override filename and line number. */ +/* Override filename, line number, and discriminator. */ static const char *override_filename; static int override_linenum; +static int override_discriminator; /* Whether to force emission of a line note before the next insn. */ static bool force_source_line = false; @@ -1738,7 +1736,7 @@ final_start_function (rtx first, FILE *file, last_filename = LOCATION_FILE (prologue_location); last_linenum = LOCATION_LINE (prologue_location); - last_discriminator = discriminator = 0; + last_discriminator = 0; high_block_linenum = high_function_linenum = last_linenum; @@ -2194,8 +2192,6 @@ final_scan_insn (rtx insn, FILE *file, int optimiz if (targetm.asm_out.unwind_emit) targetm.asm_out.unwind_emit (asm_out_file, insn); - discriminator = NOTE_BASIC_BLOCK (insn)->discriminator; - break; case NOTE_INSN_EH_REGION_BEG: @@ -2288,6 +2284,8 @@ final_scan_insn (rtx insn, FILE *file, int optimiz { override_filename = LOCATION_FILE (*locus_ptr); override_linenum = LOCATION_LINE (*locus_ptr); + override_discriminator = + get_discriminator_from_locus (*locus_ptr); } } break; @@ -2321,11 +2319,14 @@ final_scan_insn (rtx insn, FILE *file, int optimiz { override_filename = LOCATION_FILE (*locus_ptr); override_linenum = LOCATION_LINE (*locus_ptr); + override_discriminator = + get_discriminator_from_locus (*locus_ptr); } else { override_filename = NULL; override_linenum = 0; + override_discriminator = 0; } } break; @@ -3008,6 +3009,17 @@ final_scan_insn (rtx insn, FILE *file, int optimiz } return NEXT_INSN (insn); } + +/* Return discriminator of the statement that produced this insn. */ +int +insn_discriminator (const_rtx insn) +{ + location_t loc = INSN_LOCATION (insn); + if (!loc) + return 0; + return get_discriminator_from_locus (loc); +} + /* Return whether a source line note needs to be emitted before INSN. Sets IS_STMT to TRUE if the line should be marked as a possible @@ -3018,16 +3030,19 @@ notice_source_line (rtx insn, bool *is_stmt) { const char *filename; int linenum; + int discriminator; if (override_filename) { filename = override_filename; linenum = override_linenum; + discriminator = override_discriminator; } else { filename = insn_file (insn); linenum = insn_line (insn); + discriminator = insn_discriminator (insn); } if (filename == NULL) Index: gcc/input.c =================================================================== --- gcc/input.c (revision 210329) +++ gcc/input.c (working copy) @@ -109,6 +109,11 @@ location_t input_location; struct line_maps *line_table; +static vec<location_t> discriminator_location_locations; +static vec<int> discriminator_location_discriminators; +static location_t next_discriminator_location = UNKNOWN_LOCATION; +static location_t min_discriminator_location = UNKNOWN_LOCATION; + static fcache *fcache_tab; static const size_t fcache_tab_size = 16; static const size_t fcache_buffer_size = 4 * 1024; @@ -143,6 +148,13 @@ expand_location_1 (source_location loc, loc = LOCATION_LOCUS (loc); } + /* If LOC describes a location with a discriminator, extract the + discriminator and map it to the real location. */ + if (min_discriminator_location != UNKNOWN_LOCATION + && loc >= min_discriminator_location + && loc < next_discriminator_location) + loc = map_discriminator_location (loc); + memset (&xloc, 0, sizeof (xloc)); if (loc >= RESERVED_LOCATION_COUNT) @@ -852,3 +864,84 @@ dump_line_table_statistics (void) STAT_LABEL (total_used_map_size)); fprintf (stderr, "\n"); } + +/* Associate the DISCRIMINATOR with LOCUS, and return a new locus. + We associate discriminators with a locus by allocating location_t + values beyond those assigned by libcpp. Each new value is mapped + directly to a real location_t value, and separately to the + discriminator. */ + +location_t +location_with_discriminator (location_t locus, int discriminator) +{ + tree block = LOCATION_BLOCK (locus); + location_t ret; + int i; + locus = map_discriminator_location (locus); + + if (locus == UNKNOWN_LOCATION) + return block ? COMBINE_LOCATION_DATA (line_table, locus, block) + : locus; + + if (min_discriminator_location == UNKNOWN_LOCATION) + { + min_discriminator_location = line_table->highest_location + 1; + next_discriminator_location = min_discriminator_location; + } + + /* Traverse the last few discriminator_locations to see if we can reuse + the entry. */ + for (i = next_discriminator_location - min_discriminator_location - 1; + (i >= 0 && LOCATION_LINE (discriminator_location_locations[i]) == + LOCATION_LINE (locus) + && discriminator_location_discriminators[i] == discriminator); + i--) + if (discriminator_location_locations[i] == locus) + return (block + ? COMBINE_LOCATION_DATA (line_table, min_discriminator_location + i, + block) + : min_discriminator_location + i); + + discriminator_location_locations.safe_push(locus); + discriminator_location_discriminators.safe_push(discriminator); + + ret = (block + ? COMBINE_LOCATION_DATA (line_table, next_discriminator_location, block) + : next_discriminator_location); + + next_discriminator_location++; + return ret; +} + +/* Return TRUE if LOCUS represents a location with a discriminator. */ + +bool +has_discriminator (location_t locus) +{ + locus = LOCATION_LOCUS (locus); + return (min_discriminator_location != UNKNOWN_LOCATION + && locus >= min_discriminator_location + && locus < next_discriminator_location); +} + +/* Return the real location_t value for LOCUS. */ + +location_t +map_discriminator_location (location_t locus) +{ + locus = LOCATION_LOCUS (locus); + if (! has_discriminator (locus)) + return locus; + return (location_t) discriminator_location_locations[locus - min_discriminator_location]; +} + +/* Return the discriminator for LOCUS. */ + +int +get_discriminator_from_locus (location_t locus) +{ + locus = LOCATION_LOCUS (locus); + if (! has_discriminator (locus)) + return 0; + return discriminator_location_discriminators[locus - min_discriminator_location]; +} Index: gcc/input.h =================================================================== --- gcc/input.h (revision 210329) +++ gcc/input.h (working copy) @@ -48,6 +48,11 @@ typedef source_location location_t; extern location_t input_location; +extern location_t location_with_discriminator (location_t, int); +extern bool has_discriminator (location_t); +extern location_t map_discriminator_location (location_t); +extern int get_discriminator_from_locus (location_t); + #define LOCATION_FILE(LOC) ((expand_location (LOC)).file) #define LOCATION_LINE(LOC) ((expand_location (LOC)).line) #define LOCATION_COLUMN(LOC)((expand_location (LOC)).column) @@ -59,7 +64,8 @@ extern location_t input_location; : NULL)) #define in_system_header_at(LOC) \ - ((linemap_location_in_system_header_p (line_table, LOC))) + ((linemap_location_in_system_header_p (line_table, \ + map_discriminator_location (LOC)))) void dump_line_table_statistics (void); Index: gcc/basic-block.h =================================================================== --- gcc/basic-block.h (revision 210329) +++ gcc/basic-block.h (working copy) @@ -201,11 +201,6 @@ struct GTY((chain_next ("%h.next_bb"), chain_prev /* Expected frequency. Normalized to be in range 0 to BB_FREQ_MAX. */ int frequency; - - /* The discriminator for this block. The discriminator distinguishes - among several basic blocks that share a common locus, allowing for - more accurate sample-based profiling. */ - int discriminator; }; /* This ensures that struct gimple_bb_info is smaller than Index: gcc/tree-cfg.c =================================================================== --- gcc/tree-cfg.c (revision 210329) +++ gcc/tree-cfg.c (working copy) @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "flags.h" +#include "input.h" #include "function.h" #include "gimple-pretty-print.h" #include "pointer-set.h" @@ -959,6 +960,32 @@ same_line_p (location_t locus1, location_t locus2) && filename_cmp (from.file, to.file) == 0); } +/* Assign a unique discriminator value to instructions in block BB that + have the same LOCUS as its predecessor block. */ + +static void +assign_discriminator (location_t locus, basic_block bb) +{ + gimple_stmt_iterator gsi; + int discriminator; + + locus = map_discriminator_location (locus); + + if (locus == UNKNOWN_LOCATION) + return; + + discriminator = next_discriminator_for_locus (locus); + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + location_t stmt_locus = gimple_location (stmt); + if (same_line_p (locus, stmt_locus)) + gimple_set_location (stmt, + location_with_discriminator (stmt_locus, discriminator)); + } +} + /* Assign discriminators to each basic block. */ static void @@ -970,9 +997,37 @@ assign_discriminators (void) { edge e; edge_iterator ei; + gimple_stmt_iterator gsi; gimple last = last_stmt (bb); location_t locus = last ? gimple_location (last) : UNKNOWN_LOCATION; + location_t curr_locus = UNKNOWN_LOCATION; + int curr_discr = 0; + /* Traverse the basic block, if two function calls within a basic block + are mapped to a same line, assign a new discriminator because a call + stmt could be a split point of a basic block. */ + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + if (curr_locus == UNKNOWN_LOCATION) + { + curr_locus = gimple_location (stmt); + } + else if (!same_line_p (curr_locus, gimple_location (stmt))) + { + curr_locus = gimple_location (stmt); + curr_discr = 0; + } + else if (curr_discr != 0) + { + gimple_set_location (stmt, location_with_discriminator ( + gimple_location (stmt), curr_discr)); + } + /* Allocate a new discriminator for CALL stmt. */ + if (gimple_code (stmt) == GIMPLE_CALL) + curr_discr = next_discriminator_for_locus (curr_locus); + } + if (locus == UNKNOWN_LOCATION) continue; @@ -983,10 +1038,12 @@ assign_discriminators (void) if ((first && same_line_p (locus, gimple_location (first))) || (last && same_line_p (locus, gimple_location (last)))) { - if (e->dest->discriminator != 0 && bb->discriminator == 0) - bb->discriminator = next_discriminator_for_locus (locus); + if (((first && has_discriminator (gimple_location (first))) + || (last && has_discriminator (gimple_location (last)))) + && !has_discriminator (locus)) + assign_discriminator (locus, bb); else - e->dest->discriminator = next_discriminator_for_locus (locus); + assign_discriminator (locus, e->dest); } } } Index: gcc/cfghooks.c =================================================================== --- gcc/cfghooks.c (revision 210329) +++ gcc/cfghooks.c (working copy) @@ -500,7 +500,6 @@ split_block (basic_block bb, void *i) new_bb->count = bb->count; new_bb->frequency = bb->frequency; - new_bb->discriminator = bb->discriminator; if (dom_info_available_p (CDI_DOMINATORS)) { Index: gcc/tree-pretty-print.c =================================================================== --- gcc/tree-pretty-print.c (revision 210329) +++ gcc/tree-pretty-print.c (working copy) @@ -668,6 +668,7 @@ static void dump_location (pretty_printer *buffer, location_t loc) { expanded_location xloc = expand_location (loc); + int discriminator = get_discriminator_from_locus (loc); pp_left_bracket (buffer); if (xloc.file) @@ -676,6 +677,11 @@ dump_location (pretty_printer *buffer, location_t pp_string (buffer, " : "); } pp_decimal_int (buffer, xloc.line); + if (discriminator) + { + pp_string (buffer, " discrim "); + pp_decimal_int (buffer, discriminator); + } pp_string (buffer, "] "); } Index: gcc/rtl.h =================================================================== --- gcc/rtl.h (revision 210329) +++ gcc/rtl.h (working copy) @@ -1920,6 +1920,7 @@ extern rtx prev_cc0_setter (rtx); extern int insn_line (const_rtx); extern const char * insn_file (const_rtx); extern tree insn_scope (const_rtx); +extern int insn_discriminator (const_rtx); extern location_t prologue_location, epilogue_location; /* In jump.c */ Index: gcc/print-rtl.c =================================================================== --- gcc/print-rtl.c (revision 210329) +++ gcc/print-rtl.c (working copy) @@ -410,8 +410,13 @@ print_rtx (const_rtx in_rtx) redundant with line number information and do not print anything when there is no location information available. */ if (INSN_LOCATION (in_rtx) && insn_file (in_rtx)) - fprintf (outfile, " %s:%i", insn_file (in_rtx), - insn_line (in_rtx)); + { + int discriminator = insn_discriminator (in_rtx); + fprintf (outfile, " %s:%i", insn_file (in_rtx), + insn_line (in_rtx)); + if (discriminator) + fprintf (outfile, " discrim %d", discriminator); + } #endif } else if (i == 6 && GET_CODE (in_rtx) == ASM_OPERANDS) Index: gcc/gimple-pretty-print.c =================================================================== --- gcc/gimple-pretty-print.c (revision 210329) +++ gcc/gimple-pretty-print.c (working copy) @@ -2057,7 +2057,9 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple g if ((flags & TDF_LINENO) && gimple_has_location (gs)) { - expanded_location xloc = expand_location (gimple_location (gs)); + location_t loc = gimple_location (gs); + expanded_location xloc = expand_location (loc); + int discriminator = get_discriminator_from_locus (loc); pp_left_bracket (buffer); if (xloc.file) { @@ -2067,6 +2069,11 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple g pp_decimal_int (buffer, xloc.line); pp_colon (buffer); pp_decimal_int (buffer, xloc.column); + if (discriminator) + { + pp_string (buffer, " discrim "); + pp_decimal_int (buffer, discriminator); + } pp_string (buffer, "] "); } @@ -2268,8 +2275,6 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, indent, "", get_lineno (gsi_stmt (gsi))); break; } - if (bb->discriminator) - fprintf (outf, ", discriminator %i", bb->discriminator); fputc ('\n', outf); } }