diff options
-rw-r--r-- | gcc/gimple-streamer-in.c | 19 | ||||
-rw-r--r-- | gcc/gimple-streamer-out.c | 12 | ||||
-rw-r--r-- | gcc/gimple.h | 16 | ||||
-rw-r--r-- | gcc/lto-streamer-in.c | 111 | ||||
-rw-r--r-- | gcc/lto-streamer-out.c | 80 | ||||
-rw-r--r-- | gcc/lto-streamer.c | 1 | ||||
-rw-r--r-- | gcc/lto-streamer.h | 16 | ||||
-rw-r--r-- | gcc/streamer-hooks.h | 14 |
8 files changed, 200 insertions, 69 deletions
diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c index 87dd962e610..3bd4a86b156 100644 --- a/gcc/gimple-streamer-in.c +++ b/gcc/gimple-streamer-in.c @@ -57,11 +57,7 @@ input_phi (class lto_input_block *ib, basic_block bb, class data_in *data_in, tree def = stream_read_tree (ib, data_in); int src_index = streamer_read_uhwi (ib); bitpack_d bp = streamer_read_bitpack (ib); - /* Do not cache a location - we do not have API to get pointer to the - location in PHI statement and we may trigger reallocation. */ - location_t arg_loc = stream_input_location_now (&bp, data_in); basic_block sbb = BASIC_BLOCK_FOR_FN (fn, src_index); - edge e = NULL; int j; @@ -72,7 +68,11 @@ input_phi (class lto_input_block *ib, basic_block bb, class data_in *data_in, break; } - add_phi_arg (result, def, e, arg_loc); + add_phi_arg (result, def, e, UNKNOWN_LOCATION); + /* Read location and lexical block information. */ + location_t *arg_locp = gimple_phi_arg_location_ptr (result, e->dest_idx); + data_in->location_cache.input_location_and_block (arg_locp, &bp, ib, + data_in); } return result; @@ -106,12 +106,9 @@ input_gimple_stmt (class lto_input_block *ib, class data_in *data_in, has_hist = bp_unpack_value (&bp, 1); stmt->subcode = bp_unpack_var_len_unsigned (&bp); - /* Read location information. Caching here makes no sense until streamer - cache can handle the following gimple_set_block. */ - gimple_set_location (stmt, stream_input_location_now (&bp, data_in)); - - /* Read lexical block reference. */ - gimple_set_block (stmt, stream_read_tree (ib, data_in)); + /* Read location and lexical block information. */ + data_in->location_cache.input_location_and_block (gimple_location_ptr (stmt), + &bp, ib, data_in); /* Read in all the operands. */ switch (code) diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c index 232453713dc..2e55c5f3d1e 100644 --- a/gcc/gimple-streamer-out.c +++ b/gcc/gimple-streamer-out.c @@ -48,8 +48,8 @@ output_phi (struct output_block *ob, gphi *phi) stream_write_tree (ob, gimple_phi_arg_def (phi, i), true); streamer_write_uhwi (ob, gimple_phi_arg_edge (phi, i)->src->index); bitpack_d bp = bitpack_create (ob->main_stream); - stream_output_location (ob, &bp, gimple_phi_arg_location (phi, i)); - streamer_write_bitpack (&bp); + location_t loc = gimple_phi_arg_location (phi, i); + stream_output_location_and_block (ob, &bp, loc); } } @@ -84,12 +84,8 @@ output_gimple_stmt (struct output_block *ob, struct function *fn, gimple *stmt) bp_pack_value (&bp, hist != NULL, 1); bp_pack_var_len_unsigned (&bp, stmt->subcode); - /* Emit location information for the statement. */ - stream_output_location (ob, &bp, LOCATION_LOCUS (gimple_location (stmt))); - streamer_write_bitpack (&bp); - - /* Emit the lexical block holding STMT. */ - stream_write_tree (ob, gimple_block (stmt), true); + /* Emit location information for the statement, including gimple_block. */ + stream_output_location_and_block (ob, &bp, gimple_location (stmt)); /* Emit the operands. */ switch (gimple_code (stmt)) diff --git a/gcc/gimple.h b/gcc/gimple.h index 6f7c7ff6a5f..6cc7e66059d 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1879,6 +1879,14 @@ gimple_set_location (gimple *g, location_t location) g->location = location; } +/* Return address of the location information for statement G. */ + +static inline location_t * +gimple_location_ptr (gimple *g) +{ + return &g->location; +} + /* Return true if G contains location information. */ @@ -4581,6 +4589,14 @@ gimple_phi_arg_set_location (gphi *phi, size_t i, location_t loc) gimple_phi_arg (phi, i)->locus = loc; } +/* Return address of source location of gimple argument I of phi node PHI. */ + +static inline location_t * +gimple_phi_arg_location_ptr (gphi *phi, size_t i) +{ + return &gimple_phi_arg (phi, i)->locus; +} + /* Return TRUE if argument I of phi node PHI has a location record. */ static inline bool diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index e02d69cc196..478125aed19 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -156,7 +156,18 @@ lto_location_cache::cmp_loc (const void *pa, const void *pb) return a->sysp ? 1 : -1; if (a->line != b->line) return a->line - b->line; - return a->col - b->col; + if (a->col != b->col) + return a->col - b->col; + if ((a->block == NULL_TREE) != (b->block == NULL_TREE)) + return a->block ? 1 : -1; + if (a->block) + { + if (BLOCK_NUMBER (a->block) < BLOCK_NUMBER (b->block)) + return -1; + if (BLOCK_NUMBER (a->block) > BLOCK_NUMBER (b->block)) + return 1; + } + return 0; } /* Apply all changes in location cache. Add locations into linemap and patch @@ -191,22 +202,33 @@ lto_location_cache::apply_location_cache () linemap_line_start (line_table, loc.line, max + 1); } gcc_assert (*loc.loc == BUILTINS_LOCATION + 1); - if (current_file == loc.file && current_line == loc.line - && current_col == loc.col) - *loc.loc = current_loc; - else - current_loc = *loc.loc = linemap_position_for_column (line_table, - loc.col); + if (current_file != loc.file + || current_line != loc.line + || current_col != loc.col) + { + current_loc = linemap_position_for_column (line_table, loc.col); + if (loc.block) + current_loc = set_block (current_loc, loc.block); + } + else if (current_block != loc.block) + { + if (loc.block) + current_loc = set_block (current_loc, loc.block); + else + current_loc = LOCATION_LOCUS (current_loc); + } + *loc.loc = current_loc; current_line = loc.line; prev_file = current_file = loc.file; current_col = loc.col; + current_block = loc.block; } loc_cache.truncate (0); accepted_length = 0; return true; } -/* Tree merging did not suceed; mark all changes in the cache as accepted. */ +/* Tree merging did not succeed; mark all changes in the cache as accepted. */ void lto_location_cache::accept_location_cache () @@ -215,7 +237,7 @@ lto_location_cache::accept_location_cache () accepted_length = loc_cache.length (); } -/* Tree merging did suceed; throw away recent changes. */ +/* Tree merging did succeed; throw away recent changes. */ void lto_location_cache::revert_location_cache () @@ -223,33 +245,46 @@ lto_location_cache::revert_location_cache () loc_cache.truncate (accepted_length); } -/* Read a location bitpack from input block IB and either update *LOC directly - or add it to the location cache. +/* Read a location bitpack from bit pack BP and either update *LOC directly + or add it to the location cache. If IB is non-NULL, stream in a block + afterwards. It is neccesary to call apply_location_cache to get *LOC updated. */ void -lto_location_cache::input_location (location_t *loc, struct bitpack_d *bp, - class data_in *data_in) +lto_location_cache::input_location_and_block (location_t *loc, + struct bitpack_d *bp, + class lto_input_block *ib, + class data_in *data_in) { static const char *stream_file; static int stream_line; static int stream_col; static bool stream_sysp; - bool file_change, line_change, column_change; + static tree stream_block; gcc_assert (current_cache == this); *loc = bp_unpack_int_in_range (bp, "location", 0, RESERVED_LOCATION_COUNT); if (*loc < RESERVED_LOCATION_COUNT) - return; + { + if (ib) + { + bool block_change = bp_unpack_value (bp, 1); + if (block_change) + stream_block = stream_read_tree (ib, data_in); + if (stream_block) + *loc = set_block (*loc, stream_block); + } + return; + } /* Keep value RESERVED_LOCATION_COUNT in *loc as linemap lookups will ICE on it. */ - file_change = bp_unpack_value (bp, 1); - line_change = bp_unpack_value (bp, 1); - column_change = bp_unpack_value (bp, 1); + bool file_change = bp_unpack_value (bp, 1); + bool line_change = bp_unpack_value (bp, 1); + bool column_change = bp_unpack_value (bp, 1); if (file_change) { @@ -263,21 +298,48 @@ lto_location_cache::input_location (location_t *loc, struct bitpack_d *bp, if (column_change) stream_col = bp_unpack_var_len_unsigned (bp); - /* This optimization saves location cache operations druing gimple + tree block = NULL_TREE; + if (ib) + { + bool block_change = bp_unpack_value (bp, 1); + if (block_change) + stream_block = stream_read_tree (ib, data_in); + block = stream_block; + } + + /* This optimization saves location cache operations during gimple streaming. */ - if (current_file == stream_file && current_line == stream_line - && current_col == stream_col && current_sysp == stream_sysp) + if (current_file == stream_file + && current_line == stream_line + && current_col == stream_col + && current_sysp == stream_sysp) { - *loc = current_loc; + if (current_block == block) + *loc = current_loc; + else if (block) + *loc = set_block (current_loc, block); + else + *loc = LOCATION_LOCUS (current_loc); return; } struct cached_location entry - = {stream_file, loc, stream_line, stream_col, stream_sysp}; + = {stream_file, loc, stream_line, stream_col, stream_sysp, block}; loc_cache.safe_push (entry); } +/* Read a location bitpack from bit pack BP and either update *LOC directly + or add it to the location cache. + It is neccesary to call apply_location_cache to get *LOC updated. */ + +void +lto_location_cache::input_location (location_t *loc, struct bitpack_d *bp, + class data_in *data_in) +{ + return input_location_and_block (loc, bp, NULL, data_in); +} + /* Read a location bitpack from input block IB and either update *LOC directly or add it to the location cache. It is neccesary to call apply_location_cache to get *LOC updated. */ @@ -1101,6 +1163,9 @@ input_function (tree fn_decl, class data_in *data_in, tag = streamer_read_record_start (ib); } + /* Finalize gimple_location/gimple_block of stmts and phis. */ + data_in->location_cache.apply_location_cache (); + /* Fix up the call statements that are mentioned in the callgraph edges. */ set_gimple_stmt_max_uid (cfun, 0); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index ec28928b56a..914d5eb70b0 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -60,6 +60,10 @@ clear_line_info (struct output_block *ob) ob->current_line = 0; ob->current_col = 0; ob->current_sysp = false; + /* Initialize to something that will never appear as block, + so that the first location with block in a function etc. + always streams a change_block bit and the first block. */ + ob->current_block = void_node; } @@ -178,40 +182,72 @@ tree_is_indexable (tree t) After outputting bitpack, lto_output_location_data has to be done to output actual data. */ -void -lto_output_location (struct output_block *ob, struct bitpack_d *bp, - location_t loc) +static void +lto_output_location_1 (struct output_block *ob, struct bitpack_d *bp, + location_t orig_loc, bool block_p) { - expanded_location xloc; + location_t loc = LOCATION_LOCUS (orig_loc); - loc = LOCATION_LOCUS (loc); bp_pack_int_in_range (bp, 0, RESERVED_LOCATION_COUNT, loc < RESERVED_LOCATION_COUNT ? loc : RESERVED_LOCATION_COUNT); - if (loc < RESERVED_LOCATION_COUNT) - return; + if (loc >= RESERVED_LOCATION_COUNT) + { + expanded_location xloc = expand_location (loc); - xloc = expand_location (loc); + bp_pack_value (bp, ob->current_file != xloc.file, 1); + bp_pack_value (bp, ob->current_line != xloc.line, 1); + bp_pack_value (bp, ob->current_col != xloc.column, 1); - bp_pack_value (bp, ob->current_file != xloc.file, 1); - bp_pack_value (bp, ob->current_line != xloc.line, 1); - bp_pack_value (bp, ob->current_col != xloc.column, 1); + if (ob->current_file != xloc.file) + { + bp_pack_string (ob, bp, remap_debug_filename (xloc.file), true); + bp_pack_value (bp, xloc.sysp, 1); + } + ob->current_file = xloc.file; + ob->current_sysp = xloc.sysp; + + if (ob->current_line != xloc.line) + bp_pack_var_len_unsigned (bp, xloc.line); + ob->current_line = xloc.line; + + if (ob->current_col != xloc.column) + bp_pack_var_len_unsigned (bp, xloc.column); + ob->current_col = xloc.column; + } - if (ob->current_file != xloc.file) + if (block_p) { - bp_pack_string (ob, bp, remap_debug_filename (xloc.file), true); - bp_pack_value (bp, xloc.sysp, 1); + tree block = LOCATION_BLOCK (orig_loc); + bp_pack_value (bp, ob->current_block != block, 1); + streamer_write_bitpack (bp); + if (ob->current_block != block) + lto_output_tree (ob, block, true, true); + ob->current_block = block; } - ob->current_file = xloc.file; - ob->current_sysp = xloc.sysp; +} + +/* Output info about new location into bitpack BP. + After outputting bitpack, lto_output_location_data has + to be done to output actual data. */ - if (ob->current_line != xloc.line) - bp_pack_var_len_unsigned (bp, xloc.line); - ob->current_line = xloc.line; +void +lto_output_location (struct output_block *ob, struct bitpack_d *bp, + location_t loc) +{ + lto_output_location_1 (ob, bp, loc, false); +} + +/* Output info about new location into bitpack BP. + After outputting bitpack, lto_output_location_data has + to be done to output actual data. Like lto_output_location, but + additionally output LOCATION_BLOCK info too and write the BP bitpack. */ - if (ob->current_col != xloc.column) - bp_pack_var_len_unsigned (bp, xloc.column); - ob->current_col = xloc.column; +void +lto_output_location_and_block (struct output_block *ob, struct bitpack_d *bp, + location_t loc) +{ + lto_output_location_1 (ob, bp, loc, true); } diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c index 7d0fd3924c0..9d12d47d909 100644 --- a/gcc/lto-streamer.c +++ b/gcc/lto-streamer.c @@ -272,4 +272,5 @@ lto_streamer_hooks_init (void) streamer_hooks.read_tree = lto_input_tree; streamer_hooks.input_location = lto_input_location; streamer_hooks.output_location = lto_output_location; + streamer_hooks.output_location_and_block = lto_output_location_and_block; } diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 0129f00cc1a..938298459eb 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -262,7 +262,7 @@ typedef void (lto_free_section_data_f) (struct lto_file_decl_data *, /* The location cache holds expanded locations for streamed in trees. This is done to reduce memory usage of libcpp linemap that strongly prefers - locations to be inserted in the soruce order. */ + locations to be inserted in the source order. */ class lto_location_cache { @@ -276,9 +276,13 @@ public: void revert_location_cache (); void input_location (location_t *loc, struct bitpack_d *bp, class data_in *data_in); + void input_location_and_block (location_t *loc, struct bitpack_d *bp, + class lto_input_block *ib, + class data_in *data_in); lto_location_cache () : loc_cache (), accepted_length (0), current_file (NULL), current_line (0), - current_col (0), current_sysp (false), current_loc (UNKNOWN_LOCATION) + current_col (0), current_sysp (false), current_loc (UNKNOWN_LOCATION), + current_block (NULL_TREE) { gcc_assert (!current_cache); current_cache = this; @@ -304,6 +308,7 @@ private: location_t *loc; int line, col; bool sysp; + tree block; }; /* The location cache. */ @@ -325,6 +330,7 @@ private: int current_col; bool current_sysp; location_t current_loc; + tree current_block; }; /* Structure used as buffer for reading an LTO file. */ @@ -711,6 +717,7 @@ struct output_block int current_line; int current_col; bool current_sysp; + tree current_block; /* Cache of nodes written in this section. */ struct streamer_tree_cache_d *writer_cache; @@ -881,7 +888,10 @@ void lto_output_decl_state_streams (struct output_block *, void lto_output_decl_state_refs (struct output_block *, struct lto_output_stream *, struct lto_out_decl_state *); -void lto_output_location (struct output_block *, struct bitpack_d *, location_t); +void lto_output_location (struct output_block *, struct bitpack_d *, + location_t); +void lto_output_location_and_block (struct output_block *, struct bitpack_d *, + location_t); void lto_output_init_mode_table (void); void lto_prepare_function_for_streaming (cgraph_node *); diff --git a/gcc/streamer-hooks.h b/gcc/streamer-hooks.h index 734f9ca04ac..4085bf4ba3d 100644 --- a/gcc/streamer-hooks.h +++ b/gcc/streamer-hooks.h @@ -54,8 +54,15 @@ struct streamer_hooks { /* [REQ] Called by every streaming routine that needs to read a location. */ void (*input_location) (location_t *, struct bitpack_d *, class data_in *); - /* [REQ] Called by every streaming routine that needs to write a location. */ - void (*output_location) (struct output_block *, struct bitpack_d *, location_t); + /* [REQ] Called by every streaming routine that needs to write a + location. */ + void (*output_location) (struct output_block *, struct bitpack_d *, + location_t); + + /* [REQ] Called by every streaming routine that needs to write a + location, both LOCATION_LOCUS and LOCATION_BLOCK. */ + void (*output_location_and_block) (struct output_block *, struct bitpack_d *, + location_t); }; #define stream_write_tree(OB, EXPR, REF_P) \ @@ -73,6 +80,9 @@ struct streamer_hooks { #define stream_output_location(OB, BP, LOC) \ streamer_hooks.output_location (OB, BP, LOC) +#define stream_output_location_and_block(OB, BP, LOC) \ + streamer_hooks.output_location_and_block (OB, BP, LOC) + /* Streamer hooks. */ extern struct streamer_hooks streamer_hooks; |