diff mbox

Combine location with block using block_locations

Message ID CAO2gOZWX+A3R0MGvWXYztBokQ=ezHNiS3vR0Cu9cbGPi_102ww@mail.gmail.com
State New
Headers show

Commit Message

Dehao Chen Sept. 8, 2012, 10:26 p.m. UTC
Hi, Diego,

Thanks a lot for the review. I've updated the patch.

This patch is large and may easily break builds because it reserves
more complete information for TREE_BLOCK as well as gimple_block (may
trigger bugs that was hided when these info are unavailable). I've
done more rigorous testing to ensure that most bugs are caught before
checking in.

* Sync to the head and retest all gcc testsuite.
* Port the patch to google-4_7 branch to retest all gcc testsuite, as
well as build many large applications.

Through these tests, I've found two additional bugs that was omitted
in the original implementation. A new patch is attached (patch.txt) to
fix these problems. After this fix, all gcc testsuites pass for both
trunk and google-4_7 branch. I've also copy pasted the new fixes
(lto.c and tree-cfg.c) below. Now I'd say this patch is in good shape.
But it may not be perfect. I'll look into build failures as soon as it
arises.

Richard and Diego, could you help me take a look at the following two fixes?

Thanks,
Dehao

New fixes:

Whole patch:
gcc/ChangeLog:
2012-09-08  Dehao Chen  <dehao@google.com>

	* toplev.c (general_init): Init block_locations.
	* tree.c (tree_set_block): New.
	(tree_block): Change to use LOCATION_BLOCK.
	* tree.h (TREE_SET_BLOCK): New.
	* final.c (reemit_insn_block_notes): Change to use LOCATION_BLOCK.
	(final_start_function): Likewise.
	* input.c (expand_location_1): Likewise.
	* input.h (LOCATION_LOCUS): New.
	(LOCATION_BLOCK): New.
	(IS_UNKNOWN_LOCATION): New.
	* fold-const.c (expr_location_or): Change to use new location.
	* reorg.c (emit_delay_sequence): Likewise.
	(try_merge_delay_insns): Likewise.
	* modulo-sched.c (dump_insn_location): Likewise.
	* lto-streamer-out.c (lto_output_location_bitpack): Likewise.
	* jump.c (rtx_renumbered_equal_p): Likewise.
	* ifcvt.c (noce_try_move): Likewise.
	(noce_try_store_flag): Likewise.
	(noce_try_store_flag_constants): Likewise.
	(noce_try_addcc): Likewise.
	(noce_try_store_flag_mask): Likewise.
	(noce_try_cmove): Likewise.
	(noce_try_cmove_arith): Likewise.
	(noce_try_minmax): Likewise.
	(noce_try_abs): Likewise.
	(noce_try_sign_mask): Likewise.
	(noce_try_bitop): Likewise.
	(noce_process_if_block): Likewise.
	(cond_move_process_if_block): Likewise.
	(find_cond_trap): Likewise.
	* dwarf2out.c (add_src_coords_attributes): Likewise.
	* expr.c (expand_expr_real): Likewise.
	* tree-parloops.c (create_loop_fn): Likewise.
	* recog.c (peep2_attempt): Likewise.
	* function.c (free_after_compilation): Likewise.
	(expand_function_end): Likewise.
	(set_insn_locations): Likewise.
	(thread_prologue_and_epilogue_insns): Likewise.
	* print-rtl.c (print_rtx): Likewise.
	* profile.c (branch_prob): Likewise.
	* trans-mem.c (ipa_tm_scan_irr_block): Likewise.
	* gimplify.c (gimplify_call_expr): Likewise.
	* except.c (duplicate_eh_regions_1): Likewise.
	* emit-rtl.c (try_split): Likewise.
	(make_insn_raw): Likewise.
	(make_debug_insn_raw): Likewise.
	(make_jump_insn_raw): Likewise.
	(make_call_insn_raw): Likewise.
	(emit_pattern_after_setloc): Likewise.
	(emit_pattern_after): Likewise.
	(emit_debug_insn_after): Likewise.
	(emit_pattern_before): Likewise.
	(emit_insn_before_setloc): Likewise.
	(emit_jump_insn_before): Likewise.
	(emit_call_insn_before_setloc): Likewise.
	(emit_call_insn_before): Likeise.
	(emit_debug_insn_before_setloc): Likewise.
	(emit_copy_of_insn_after): Likewise.
	(insn_locators_alloc): Remove.
	(insn_locators_finalize): Remove.
	(insn_locators_free): Remove.
	(set_curr_insn_source_location): Remove.
	(get_curr_insn_source_location): Remove.
	(set_curr_insn_block): Remove.
	(get_curr_insn_block): Remove.
	(locator_scope): Remove.
	(insn_scope): Change to use new location.
	(locator_location): Remove.
	(insn_line): Change to use new location.
	(locator_file): Remove.
	(insn_file): Change to use new location.
	(locator_eq): Remove.
	(insn_locations_init): New.
	(insn_locations_finalize): New.
	(set_curr_insn_location): New.
	(curr_insn_location): New.
	* cfgexpand.c (gimple_assign_rhs_to_tree): Change to use new location.
	(expand_gimple_cond): Likewise.
	(expand_call_stmt): Likewise.
	(expand_gimple_stmt_1): Likewise.
	(expand_gimple_basic_block): Likewise.
	(construct_exit_block): Likewise.
	(gimple_expand_cfg): Likewise.
	* cfgcleanup.c (try_forward_edges): Likewise.
	* tree-ssa-live.c (remove_unused_scope_block_p): Likewise.
	(dump_scope_block): Likewise.
	(remove_unused_locals): Likewise.
	* rtl.c (rtx_equal_p_cb): Likewise.
	(rtx_equal_p): Likewise.
	* rtl.h (XUINT): New.
	(INSN_LOCATOR): Remove.
	(CURR_INSN_LOCATION): Remove.
	(INSN_LOCATION): New.
	(INSN_HAS_LOCATION): New.
	* tree-inline.c (remap_gimple_op_r): Change to use new location.
	(copy_tree_body_r): Likewise.
	(copy_phis_for_bb): Likewise.
	(expand_call_inline): Likewise.
	* tree-streamer-in.c (lto_input_ts_exp_tree_pointers): Likewise.
	* tree-streamer-out.c (write_ts_decl_minimal_tree_pointers): Likewise.
	* gimple-streamer-out.c (output_gimple_stmt): Likewise.
	* combine.c (try_combine): Likewise.
	* tree-outof-ssa.c (set_location_for_edge): Likewise.
	(insert_partition_copy_on_edge): Likewise.
	(insert_value_copy_on_edge): Likewise.
	(insert_rtx_to_part_on_edge): Likewise.
	(insert_part_to_rtx_on_edge): Likewise.
	* basic-block.h (edge_def): Remove field.
	* gimple.h (gimple_statement_base): Remove field.
	(gimple_bb): Change to use new location.
	(gimple_set_block): Likewise.
	(gimple_has_location): Likewise.
	* tree-cfg.c (make_cond_expr_edges): Likewise.
	(make_goto_expr_edges): Likewise.
	(gimple_can_merge_blocks_p): Likewise.
	(move_stmt_op): Likewise.
	(move_block_to_fn): Likewise.
	* config/alpha/alpha.c (alpha_output_mi_thunk_osf): Likewise.
	* config/sparc/sparc.c (sparc_output_mi_thunk): Likewise.
	* config/i386/i386.c (x86_output_mi_thunk): Likewise.
	* config/tilegx/tilegx.c (tilegx_output_mi_thunk): Likewise.
	* config/sh/sh.c (sh_output_mi_thunk): Likewise.
	* config/ia64/ia64.c (ia64_output_mi_thunk): Likewise.
	* config/rs6000/rs6000.c (rs6000_output_mi_thunk): Likewise.
	* config/score/score.c (score_output_mi_thunk): Likewise.
	* config/tilepro/tilepro.c (tilepro_asm_output_mi_thunk): Likewise.
	* config/mips/mips.c (mips_output_mi_thunk): Likewise.
	* cfgrtl.c (unique_locus_on_edge_between_p): Likewise.
	(unique_locus_on_edge_between_p): Likewise.
	(emit_nop_for_unique_locus_between): Likewise.
	(force_nonfallthru_and_redirect): Likewise.
	(fixup_reorder_chain): Likewise.
	(cfg_layout_merge_blocks): Likewise.
	* stmt.c (emit_case_nodes): Likewise.

gcc/lto/ChangeLog:
2012-09-08  Dehao Chen  <dehao@google.com>

        * lto/lto.c (lto_fixup_prevailing_decls): Remove tree.exp.block field.

libcpp/ChangeLog:
2012-09-08  Dehao Chen  <dehao@google.com>

        * include/line-map.h (MAX_SOURCE_LOCATION): New value.
        (location_adhoc_data_init): New.
        (location_adhoc_data_fini): New.
        (get_combined_adhoc_loc): New.
        (get_data_from_adhoc_loc): New.
        (get_location_from_adhoc_loc): New.
        (COMBINE_LOCATION_DATA): New.
        (IS_ADHOC_LOC): New.
        (expanded_location): New field.
        * line-map.c (location_adhoc_data): New.
        (location_adhoc_data_htab): New.
        (curr_adhoc_loc): New.
        (location_adhoc_data): New.
        (allocated_location_adhoc_data): New.
        (location_adhoc_data_hash): New.
        (location_adhoc_data_eq): New.
        (location_adhoc_data_update): New.
        (get_combined_adhoc_loc): New.
        (get_data_from_adhoc_loc): New.
        (get_location_from_adhoc_loc): New.
        (location_adhoc_data_init): New.
        (location_adhoc_data_fini): New.
        (linemap_lookup): Change to use new location.
        (linemap_ordinary_map_lookup): Likewise.
        (linemap_macro_map_lookup): Likewise.
        (linemap_macro_map_loc_to_def_point): Likewise.
        (linemap_macro_map_loc_unwind_toward_spel): Likewise.
        (linemap_get_expansion_line): Likewise.
        (linemap_get_expansion_filename): Likewise.
        (linemap_location_in_system_header_p): Likewise.
        (linemap_location_from_macro_expansion_p): Likewise.
        (linemap_macro_loc_to_spelling_point): Likewise.
        (linemap_macro_loc_to_def_point): Likewise.
        (linemap_macro_loc_to_exp_point): Likewise.
        (linemap_resolve_location): Likewise.
        (linemap_unwind_toward_expansion): Likewise.
        (linemap_unwind_to_first_non_reserved_loc): Likewise.
        (linemap_expand_location): Likewise.
        (linemap_dump_location): Likewise.
Index: gcc/gimple-streamer-out.c
===================================================================
--- gcc/gimple-streamer-out.c	(revision 191083)
+++ gcc/gimple-streamer-out.c	(working copy)
@@ -74,7 +74,7 @@ output_gimple_stmt (struct output_block *ob, gimpl
   streamer_write_bitpack (&bp);
 
   /* Emit location information for the statement.  */
-  lto_output_location (ob, gimple_location (stmt));
+  lto_output_location (ob, LOCATION_LOCUS (gimple_location (stmt)));
 
   /* Emit the lexical block holding STMT.  */
   stream_write_tree (ob, gimple_block (stmt), true);
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 191083)
+++ gcc/tree.c	(working copy)
@@ -3762,7 +3762,6 @@ build1_stat (enum tree_code code, tree type, tree
   TREE_TYPE (t) = type;
   SET_EXPR_LOCATION (t, UNKNOWN_LOCATION);
   TREE_OPERAND (t, 0) = node;
-  TREE_BLOCK (t) = NULL_TREE;
   if (node && !TYPE_P (node))
     {
       TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (node);
@@ -10828,17 +10827,28 @@ walk_tree_without_duplicates_1 (tree *tp, walk_tre
 }
 
 
-tree *
+tree
 tree_block (tree t)
 {
   char const c = TREE_CODE_CLASS (TREE_CODE (t));
 
   if (IS_EXPR_CODE_CLASS (c))
-    return &t->exp.block;
+    return LOCATION_BLOCK (t->exp.locus);
   gcc_unreachable ();
   return NULL;
 }
 
+void
+tree_set_block (tree t, tree b)
+{
+  char const c = TREE_CODE_CLASS (TREE_CODE (t));
+
+  if (IS_EXPR_CODE_CLASS (c))
+    t->exp.locus = COMBINE_LOCATION_DATA (t->exp.locus, b);
+  else
+    gcc_unreachable ();
+}
+
 /* Create a nameless artificial label and put it in the current
    function context.  The label has a location of LOC.  Returns the
    newly created label.  */
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 191083)
+++ gcc/tree.h	(working copy)
@@ -907,7 +907,8 @@ extern void omp_clause_range_check_failed (const_t
 
 #endif
 
-#define TREE_BLOCK(NODE)		*(tree_block (NODE))
+#define TREE_BLOCK(NODE)		(tree_block (NODE))
+#define TREE_SET_BLOCK(T, B)		(tree_set_block ((T), (B)))
 
 #include "tree-check.h"
 
@@ -1612,7 +1613,7 @@ struct GTY(()) tree_constructor {
 #define EXPR_LOCATION(NODE) \
   (CAN_HAVE_LOCATION_P ((NODE)) ? (NODE)->exp.locus : UNKNOWN_LOCATION)
 #define SET_EXPR_LOCATION(NODE, LOCUS) EXPR_CHECK ((NODE))->exp.locus = (LOCUS)
-#define EXPR_HAS_LOCATION(NODE) (EXPR_LOCATION (NODE) != UNKNOWN_LOCATION)
+#define EXPR_HAS_LOCATION(NODE) (!IS_UNKNOWN_LOCATION (EXPR_LOCATION (NODE)))
 /* The location to be used in a diagnostic about this expression.  Do not
    use this macro if the location will be assigned to other expressions.  */
 #define EXPR_LOC_OR_HERE(NODE) (EXPR_HAS_LOCATION (NODE) ? (NODE)->exp.locus : input_location)
@@ -1791,7 +1792,7 @@ extern void protected_set_expr_location (tree, loc
 					      OMP_CLAUSE_PRIVATE,	\
 	                                      OMP_CLAUSE_COPYPRIVATE), 0)
 #define OMP_CLAUSE_HAS_LOCATION(NODE) \
-  ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus != UNKNOWN_LOCATION)
+  (!IS_UNKNOWN_LOCATION ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus))
 #define OMP_CLAUSE_LOCATION(NODE)  (OMP_CLAUSE_CHECK (NODE))->omp_clause.locus
 
 /* True on an OMP_SECTION statement that was the last lexical member.
@@ -1882,7 +1883,6 @@ enum omp_clause_default_kind
 struct GTY(()) tree_exp {
   struct tree_typed typed;
   location_t locus;
-  tree block;
   tree GTY ((special ("tree_exp"),
 	     desc ("TREE_CODE ((tree) &%0)")))
     operands[1];
@@ -5536,7 +5536,7 @@ function_args_iter_next (function_args_iterator *i
 static inline bool
 inlined_function_outer_scope_p (const_tree block)
 {
- return BLOCK_SOURCE_LOCATION (block) != UNKNOWN_LOCATION;
+ return !IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (block));
 }
 
 /* Loop over all function arguments of FNTYPE.  In each iteration, PTR is set
@@ -5911,7 +5911,8 @@ extern bool subrange_type_for_debug_p (const_tree,
 extern HOST_WIDE_INT int_cst_value (const_tree);
 extern HOST_WIDEST_INT widest_int_cst_value (const_tree);
 
-extern tree *tree_block (tree);
+extern tree tree_block (tree);
+extern void tree_set_block (tree, tree);
 extern location_t *block_nonartificial_location (tree);
 extern location_t tree_nonartificial_location (tree);
 
Index: gcc/final.c
===================================================================
--- gcc/final.c	(revision 191083)
+++ gcc/final.c	(working copy)
@@ -1606,7 +1606,7 @@ reemit_insn_block_notes (void)
 					     insn_scope (XVECEXP (body, 0, i)));
 	}
       if (! this_block)
-	continue;
+	this_block = DECL_INITIAL (cfun->decl);
 
       if (this_block != cur_block)
 	{
@@ -1641,8 +1641,8 @@ final_start_function (rtx first ATTRIBUTE_UNUSED,
 
   this_is_asm_operands = 0;
 
-  last_filename = locator_file (prologue_locator);
-  last_linenum = locator_line (prologue_locator);
+  last_filename = LOCATION_FILE (prologue_location);
+  last_linenum = LOCATION_LINE (prologue_location);
   last_discriminator = discriminator = 0;
 
   high_block_linenum = high_function_linenum = last_linenum;
Index: gcc/input.c
===================================================================
--- gcc/input.c	(revision 191083)
+++ gcc/input.c	(working copy)
@@ -51,7 +51,14 @@ expand_location_1 (source_location loc,
   expanded_location xloc;
   const struct line_map *map;
   enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
+  tree block = NULL;
 
+  if (IS_ADHOC_LOC (loc))
+    {
+      block = LOCATION_BLOCK (loc);
+      loc = LOCATION_LOCUS (loc);
+    }
+
   memset (&xloc, 0, sizeof (xloc));
 
   if (loc >= RESERVED_LOCATION_COUNT)
@@ -74,6 +81,7 @@ expand_location_1 (source_location loc,
       xloc = linemap_expand_location (line_table, map, loc);
     }
 
+  xloc.data = block;
   if (loc <= BUILTINS_LOCATION)
     xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
 
Index: gcc/input.h
===================================================================
--- gcc/input.h	(revision 191083)
+++ gcc/input.h	(working copy)
@@ -51,6 +51,14 @@ extern location_t input_location;
 #define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
 #define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
 #define LOCATION_COLUMN(LOC)((expand_location (LOC)).column)
+#define LOCATION_LOCUS(LOC) \
+  ((IS_ADHOC_LOC(LOC)) ? get_location_from_adhoc_loc (LOC) : (LOC))
+#define LOCATION_BLOCK(LOC) \
+  ((tree) ((IS_ADHOC_LOC (LOC)) ? get_data_from_adhoc_loc (LOC) \
+  : NULL))
+#define IS_UNKNOWN_LOCATION(LOC) \
+  ((IS_ADHOC_LOC (LOC)) ? get_location_from_adhoc_loc (LOC) == 0 \
+  : (LOC) == 0)
 
 #define input_line LOCATION_LINE (input_location)
 #define input_filename LOCATION_FILE (input_location)
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 191083)
+++ gcc/fold-const.c	(working copy)
@@ -145,7 +145,7 @@ static location_t
 expr_location_or (tree t, location_t loc)
 {
   location_t tloc = EXPR_LOCATION (t);
-  return tloc != UNKNOWN_LOCATION ? tloc : loc;
+  return IS_UNKNOWN_LOCATION (tloc) ? loc : tloc;
 }
 
 /* Similar to protected_set_expr_location, but never modify x in place,
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 191083)
+++ gcc/toplev.c	(working copy)
@@ -1140,6 +1140,7 @@ general_init (const char *argv0)
   linemap_init (line_table);
   line_table->reallocator = realloc_for_line_map;
   line_table->round_alloc_size = ggc_round_alloc_size;
+  location_adhoc_data_init ();
   init_ttree ();
 
   /* Initialize register usage now so switches may override.  */
@@ -1946,6 +1947,7 @@ toplev_main (int argc, char **argv)
   invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
 
   finalize_plugins ();
+  location_adhoc_data_fini ();
   if (seen_error ())
     return (FATAL_EXIT_CODE);
 
Index: gcc/reorg.c
===================================================================
--- gcc/reorg.c	(revision 191083)
+++ gcc/reorg.c	(working copy)
@@ -545,7 +545,7 @@ emit_delay_sequence (rtx insn, rtx list, int lengt
   INSN_DELETED_P (delay_insn) = 0;
   PREV_INSN (delay_insn) = PREV_INSN (seq_insn);
 
-  INSN_LOCATOR (seq_insn) = INSN_LOCATOR (delay_insn);
+  INSN_LOCATION (seq_insn) = INSN_LOCATION (delay_insn);
 
   for (li = list; li; li = XEXP (li, 1), i++)
     {
@@ -561,9 +561,9 @@ emit_delay_sequence (rtx insn, rtx list, int lengt
 
       /* SPARC assembler, for instance, emit warning when debug info is output
          into the delay slot.  */
-      if (INSN_LOCATOR (tem) && !INSN_LOCATOR (seq_insn))
-	INSN_LOCATOR (seq_insn) = INSN_LOCATOR (tem);
-      INSN_LOCATOR (tem) = 0;
+      if (INSN_LOCATION (tem) && !INSN_LOCATION (seq_insn))
+	INSN_LOCATION (seq_insn) = INSN_LOCATION (tem);
+      INSN_LOCATION (tem) = 0;
 
       for (note = REG_NOTES (tem); note; note = next)
 	{
@@ -4065,7 +4065,7 @@ dbr_schedule (rtx first)
     for (link = crtl->epilogue_delay_list;
          link;
          link = XEXP (link, 1))
-      INSN_LOCATOR (XEXP (link, 0)) = 0;
+      INSN_LOCATION (XEXP (link, 0)) = 0;
   }
 
 #endif
Index: gcc/modulo-sched.c
===================================================================
--- gcc/modulo-sched.c	(revision 191083)
+++ gcc/modulo-sched.c	(working copy)
@@ -1246,9 +1246,9 @@ loop_single_full_bb_p (struct loop *loop)
 /* Dump file:line from INSN's location info to dump_file.  */
 
 static void
-dump_insn_locator (rtx insn)
+dump_insn_location (rtx insn)
 {
-  if (dump_file && INSN_LOCATOR (insn))
+  if (dump_file && INSN_LOCATION (insn))
     {
       const char *file = insn_file (insn);
       if (file)
@@ -1282,7 +1282,7 @@ loop_canon_p (struct loop *loop)
 	  rtx insn = BB_END (loop->header);
 
 	  fprintf (dump_file, "SMS loop many exits");
-	  dump_insn_locator (insn);
+	  dump_insn_location (insn);
 	  fprintf (dump_file, "\n");
 	}
       return false;
@@ -1295,7 +1295,7 @@ loop_canon_p (struct loop *loop)
 	  rtx insn = BB_END (loop->header);
 
 	  fprintf (dump_file, "SMS loop many BBs.");
-	  dump_insn_locator (insn);
+	  dump_insn_location (insn);
 	  fprintf (dump_file, "\n");
 	}
       return false;
@@ -1421,7 +1421,7 @@ sms_schedule (void)
 	  rtx insn = BB_END (loop->header);
 
 	  fprintf (dump_file, "SMS loop num: %d", loop->num);
-	  dump_insn_locator (insn);
+	  dump_insn_location (insn);
 	  fprintf (dump_file, "\n");
 	}
 
@@ -1450,7 +1450,7 @@ sms_schedule (void)
 	{
 	  if (dump_file)
 	    {
-	      dump_insn_locator (tail);
+	      dump_insn_location (tail);
 	      fprintf (dump_file, "\nSMS single-bb-loop\n");
 	      if (profile_info && flag_branch_probabilities)
 	    	{
@@ -1556,7 +1556,7 @@ sms_schedule (void)
 	  rtx insn = BB_END (loop->header);
 
 	  fprintf (dump_file, "SMS loop num: %d", loop->num);
-	  dump_insn_locator (insn);
+	  dump_insn_location (insn);
 	  fprintf (dump_file, "\n");
 
 	  print_ddg (dump_file, g);
@@ -1571,7 +1571,7 @@ sms_schedule (void)
 
       if (dump_file)
 	{
-	  dump_insn_locator (tail);
+	  dump_insn_location (tail);
 	  fprintf (dump_file, "\nSMS single-bb-loop\n");
 	  if (profile_info && flag_branch_probabilities)
 	    {
@@ -1714,7 +1714,7 @@ sms_schedule (void)
 
           if (dump_file)
             {
-	      dump_insn_locator (tail);
+	      dump_insn_location (tail);
 	      fprintf (dump_file, " SMS succeeded %d %d (with ii, sc)\n",
 		       ps->ii, stage_count);
 	      print_partial_schedule (ps, dump_file);
Index: gcc/lto-streamer-out.c
===================================================================
--- gcc/lto-streamer-out.c	(revision 191083)
+++ gcc/lto-streamer-out.c	(working copy)
@@ -155,6 +155,7 @@ lto_output_location_bitpack (struct bitpack_d *bp,
 {
   expanded_location xloc;
 
+  loc = LOCATION_LOCUS (loc);
   bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
   if (loc == UNKNOWN_LOCATION)
     return;
Index: gcc/ifcvt.c
===================================================================
--- gcc/ifcvt.c	(revision 191083)
+++ gcc/ifcvt.c	(working copy)
@@ -1020,7 +1020,7 @@ noce_try_move (struct noce_if_info *if_info)
 	    return FALSE;
 
 	  emit_insn_before_setloc (seq, if_info->jump,
-				   INSN_LOCATOR (if_info->insn_a));
+				   INSN_LOCATION (if_info->insn_a));
 	}
       return TRUE;
     }
@@ -1065,7 +1065,7 @@ noce_try_store_flag (struct noce_if_info *if_info)
 	return FALSE;
 
       emit_insn_before_setloc (seq, if_info->jump,
-			       INSN_LOCATOR (if_info->insn_a));
+			       INSN_LOCATION (if_info->insn_a));
       return TRUE;
     }
   else
@@ -1196,7 +1196,7 @@ noce_try_store_flag_constants (struct noce_if_info
 	return FALSE;
 
       emit_insn_before_setloc (seq, if_info->jump,
-			       INSN_LOCATOR (if_info->insn_a));
+			       INSN_LOCATION (if_info->insn_a));
       return TRUE;
     }
 
@@ -1244,7 +1244,7 @@ noce_try_addcc (struct noce_if_info *if_info)
 		return FALSE;
 
 	      emit_insn_before_setloc (seq, if_info->jump,
-				       INSN_LOCATOR (if_info->insn_a));
+				       INSN_LOCATION (if_info->insn_a));
 	      return TRUE;
 	    }
 	  end_sequence ();
@@ -1284,7 +1284,7 @@ noce_try_addcc (struct noce_if_info *if_info)
 		return FALSE;
 
 	      emit_insn_before_setloc (seq, if_info->jump,
-				       INSN_LOCATOR (if_info->insn_a));
+				       INSN_LOCATION (if_info->insn_a));
 	      return TRUE;
 	    }
 	  end_sequence ();
@@ -1333,7 +1333,7 @@ noce_try_store_flag_mask (struct noce_if_info *if_
 	    return FALSE;
 
 	  emit_insn_before_setloc (seq, if_info->jump,
-				   INSN_LOCATOR (if_info->insn_a));
+				   INSN_LOCATION (if_info->insn_a));
 	  return TRUE;
 	}
 
@@ -1482,7 +1482,7 @@ noce_try_cmove (struct noce_if_info *if_info)
 	    return FALSE;
 
 	  emit_insn_before_setloc (seq, if_info->jump,
-				   INSN_LOCATOR (if_info->insn_a));
+				   INSN_LOCATION (if_info->insn_a));
 	  return TRUE;
 	}
       else
@@ -1683,7 +1683,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info
   if (!tmp)
     return FALSE;
 
-  emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR (if_info->insn_a));
+  emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATION (if_info->insn_a));
   return TRUE;
 
  end_seq_and_fail:
@@ -1930,7 +1930,7 @@ noce_try_minmax (struct noce_if_info *if_info)
   if (!seq)
     return FALSE;
 
-  emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
+  emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
   if_info->cond = cond;
   if_info->cond_earliest = earliest;
 
@@ -2077,7 +2077,7 @@ noce_try_abs (struct noce_if_info *if_info)
   if (!seq)
     return FALSE;
 
-  emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
+  emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
   if_info->cond = cond;
   if_info->cond_earliest = earliest;
 
@@ -2156,7 +2156,7 @@ noce_try_sign_mask (struct noce_if_info *if_info)
   if (!seq)
     return FALSE;
 
-  emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
+  emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
   return TRUE;
 }
 
@@ -2256,7 +2256,7 @@ noce_try_bitop (struct noce_if_info *if_info)
 	return FALSE;
 
       emit_insn_before_setloc (seq, if_info->jump,
-			       INSN_LOCATOR (if_info->insn_a));
+			       INSN_LOCATION (if_info->insn_a));
     }
   return TRUE;
 }
@@ -2657,7 +2657,7 @@ noce_process_if_block (struct noce_if_info *if_inf
       unshare_all_rtl_in_chain (seq);
       end_sequence ();
 
-      emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATOR (insn_a));
+      emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATION (insn_a));
     }
 
   /* The original THEN and ELSE blocks may now be removed.  The test block
@@ -2929,7 +2929,7 @@ cond_move_process_if_block (struct noce_if_info *i
       loc_insn = first_active_insn (else_bb);
       gcc_assert (loc_insn);
     }
-  emit_insn_before_setloc (seq, jump, INSN_LOCATOR (loc_insn));
+  emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));
 
   if (else_bb)
     {
@@ -3652,7 +3652,7 @@ find_cond_trap (basic_block test_bb, edge then_edg
     return FALSE;
 
   /* Emit the new insns before cond_earliest.  */
-  emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATOR (trap));
+  emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATION (trap));
 
   /* Delete the trap block if possible.  */
   remove_edge (trap_bb == then_bb ? then_edge : else_edge);
Index: gcc/jump.c
===================================================================
--- gcc/jump.c	(revision 191083)
+++ gcc/jump.c	(working copy)
@@ -1815,8 +1815,7 @@ rtx_renumbered_equal_p (const_rtx x, const_rtx y)
 	  if (XINT (x, i) != XINT (y, i))
 	    {
 	      if (((code == ASM_OPERANDS && i == 6)
-		   || (code == ASM_INPUT && i == 1))
-		  && locator_eq (XINT (x, i), XINT (y, i)))
+		   || (code == ASM_INPUT && i == 1)))
 		break;
 	      return 0;
 	    }
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 191083)
+++ gcc/dwarf2out.c	(working copy)
@@ -15552,7 +15552,7 @@ add_src_coords_attributes (dw_die_ref die, tree de
 {
   expanded_location s;
 
-  if (DECL_SOURCE_LOCATION (decl) == UNKNOWN_LOCATION)
+  if (IS_UNKNOWN_LOCATION (DECL_SOURCE_LOCATION (decl)))
     return;
   s = expand_location (DECL_SOURCE_LOCATION (decl));
   add_AT_file (die, DW_AT_decl_file, lookup_filename (s.file));
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 191083)
+++ gcc/expr.c	(working copy)
@@ -7793,19 +7793,14 @@ expand_expr_real (tree exp, rtx target, enum machi
   if (cfun && EXPR_HAS_LOCATION (exp))
     {
       location_t saved_location = input_location;
-      location_t saved_curr_loc = get_curr_insn_source_location ();
-      tree saved_block = get_curr_insn_block ();
+      location_t saved_curr_loc = curr_insn_location ();
       input_location = EXPR_LOCATION (exp);
-      set_curr_insn_source_location (input_location);
+      set_curr_insn_location (input_location);
 
-      /* Record where the insns produced belong.  */
-      set_curr_insn_block (TREE_BLOCK (exp));
-
       ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
 
       input_location = saved_location;
-      set_curr_insn_block (saved_block);
-      set_curr_insn_source_location (saved_curr_loc);
+      set_curr_insn_location (saved_curr_loc);
     }
   else
     {
Index: gcc/tree-parloops.c
===================================================================
--- gcc/tree-parloops.c	(revision 191083)
+++ gcc/tree-parloops.c	(working copy)
@@ -1403,6 +1403,7 @@ create_loop_fn (location_t loc)
   struct function *act_cfun = cfun;
   static unsigned loopfn_num;
 
+  loc = LOCATION_LOCUS (loc);
   snprintf (buf, 100, "%s.$loopfn", current_function_name ());
   ASM_FORMAT_PRIVATE_NAME (tname, buf, loopfn_num++);
   clean_symbol_name (tname);
Index: gcc/recog.c
===================================================================
--- gcc/recog.c	(revision 191083)
+++ gcc/recog.c	(working copy)
@@ -3326,7 +3326,7 @@ peep2_attempt (basic_block bb, rtx insn, int match
   /* Replace the old sequence with the new.  */
   last = emit_insn_after_setloc (attempt,
 				 peep2_insn_data[i].insn,
-				 INSN_LOCATOR (peep2_insn_data[i].insn));
+				 INSN_LOCATION (peep2_insn_data[i].insn));
   before_try = PREV_INSN (insn);
   delete_insn_chain (insn, peep2_insn_data[i].insn, false);
 
Index: gcc/function.c
===================================================================
--- gcc/function.c	(revision 191083)
+++ gcc/function.c	(working copy)
@@ -133,7 +133,7 @@ static bool contains (const_rtx, htab_t);
 static void prepare_function_start (void);
 static void do_clobber_return_reg (rtx, void *);
 static void do_use_return_reg (rtx, void *);
-static void set_insn_locators (rtx, int) ATTRIBUTE_UNUSED;
+static void set_insn_locations (rtx, int) ATTRIBUTE_UNUSED;
 
 /* Stack of nested functions.  */
 /* Keep track of the cfun stack.  */
@@ -200,7 +200,6 @@ free_after_compilation (struct function *f)
   f->cfg = NULL;
 
   regno_reg_rtx = NULL;
-  insn_locators_free ();
 }
 
 /* Return size needed for stack frame based on slots so far allocated.
@@ -4979,7 +4978,7 @@ expand_function_end (void)
 	      probe_stack_range (STACK_OLD_CHECK_PROTECT, max_frame_size);
 	    seq = get_insns ();
 	    end_sequence ();
-	    set_insn_locators (seq, prologue_locator);
+	    set_insn_locations (seq, prologue_location);
 	    emit_insn_before (seq, stack_check_probe_note);
 	    break;
 	  }
@@ -4994,7 +4993,7 @@ expand_function_end (void)
 
   /* Output a linenumber for the end of the function.
      SDB depends on this.  */
-  set_curr_insn_source_location (input_location);
+  set_curr_insn_location (input_location);
 
   /* Before the return label (if any), clobber the return
      registers so that they are not propagated live to the rest of
@@ -5277,14 +5276,14 @@ maybe_copy_prologue_epilogue_insn (rtx insn, rtx c
   *slot = copy;
 }
 
-/* Set the locator of the insn chain starting at INSN to LOC.  */
+/* Set the location of the insn chain starting at INSN to LOC.  */
 static void
-set_insn_locators (rtx insn, int loc)
+set_insn_locations (rtx insn, int loc)
 {
   while (insn != NULL_RTX)
     {
       if (INSN_P (insn))
-	INSN_LOCATOR (insn) = loc;
+	INSN_LOCATION (insn) = loc;
       insn = NEXT_INSN (insn);
     }
 }
@@ -5893,7 +5892,7 @@ thread_prologue_and_epilogue_insns (void)
       end_sequence ();
 
       record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
-      set_insn_locators (split_prologue_seq, prologue_locator);
+      set_insn_locations (split_prologue_seq, prologue_location);
 #endif
     }
 
@@ -5922,7 +5921,7 @@ thread_prologue_and_epilogue_insns (void)
 
       prologue_seq = get_insns ();
       end_sequence ();
-      set_insn_locators (prologue_seq, prologue_locator);
+      set_insn_locations (prologue_seq, prologue_location);
     }
 #endif
 
@@ -6418,7 +6417,7 @@ thread_prologue_and_epilogue_insns (void)
 
       /* Retain a map of the epilogue insns.  */
       record_insns (seq, NULL, &epilogue_insn_hash);
-      set_insn_locators (seq, epilogue_locator);
+      set_insn_locations (seq, epilogue_location);
 
       seq = get_insns ();
       returnjump = get_last_insn ();
@@ -6608,7 +6607,7 @@ epilogue_done:
 	     avoid getting rid of sibcall epilogue insns.  Do this before we
 	     actually emit the sequence.  */
 	  record_insns (seq, NULL, &epilogue_insn_hash);
-	  set_insn_locators (seq, epilogue_locator);
+	  set_insn_locations (seq, epilogue_location);
 
 	  emit_insn_before (seq, insn);
 	}
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c	(revision 191083)
+++ gcc/print-rtl.c	(working copy)
@@ -416,10 +416,10 @@ print_rtx (const_rtx in_rtx)
 	if (i == 5 && INSN_P (in_rtx))
 	  {
 #ifndef GENERATOR_FILE
-	    /*  Pretty-print insn locators.  Ignore scoping as it is mostly
+	    /*  Pretty-print insn locations.  Ignore scoping as it is mostly
 		redundant with line number information and do not print anything
 		when there is no location information available.  */
-	    if (INSN_LOCATOR (in_rtx) && insn_file (in_rtx))
+	    if (INSN_LOCATION (in_rtx) && insn_file (in_rtx))
 	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
 #endif
 	  }
@@ -427,16 +427,16 @@ print_rtx (const_rtx in_rtx)
 	  {
 #ifndef GENERATOR_FILE
 	    fprintf (outfile, " %s:%i",
-		     locator_file (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)),
-		     locator_line (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)));
+		     LOCATION_FILE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)),
+		     LOCATION_LINE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)));
 #endif
 	  }
 	else if (i == 1 && GET_CODE (in_rtx) == ASM_INPUT)
 	  {
 #ifndef GENERATOR_FILE
 	    fprintf (outfile, " %s:%i",
-		     locator_file (ASM_INPUT_SOURCE_LOCATION (in_rtx)),
-		     locator_line (ASM_INPUT_SOURCE_LOCATION (in_rtx)));
+		     LOCATION_FILE (ASM_INPUT_SOURCE_LOCATION (in_rtx)),
+		     LOCATION_LINE (ASM_INPUT_SOURCE_LOCATION (in_rtx)));
 #endif
 	  }
 	else if (i == 6 && NOTE_P (in_rtx))
Index: gcc/profile.c
===================================================================
--- gcc/profile.c	(revision 191083)
+++ gcc/profile.c	(working copy)
@@ -1123,7 +1123,7 @@ branch_prob (void)
 	     is not computed twice.  */
 	  if (last
 	      && gimple_has_location (last)
-	      && e->goto_locus != UNKNOWN_LOCATION
+	      && !IS_UNKNOWN_LOCATION (e->goto_locus)
 	      && !single_succ_p (bb)
 	      && (LOCATION_FILE (e->goto_locus)
 	          != LOCATION_FILE (gimple_location (last))
@@ -1133,7 +1133,6 @@ branch_prob (void)
 	      basic_block new_bb = split_edge (e);
 	      edge ne = single_succ_edge (new_bb);
 	      ne->goto_locus = e->goto_locus;
-	      ne->goto_block = e->goto_block;
 	    }
 	  if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
 	       && e->dest != EXIT_BLOCK_PTR)
@@ -1345,7 +1344,7 @@ branch_prob (void)
 
 	  /* Notice GOTO expressions eliminated while constructing the CFG.  */
 	  if (single_succ_p (bb)
-	      && single_succ_edge (bb)->goto_locus != UNKNOWN_LOCATION)
+	      && !IS_UNKNOWN_LOCATION (single_succ_edge (bb)->goto_locus))
 	    {
 	      expanded_location curr_location
 		= expand_location (single_succ_edge (bb)->goto_locus);
Index: gcc/trans-mem.c
===================================================================
--- gcc/trans-mem.c	(revision 191083)
+++ gcc/trans-mem.c	(working copy)
@@ -3795,7 +3795,6 @@ ipa_tm_scan_irr_block (basic_block bb)
 	    {
 	      tree t = build1 (NOP_EXPR, void_type_node, size_zero_node);
 	      SET_EXPR_LOCATION (t, gimple_location (stmt));
-	      TREE_BLOCK (t) = gimple_block (stmt);
 	      error ("%Kasm not allowed in %<transaction_safe%> function", t);
 	    }
 	  return true;
Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c	(revision 191083)
+++ gcc/gimplify.c	(working copy)
@@ -2588,7 +2588,6 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_
 	    = CALL_EXPR_RETURN_SLOT_OPT (call);
 	  CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call);
 	  SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call));
-	  TREE_BLOCK (*expr_p) = TREE_BLOCK (call);
 
 	  /* Set CALL_EXPR_VA_ARG_PACK.  */
 	  CALL_EXPR_VA_ARG_PACK (*expr_p) = 1;
Index: gcc/except.c
===================================================================
--- gcc/except.c	(revision 191083)
+++ gcc/except.c	(working copy)
@@ -526,7 +526,10 @@ duplicate_eh_regions_1 (struct duplicate_eh_region
       break;
 
     case ERT_MUST_NOT_THROW:
-      new_r->u.must_not_throw = old_r->u.must_not_throw;
+      new_r->u.must_not_throw.failure_loc =
+	LOCATION_LOCUS (old_r->u.must_not_throw.failure_loc);
+      new_r->u.must_not_throw.failure_decl =
+	old_r->u.must_not_throw.failure_decl;
       break;
     }
 
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	(revision 191083)
+++ gcc/emit-rtl.c	(working copy)
@@ -3625,7 +3625,7 @@ try_split (rtx pat, rtx trial, int last)
 	}
     }
 
-  tem = emit_insn_after_setloc (seq, trial, INSN_LOCATOR (trial));
+  tem = emit_insn_after_setloc (seq, trial, INSN_LOCATION (trial));
 
   delete_insn (trial);
   if (has_barrier)
@@ -3661,7 +3661,7 @@ make_insn_raw (rtx pattern)
   PATTERN (insn) = pattern;
   INSN_CODE (insn) = -1;
   REG_NOTES (insn) = NULL;
-  INSN_LOCATOR (insn) = curr_insn_locator ();
+  INSN_LOCATION (insn) = curr_insn_location ();
   BLOCK_FOR_INSN (insn) = NULL;
 
 #ifdef ENABLE_RTL_CHECKING
@@ -3694,7 +3694,7 @@ make_debug_insn_raw (rtx pattern)
   PATTERN (insn) = pattern;
   INSN_CODE (insn) = -1;
   REG_NOTES (insn) = NULL;
-  INSN_LOCATOR (insn) = curr_insn_locator ();
+  INSN_LOCATION (insn) = curr_insn_location ();
   BLOCK_FOR_INSN (insn) = NULL;
 
   return insn;
@@ -3714,7 +3714,7 @@ make_jump_insn_raw (rtx pattern)
   INSN_CODE (insn) = -1;
   REG_NOTES (insn) = NULL;
   JUMP_LABEL (insn) = NULL;
-  INSN_LOCATOR (insn) = curr_insn_locator ();
+  INSN_LOCATION (insn) = curr_insn_location ();
   BLOCK_FOR_INSN (insn) = NULL;
 
   return insn;
@@ -3734,7 +3734,7 @@ make_call_insn_raw (rtx pattern)
   INSN_CODE (insn) = -1;
   REG_NOTES (insn) = NULL;
   CALL_INSN_FUNCTION_USAGE (insn) = NULL;
-  INSN_LOCATOR (insn) = curr_insn_locator ();
+  INSN_LOCATION (insn) = curr_insn_location ();
   BLOCK_FOR_INSN (insn) = NULL;
 
   return insn;
@@ -4407,8 +4407,8 @@ emit_pattern_after_setloc (rtx pattern, rtx after,
   after = NEXT_INSN (after);
   while (1)
     {
-      if (active_insn_p (after) && !INSN_LOCATOR (after))
-	INSN_LOCATOR (after) = loc;
+      if (active_insn_p (after) && !INSN_LOCATION (after))
+	INSN_LOCATION (after) = loc;
       if (after == last)
 	break;
       after = NEXT_INSN (after);
@@ -4431,62 +4431,62 @@ emit_pattern_after (rtx pattern, rtx after, bool s
       prev = PREV_INSN (prev);
 
   if (INSN_P (prev))
-    return emit_pattern_after_setloc (pattern, after, INSN_LOCATOR (prev),
+    return emit_pattern_after_setloc (pattern, after, INSN_LOCATION (prev),
 				      make_raw);
   else
     return emit_pattern_after_noloc (pattern, after, NULL, make_raw);
 }
 
-/* Like emit_insn_after_noloc, but set INSN_LOCATOR according to LOC.  */
+/* Like emit_insn_after_noloc, but set INSN_LOCATION according to LOC.  */
 rtx
 emit_insn_after_setloc (rtx pattern, rtx after, int loc)
 {
   return emit_pattern_after_setloc (pattern, after, loc, make_insn_raw);
 }
 
-/* Like emit_insn_after_noloc, but set INSN_LOCATOR according to AFTER.  */
+/* Like emit_insn_after_noloc, but set INSN_LOCATION according to AFTER.  */
 rtx
 emit_insn_after (rtx pattern, rtx after)
 {
   return emit_pattern_after (pattern, after, true, make_insn_raw);
 }
 
-/* Like emit_jump_insn_after_noloc, but set INSN_LOCATOR according to LOC.  */
+/* Like emit_jump_insn_after_noloc, but set INSN_LOCATION according to LOC.  */
 rtx
 emit_jump_insn_after_setloc (rtx pattern, rtx after, int loc)
 {
   return emit_pattern_after_setloc (pattern, after, loc, make_jump_insn_raw);
 }
 
-/* Like emit_jump_insn_after_noloc, but set INSN_LOCATOR according to AFTER.  */
+/* Like emit_jump_insn_after_noloc, but set INSN_LOCATION according to AFTER.  */
 rtx
 emit_jump_insn_after (rtx pattern, rtx after)
 {
   return emit_pattern_after (pattern, after, true, make_jump_insn_raw);
 }
 
-/* Like emit_call_insn_after_noloc, but set INSN_LOCATOR according to LOC.  */
+/* Like emit_call_insn_after_noloc, but set INSN_LOCATION according to LOC.  */
 rtx
 emit_call_insn_after_setloc (rtx pattern, rtx after, int loc)
 {
   return emit_pattern_after_setloc (pattern, after, loc, make_call_insn_raw);
 }
 
-/* Like emit_call_insn_after_noloc, but set INSN_LOCATOR according to AFTER.  */
+/* Like emit_call_insn_after_noloc, but set INSN_LOCATION according to AFTER.  */
 rtx
 emit_call_insn_after (rtx pattern, rtx after)
 {
   return emit_pattern_after (pattern, after, true, make_call_insn_raw);
 }
 
-/* Like emit_debug_insn_after_noloc, but set INSN_LOCATOR according to LOC.  */
+/* Like emit_debug_insn_after_noloc, but set INSN_LOCATION according to LOC.  */
 rtx
 emit_debug_insn_after_setloc (rtx pattern, rtx after, int loc)
 {
   return emit_pattern_after_setloc (pattern, after, loc, make_debug_insn_raw);
 }
 
-/* Like emit_debug_insn_after_noloc, but set INSN_LOCATOR according to AFTER.  */
+/* Like emit_debug_insn_after_noloc, but set INSN_LOCATION according to AFTER.  */
 rtx
 emit_debug_insn_after (rtx pattern, rtx after)
 {
@@ -4516,8 +4516,8 @@ emit_pattern_before_setloc (rtx pattern, rtx befor
     first = NEXT_INSN (first);
   while (1)
     {
-      if (active_insn_p (first) && !INSN_LOCATOR (first))
-	INSN_LOCATOR (first) = loc;
+      if (active_insn_p (first) && !INSN_LOCATION (first))
+	INSN_LOCATION (first) = loc;
       if (first == last)
 	break;
       first = NEXT_INSN (first);
@@ -4541,7 +4541,7 @@ emit_pattern_before (rtx pattern, rtx before, bool
       next = PREV_INSN (next);
 
   if (INSN_P (next))
-    return emit_pattern_before_setloc (pattern, before, INSN_LOCATOR (next),
+    return emit_pattern_before_setloc (pattern, before, INSN_LOCATION (next),
 				       insnp, make_raw);
   else
     return emit_pattern_before_noloc (pattern, before,
@@ -4549,7 +4549,7 @@ emit_pattern_before (rtx pattern, rtx before, bool
                                       NULL, make_raw);
 }
 
-/* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
+/* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
 rtx
 emit_insn_before_setloc (rtx pattern, rtx before, int loc)
 {
@@ -4557,14 +4557,14 @@ emit_insn_before_setloc (rtx pattern, rtx before,
 				     make_insn_raw);
 }
 
-/* Like emit_insn_before_noloc, but set INSN_LOCATOR according to BEFORE.  */
+/* Like emit_insn_before_noloc, but set INSN_LOCATION according to BEFORE.  */
 rtx
 emit_insn_before (rtx pattern, rtx before)
 {
   return emit_pattern_before (pattern, before, true, true, make_insn_raw);
 }
 
-/* like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
+/* like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
 rtx
 emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
 {
@@ -4572,7 +4572,7 @@ emit_jump_insn_before_setloc (rtx pattern, rtx bef
 				     make_jump_insn_raw);
 }
 
-/* Like emit_jump_insn_before_noloc, but set INSN_LOCATOR according to BEFORE.  */
+/* Like emit_jump_insn_before_noloc, but set INSN_LOCATION according to BEFORE.  */
 rtx
 emit_jump_insn_before (rtx pattern, rtx before)
 {
@@ -4580,7 +4580,7 @@ emit_jump_insn_before (rtx pattern, rtx before)
 			      make_jump_insn_raw);
 }
 
-/* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
+/* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
 rtx
 emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
 {
@@ -4589,7 +4589,7 @@ emit_call_insn_before_setloc (rtx pattern, rtx bef
 }
 
 /* Like emit_call_insn_before_noloc,
-   but set insn_locator according to BEFORE.  */
+   but set insn_location according to BEFORE.  */
 rtx
 emit_call_insn_before (rtx pattern, rtx before)
 {
@@ -4597,7 +4597,7 @@ emit_call_insn_before (rtx pattern, rtx before)
 			      make_call_insn_raw);
 }
 
-/* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
+/* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
 rtx
 emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
 {
@@ -4606,7 +4606,7 @@ emit_debug_insn_before_setloc (rtx pattern, rtx be
 }
 
 /* Like emit_debug_insn_before_noloc,
-   but set insn_locator according to BEFORE.  */
+   but set insn_location according to BEFORE.  */
 rtx
 emit_debug_insn_before (rtx pattern, rtx before)
 {
@@ -5853,7 +5853,7 @@ emit_copy_of_insn_after (rtx insn, rtx after)
   /* Update LABEL_NUSES.  */
   mark_jump_label (PATTERN (new_rtx), new_rtx, 0);
 
-  INSN_LOCATOR (new_rtx) = INSN_LOCATOR (insn);
+  INSN_LOCATION (new_rtx) = INSN_LOCATION (insn);
 
   /* If the old insn is frame related, then so is the new one.  This is
      primarily needed for IA-64 unwind info which marks epilogue insns,
@@ -5888,250 +5888,66 @@ gen_hard_reg_clobber (enum machine_mode mode, unsi
 	    gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
 }
 
-/* Data structures representing mapping of INSN_LOCATOR into scope blocks, line
-   numbers and files.  In order to be GGC friendly we need to use separate
-   varrays.  This also slightly improve the memory locality in binary search.
-   The _locs array contains locators where the given property change.  The
-   block_locators_blocks contains the scope block that is used for all insn
-   locator greater than corresponding block_locators_locs value and smaller
-   than the following one.  Similarly for the other properties.  */
-static VEC(int,heap) *block_locators_locs;
-static GTY(()) VEC(tree,gc) *block_locators_blocks;
-static VEC(int,heap) *locations_locators_locs;
-DEF_VEC_A(location_t);
-DEF_VEC_ALLOC_A(location_t,heap);
-static VEC(location_t,heap) *locations_locators_vals;
-int prologue_locator;
-int epilogue_locator;
+location_t prologue_location;
+location_t epilogue_location;
 
 /* Hold current location information and last location information, so the
    datastructures are built lazily only when some instructions in given
    place are needed.  */
 static location_t curr_location, last_location;
-static tree curr_block, last_block;
-static int curr_rtl_loc = -1;
 
-/* Allocate insn locator datastructure.  */
+/* Allocate insn location datastructure.  */
 void
-insn_locators_alloc (void)
+insn_locations_init (void)
 {
-  prologue_locator = epilogue_locator = 0;
-
-  block_locators_locs = VEC_alloc (int, heap, 32);
-  block_locators_blocks = VEC_alloc (tree, gc, 32);
-  locations_locators_locs = VEC_alloc (int, heap, 32);
-  locations_locators_vals = VEC_alloc (location_t, heap, 32);
-
+  prologue_location = epilogue_location = 0;
   curr_location = UNKNOWN_LOCATION;
   last_location = UNKNOWN_LOCATION;
-  curr_block = NULL;
-  last_block = NULL;
-  curr_rtl_loc = 0;
 }
 
 /* At the end of emit stage, clear current location.  */
 void
-insn_locators_finalize (void)
+insn_locations_finalize (void)
 {
-  if (curr_rtl_loc >= 0)
-    epilogue_locator = curr_insn_locator ();
-  curr_rtl_loc = -1;
+  epilogue_location = curr_location;
+  curr_location = UNKNOWN_LOCATION;
 }
 
-/* Allocate insn locator datastructure.  */
-void
-insn_locators_free (void)
-{
-  prologue_locator = epilogue_locator = 0;
-
-  VEC_free (int, heap, block_locators_locs);
-  VEC_free (tree,gc, block_locators_blocks);
-  VEC_free (int, heap, locations_locators_locs);
-  VEC_free (location_t, heap, locations_locators_vals);
-}
-
 /* Set current location.  */
 void
-set_curr_insn_source_location (location_t location)
+set_curr_insn_location (location_t location)
 {
-  /* IV opts calls into RTL expansion to compute costs of operations.  At this
-     time locators are not initialized.  */
-  if (curr_rtl_loc == -1)
-    return;
   curr_location = location;
 }
 
 /* Get current location.  */
 location_t
-get_curr_insn_source_location (void)
+curr_insn_location (void)
 {
   return curr_location;
 }
 
-/* Set current scope block.  */
-void
-set_curr_insn_block (tree b)
-{
-  /* IV opts calls into RTL expansion to compute costs of operations.  At this
-     time locators are not initialized.  */
-  if (curr_rtl_loc == -1)
-    return;
-  if (b)
-    curr_block = b;
-}
-
-/* Get current scope block.  */
-tree
-get_curr_insn_block (void)
-{
-  return curr_block;
-}
-
-/* Return current insn locator.  */
-int
-curr_insn_locator (void)
-{
-  if (curr_rtl_loc == -1 || curr_location == UNKNOWN_LOCATION)
-    return 0;
-  if (last_block != curr_block)
-    {
-      curr_rtl_loc++;
-      VEC_safe_push (int, heap, block_locators_locs, curr_rtl_loc);
-      VEC_safe_push (tree, gc, block_locators_blocks, curr_block);
-      last_block = curr_block;
-    }
-  if (last_location != curr_location)
-    {
-      curr_rtl_loc++;
-      VEC_safe_push (int, heap, locations_locators_locs, curr_rtl_loc);
-      VEC_safe_push (location_t, heap, locations_locators_vals, &curr_location);
-      last_location = curr_location;
-    }
-  return curr_rtl_loc;
-}
-
-
-/* Return lexical scope block locator belongs to.  */
-static tree
-locator_scope (int loc)
-{
-  int max = VEC_length (int, block_locators_locs);
-  int min = 0;
-
-  /* When block_locators_locs was initialized, the pro- and epilogue
-     insns didn't exist yet and can therefore not be found this way.
-     But we know that they belong to the outer most block of the
-     current function.
-     Without this test, the prologue would be put inside the block of
-     the first valid instruction in the function and when that first
-     insn is part of an inlined function then the low_pc of that
-     inlined function is messed up.  Likewise for the epilogue and
-     the last valid instruction.  */
-  if (loc == prologue_locator || loc == epilogue_locator)
-    return DECL_INITIAL (cfun->decl);
-
-  if (!max || !loc)
-    return NULL;
-  while (1)
-    {
-      int pos = (min + max) / 2;
-      int tmp = VEC_index (int, block_locators_locs, pos);
-
-      if (tmp <= loc && min != pos)
-	min = pos;
-      else if (tmp > loc && max != pos)
-	max = pos;
-      else
-	{
-	  min = pos;
-	  break;
-	}
-    }
-  return VEC_index (tree, block_locators_blocks, min);
-}
-
 /* Return lexical scope block insn belongs to.  */
 tree
 insn_scope (const_rtx insn)
 {
-  return locator_scope (INSN_LOCATOR (insn));
+  return LOCATION_BLOCK (INSN_LOCATION (insn));
 }
 
-/* Return line number of the statement specified by the locator.  */
-location_t
-locator_location (int loc)
-{
-  int max = VEC_length (int, locations_locators_locs);
-  int min = 0;
-
-  while (1)
-    {
-      int pos = (min + max) / 2;
-      int tmp = VEC_index (int, locations_locators_locs, pos);
-
-      if (tmp <= loc && min != pos)
-	min = pos;
-      else if (tmp > loc && max != pos)
-	max = pos;
-      else
-	{
-	  min = pos;
-	  break;
-	}
-    }
-  return VEC_index (location_t, locations_locators_vals, min);
-}
-
-/* Return source line of the statement that produced this insn.  */
-int
-locator_line (int loc)
-{
-  expanded_location xloc;
-  if (!loc)
-    return 0;
-  else
-    xloc = expand_location (locator_location (loc));
-  return xloc.line;
-}
-
 /* Return line number of the statement that produced this insn.  */
 int
 insn_line (const_rtx insn)
 {
-  return locator_line (INSN_LOCATOR (insn));
+  return LOCATION_LINE (INSN_LOCATION (insn));
 }
 
-/* Return source file of the statement specified by LOC.  */
-const char *
-locator_file (int loc)
-{
-  expanded_location xloc;
-  if (!loc)
-    return 0;
-  else
-    xloc = expand_location (locator_location (loc));
-  return xloc.file;
-}
-
 /* Return source file of the statement that produced this insn.  */
 const char *
 insn_file (const_rtx insn)
 {
-  return locator_file (INSN_LOCATOR (insn));
+  return LOCATION_FILE (INSN_LOCATION (insn));
 }
 
-/* Return true if LOC1 and LOC2 locators have the same location and scope.  */
-bool
-locator_eq (int loc1, int loc2)
-{
-  if (loc1 == loc2)
-    return true;
-  if (locator_location (loc1) != locator_location (loc2))
-    return false;
-  return locator_scope (loc1) == locator_scope (loc2);
-}
-
-
 /* Return true if memory model MODEL requires a pre-operation (release-style)
    barrier or a post-operation (acquire-style) barrier.  While not universal,
    this function matches behavior of several targets.  */
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c	(revision 191083)
+++ gcc/cfgexpand.c	(working copy)
@@ -92,8 +92,7 @@ gimple_assign_rhs_to_tree (gimple stmt)
 	   && gimple_location (stmt) != EXPR_LOCATION (t))
 	  || (gimple_block (stmt)
 	      && currently_expanding_to_rtl
-	      && EXPR_P (t)
-	      && gimple_block (stmt) != TREE_BLOCK (t)))
+	      && EXPR_P (t)))
 	t = copy_node (t);
     }
   else
@@ -101,8 +100,6 @@ gimple_assign_rhs_to_tree (gimple stmt)
 
   if (gimple_has_location (stmt) && CAN_HAVE_LOCATION_P (t))
     SET_EXPR_LOCATION (t, gimple_location (stmt));
-  if (gimple_block (stmt) && currently_expanding_to_rtl && EXPR_P (t))
-    TREE_BLOCK (t) = gimple_block (stmt);
 
   return t;
 }
@@ -1831,8 +1828,7 @@ expand_gimple_cond (basic_block bb, gimple stmt)
   last2 = last = get_last_insn ();
 
   extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
-  set_curr_insn_source_location (gimple_location (stmt));
-  set_curr_insn_block (gimple_block (stmt));
+  set_curr_insn_location (gimple_location (stmt));
 
   /* These flags have no purpose in RTL land.  */
   true_edge->flags &= ~EDGE_TRUE_VALUE;
@@ -1845,13 +1841,8 @@ expand_gimple_cond (basic_block bb, gimple stmt)
       jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
 		true_edge->probability);
       maybe_dump_rtl_for_gimple_stmt (stmt, last);
-      if (true_edge->goto_locus)
-	{
-	  set_curr_insn_source_location (true_edge->goto_locus);
-	  set_curr_insn_block (true_edge->goto_block);
-	  true_edge->goto_locus = curr_insn_locator ();
-	}
-      true_edge->goto_block = NULL;
+      if (!IS_UNKNOWN_LOCATION (true_edge->goto_locus))
+	set_curr_insn_location (true_edge->goto_locus);
       false_edge->flags |= EDGE_FALLTHRU;
       maybe_cleanup_end_of_block (false_edge, last);
       return NULL;
@@ -1861,13 +1852,8 @@ expand_gimple_cond (basic_block bb, gimple stmt)
       jumpifnot_1 (code, op0, op1, label_rtx_for_bb (false_edge->dest),
 		   false_edge->probability);
       maybe_dump_rtl_for_gimple_stmt (stmt, last);
-      if (false_edge->goto_locus)
-	{
-	  set_curr_insn_source_location (false_edge->goto_locus);
-	  set_curr_insn_block (false_edge->goto_block);
-	  false_edge->goto_locus = curr_insn_locator ();
-	}
-      false_edge->goto_block = NULL;
+      if (!IS_UNKNOWN_LOCATION (false_edge->goto_locus))
+	set_curr_insn_location (false_edge->goto_locus);
       true_edge->flags |= EDGE_FALLTHRU;
       maybe_cleanup_end_of_block (true_edge, last);
       return NULL;
@@ -1876,13 +1862,8 @@ expand_gimple_cond (basic_block bb, gimple stmt)
   jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
 	    true_edge->probability);
   last = get_last_insn ();
-  if (false_edge->goto_locus)
-    {
-      set_curr_insn_source_location (false_edge->goto_locus);
-      set_curr_insn_block (false_edge->goto_block);
-      false_edge->goto_locus = curr_insn_locator ();
-    }
-  false_edge->goto_block = NULL;
+  if (!IS_UNKNOWN_LOCATION (false_edge->goto_locus))
+    set_curr_insn_location (false_edge->goto_locus);
   emit_jump (label_rtx_for_bb (false_edge->dest));
 
   BB_END (bb) = last;
@@ -1907,13 +1888,11 @@ expand_gimple_cond (basic_block bb, gimple stmt)
 
   maybe_dump_rtl_for_gimple_stmt (stmt, last2);
 
-  if (true_edge->goto_locus)
+  if (!IS_UNKNOWN_LOCATION (true_edge->goto_locus))
     {
-      set_curr_insn_source_location (true_edge->goto_locus);
-      set_curr_insn_block (true_edge->goto_block);
-      true_edge->goto_locus = curr_insn_locator ();
+      set_curr_insn_location (true_edge->goto_locus);
+      true_edge->goto_locus = curr_insn_location ();
     }
-  true_edge->goto_block = NULL;
 
   return new_bb;
 }
@@ -2013,7 +1992,6 @@ expand_call_stmt (gimple stmt)
     CALL_FROM_THUNK_P (exp) = gimple_call_from_thunk_p (stmt);
   CALL_EXPR_VA_ARG_PACK (exp) = gimple_call_va_arg_pack_p (stmt);
   SET_EXPR_LOCATION (exp, gimple_location (stmt));
-  TREE_BLOCK (exp) = gimple_block (stmt);
 
   /* Ensure RTL is created for debug args.  */
   if (decl && DECL_HAS_DEBUG_ARGS_P (decl))
@@ -2048,8 +2026,7 @@ expand_gimple_stmt_1 (gimple stmt)
 {
   tree op0;
 
-  set_curr_insn_source_location (gimple_location (stmt));
-  set_curr_insn_block (gimple_block (stmt));
+  set_curr_insn_location (gimple_location (stmt));
 
   switch (gimple_code (stmt))
     {
@@ -3793,8 +3770,7 @@ expand_gimple_basic_block (basic_block bb)
 	  tree op;
 	  gimple def;
 
-	  location_t sloc = get_curr_insn_source_location ();
-	  tree sblock = get_curr_insn_block ();
+	  location_t sloc = curr_insn_location ();
 
 	  /* Look for SSA names that have their last use here (TERed
 	     names always have only one real use).  */
@@ -3827,8 +3803,7 @@ expand_gimple_basic_block (basic_block bb)
 		    rtx val;
 		    enum machine_mode mode;
 
-		    set_curr_insn_source_location (gimple_location (def));
-		    set_curr_insn_block (gimple_block (def));
+		    set_curr_insn_location (gimple_location (def));
 
 		    DECL_ARTIFICIAL (vexpr) = 1;
 		    TREE_TYPE (vexpr) = TREE_TYPE (value);
@@ -3855,8 +3830,7 @@ expand_gimple_basic_block (basic_block bb)
 		      }
 		  }
 	      }
-	  set_curr_insn_source_location (sloc);
-	  set_curr_insn_block (sblock);
+	  set_curr_insn_location (sloc);
 	}
 
       currently_expanding_gimple_stmt = stmt;
@@ -3871,8 +3845,7 @@ expand_gimple_basic_block (basic_block bb)
 	}
       else if (gimple_debug_bind_p (stmt))
 	{
-	  location_t sloc = get_curr_insn_source_location ();
-	  tree sblock = get_curr_insn_block ();
+	  location_t sloc = curr_insn_location ();
 	  gimple_stmt_iterator nsi = gsi;
 
 	  for (;;)
@@ -3894,8 +3867,7 @@ expand_gimple_basic_block (basic_block bb)
 
 	      last = get_last_insn ();
 
-	      set_curr_insn_source_location (gimple_location (stmt));
-	      set_curr_insn_block (gimple_block (stmt));
+	      set_curr_insn_location (gimple_location (stmt));
 
 	      if (DECL_P (var))
 		mode = DECL_MODE (var);
@@ -3933,13 +3905,11 @@ expand_gimple_basic_block (basic_block bb)
 		break;
 	    }
 
-	  set_curr_insn_source_location (sloc);
-	  set_curr_insn_block (sblock);
+	  set_curr_insn_location (sloc);
 	}
       else if (gimple_debug_source_bind_p (stmt))
 	{
-	  location_t sloc = get_curr_insn_source_location ();
-	  tree sblock = get_curr_insn_block ();
+	  location_t sloc = curr_insn_location ();
 	  tree var = gimple_debug_source_bind_get_var (stmt);
 	  tree value = gimple_debug_source_bind_get_value (stmt);
 	  rtx val;
@@ -3947,8 +3917,7 @@ expand_gimple_basic_block (basic_block bb)
 
 	  last = get_last_insn ();
 
-	  set_curr_insn_source_location (gimple_location (stmt));
-	  set_curr_insn_block (gimple_block (stmt));
+	  set_curr_insn_location (gimple_location (stmt));
 
 	  mode = DECL_MODE (var);
 
@@ -3966,8 +3935,7 @@ expand_gimple_basic_block (basic_block bb)
 	      PAT_VAR_LOCATION_LOC (val) = (rtx)value;
 	    }
 
-	  set_curr_insn_source_location (sloc);
-	  set_curr_insn_block (sblock);
+	  set_curr_insn_location (sloc);
 	}
       else
 	{
@@ -4008,13 +3976,8 @@ expand_gimple_basic_block (basic_block bb)
   /* Expand implicit goto and convert goto_locus.  */
   FOR_EACH_EDGE (e, ei, bb->succs)
     {
-      if (e->goto_locus && e->goto_block)
-	{
-	  set_curr_insn_source_location (e->goto_locus);
-	  set_curr_insn_block (e->goto_block);
-	  e->goto_locus = curr_insn_locator ();
-	}
-      e->goto_block = NULL;
+      if (!IS_UNKNOWN_LOCATION (e->goto_locus))
+	set_curr_insn_location (e->goto_locus);
       if ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb)
 	{
 	  emit_jump (label_rtx_for_bb (e->dest));
@@ -4134,12 +4097,9 @@ construct_exit_block (void)
 
   /* Make sure the locus is set to the end of the function, so that
      epilogue line numbers and warnings are set properly.  */
-  if (cfun->function_end_locus != UNKNOWN_LOCATION)
+  if (!IS_UNKNOWN_LOCATION (cfun->function_end_locus))
     input_location = cfun->function_end_locus;
 
-  /* The following insns belong to the top scope.  */
-  set_curr_insn_block (DECL_INITIAL (current_function_decl));
-
   /* Generate rtl for function exit.  */
   expand_function_end ();
 
@@ -4357,20 +4317,19 @@ gimple_expand_cfg (void)
 
   rtl_profile_for_bb (ENTRY_BLOCK_PTR);
 
-  insn_locators_alloc ();
+  insn_locations_init ();
   if (!DECL_IS_BUILTIN (current_function_decl))
     {
       /* Eventually, all FEs should explicitly set function_start_locus.  */
-      if (cfun->function_start_locus == UNKNOWN_LOCATION)
-       set_curr_insn_source_location
+      if (IS_UNKNOWN_LOCATION (cfun->function_start_locus))
+       set_curr_insn_location
          (DECL_SOURCE_LOCATION (current_function_decl));
       else
-       set_curr_insn_source_location (cfun->function_start_locus);
+       set_curr_insn_location (cfun->function_start_locus);
     }
   else
-    set_curr_insn_source_location (UNKNOWN_LOCATION);
-  set_curr_insn_block (DECL_INITIAL (current_function_decl));
-  prologue_locator = curr_insn_locator ();
+    set_curr_insn_location (UNKNOWN_LOCATION);
+  prologue_location = curr_insn_location ();
 
 #ifdef INSN_SCHEDULING
   init_sched_attrs ();
@@ -4551,8 +4510,7 @@ gimple_expand_cfg (void)
   free_histograms ();
 
   construct_exit_block ();
-  set_curr_insn_block (DECL_INITIAL (current_function_decl));
-  insn_locators_finalize ();
+  insn_locations_finalize ();
 
   /* Zap the tree EH table.  */
   set_eh_throw_stmt_table (cfun, NULL);
Index: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c	(revision 191083)
+++ gcc/cfgcleanup.c	(working copy)
@@ -481,13 +481,15 @@ try_forward_edges (int mode, basic_block b)
 		  int new_locus = single_succ_edge (target)->goto_locus;
 		  int locus = goto_locus;
 
-		  if (new_locus && locus && !locator_eq (new_locus, locus))
+		  if (!IS_UNKNOWN_LOCATION (new_locus)
+		      && !IS_UNKNOWN_LOCATION (locus)
+		      && new_locus != locus)
 		    new_target = NULL;
 		  else
 		    {
 		      rtx last;
 
-		      if (new_locus)
+		      if (!IS_UNKNOWN_LOCATION (new_locus))
 			locus = new_locus;
 
 		      last = BB_END (target);
@@ -495,13 +497,15 @@ try_forward_edges (int mode, basic_block b)
 			last = prev_nondebug_insn (last);
 
 		      new_locus = last && INSN_P (last)
-				  ? INSN_LOCATOR (last) : 0;
+				  ? INSN_LOCATION (last) : 0;
 
-		      if (new_locus && locus && !locator_eq (new_locus, locus))
+		      if (!IS_UNKNOWN_LOCATION (new_locus)
+			  && !IS_UNKNOWN_LOCATION (locus)
+			  && new_locus != locus)
 			new_target = NULL;
 		      else
 			{
-			  if (new_locus)
+			  if (!IS_UNKNOWN_LOCATION (new_locus))
 			    locus = new_locus;
 
 			  goto_locus = locus;
Index: gcc/tree-ssa-live.c
===================================================================
--- gcc/tree-ssa-live.c	(revision 191083)
+++ gcc/tree-ssa-live.c	(working copy)
@@ -597,7 +597,7 @@ remove_unused_scope_block_p (tree scope)
    else
    /* Verfify that only blocks with source location set
       are entry points to the inlined functions.  */
-     gcc_assert (BLOCK_SOURCE_LOCATION (scope) == UNKNOWN_LOCATION);
+     gcc_assert (IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (scope)));
 
    TREE_USED (scope) = !unused;
    return unused;
@@ -625,7 +625,7 @@ dump_scope_block (FILE *file, int indent, tree sco
   fprintf (file, "\n%*s{ Scope block #%i%s%s",indent, "" , BLOCK_NUMBER (scope),
   	   TREE_USED (scope) ? "" : " (unused)",
 	   BLOCK_ABSTRACT (scope) ? " (abstract)": "");
-  if (BLOCK_SOURCE_LOCATION (scope) != UNKNOWN_LOCATION)
+  if (!IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (scope)))
     {
       expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (scope));
       fprintf (file, " %s:%i", s.file, s.line);
@@ -758,13 +758,18 @@ remove_unused_locals (void)
           FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_ALL_USES)
             {
 	      tree arg = USE_FROM_PTR (arg_p);
+	      int index = PHI_ARG_INDEX_FROM_USE (arg_p);
+	      tree block =
+		LOCATION_BLOCK (gimple_phi_arg_location (phi, index));
+	      if (block != NULL)
+		TREE_USED (block) = true;
 	      mark_all_vars_used (&arg);
             }
         }
 
       FOR_EACH_EDGE (e, ei, bb->succs)
 	if (e->goto_locus)
-	  TREE_USED (e->goto_block) = true;
+	  TREE_USED (LOCATION_BLOCK (e->goto_locus)) = true;
     }
 
   /* We do a two-pass approach about the out-of-scope clobbers.  We want
Index: gcc/lto/lto.c
===================================================================
--- gcc/lto/lto.c	(revision 191083)
+++ gcc/lto/lto.c	(working copy)
@@ -1559,8 +1559,6 @@ lto_fixup_prevailing_decls (tree t)
 {
   enum tree_code code = TREE_CODE (t);
   LTO_NO_PREVAIL (TREE_TYPE (t));
-  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
-    LTO_NO_PREVAIL (TREE_CHAIN (t));
   if (DECL_P (t))
     {
       LTO_NO_PREVAIL (DECL_NAME (t));
@@ -1616,7 +1614,6 @@ lto_fixup_prevailing_decls (tree t)
   else if (EXPR_P (t))
     {
       int i;
-      LTO_NO_PREVAIL (t->exp.block);
       for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i)
 	LTO_SET_PREVAIL (TREE_OPERAND (t, i));
     }
Index: gcc/tree-streamer-out.c
===================================================================
--- gcc/tree-streamer-out.c	(revision 191083)
+++ gcc/tree-streamer-out.c	(working copy)
@@ -471,7 +471,7 @@ write_ts_decl_minimal_tree_pointers (struct output
 {
   stream_write_tree (ob, DECL_NAME (expr), ref_p);
   stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
-  lto_output_location (ob, DECL_SOURCE_LOCATION (expr));
+  lto_output_location (ob, LOCATION_LOCUS (DECL_SOURCE_LOCATION (expr)));
 }
 
 
@@ -668,7 +668,7 @@ write_ts_exp_tree_pointers (struct output_block *o
   streamer_write_hwi (ob, TREE_OPERAND_LENGTH (expr));
   for (i = 0; i < TREE_OPERAND_LENGTH (expr); i++)
     stream_write_tree (ob, TREE_OPERAND (expr, i), ref_p);
-  lto_output_location (ob, EXPR_LOCATION (expr));
+  lto_output_location (ob, LOCATION_LOCUS (EXPR_LOCATION (expr)));
   stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
 }
 
Index: gcc/rtl.c
===================================================================
--- gcc/rtl.c	(revision 191083)
+++ gcc/rtl.c	(working copy)
@@ -435,7 +435,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equa
 #ifndef GENERATOR_FILE
 	      if (((code == ASM_OPERANDS && i == 6)
 		   || (code == ASM_INPUT && i == 1))
-		  && locator_eq (XINT (x, i), XINT (y, i)))
+		  && XINT (x, i) == XINT (y, i))
 		break;
 #endif
 	      return 0;
@@ -572,7 +572,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
 #ifndef GENERATOR_FILE
 	      if (((code == ASM_OPERANDS && i == 6)
 		   || (code == ASM_INPUT && i == 1))
-		  && locator_eq (XINT (x, i), XINT (y, i)))
+		  && XINT (x, i) == XINT (y, i))
 		break;
 #endif
 	      return 0;
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	(revision 191083)
+++ gcc/rtl.h	(working copy)
@@ -765,6 +765,7 @@ extern void rtl_check_failed_flag (const char *, c
 #endif
 
 #define XINT(RTX, N)	(RTL_CHECK2 (RTX, N, 'i', 'n').rt_int)
+#define XUINT(RTX, N)   (RTL_CHECK2 (RTX, N, 'i', 'n').rt_uint)
 #define XSTR(RTX, N)	(RTL_CHECK2 (RTX, N, 's', 'S').rt_str)
 #define XEXP(RTX, N)	(RTL_CHECK2 (RTX, N, 'e', 'u').rt_rtx)
 #define XVEC(RTX, N)	(RTL_CHECK2 (RTX, N, 'E', 'V').rt_rtvec)
@@ -828,13 +829,13 @@ extern void rtl_check_failed_flag (const char *, c
 /* The body of an insn.  */
 #define PATTERN(INSN)	XEXP (INSN, 4)
 
-#define INSN_LOCATOR(INSN) XINT (INSN, 5)
+#define INSN_LOCATION(INSN) XUINT (INSN, 5)
+
+#define INSN_HAS_LOCATION(INSN) (!IS_UNKNOWN_LOCATION (INSN_LOCATION (INSN)))
+
 /* LOCATION of an RTX if relevant.  */
 #define RTL_LOCATION(X) (INSN_P (X) ? \
-			 locator_location (INSN_LOCATOR (X)) \
-			 : UNKNOWN_LOCATION)
-/* LOCATION of current INSN.  */
-#define CURR_INSN_LOCATION (locator_location (curr_insn_locator ()))
+			 INSN_LOCATION (X) : UNKNOWN_LOCATION)
 
 /* Code number of instruction, from when it was recognized.
    -1 means this instruction has not been recognized yet.  */
@@ -1833,12 +1834,8 @@ extern rtx prev_cc0_setter (rtx);
 /* In emit-rtl.c  */
 extern int insn_line (const_rtx);
 extern const char * insn_file (const_rtx);
-extern location_t locator_location (int);
-extern int locator_line (int);
-extern const char * locator_file (int);
-extern bool locator_eq (int, int);
-extern int prologue_locator, epilogue_locator;
 extern tree insn_scope (const_rtx);
+extern location_t prologue_location, epilogue_location;
 
 /* In jump.c */
 extern enum rtx_code reverse_condition (enum rtx_code);
@@ -2675,14 +2672,10 @@ extern const struct rtl_hooks general_rtl_hooks;
 /* Keep this for the nonce.  */
 #define gen_lowpart rtl_hooks.gen_lowpart
 
-extern void insn_locators_alloc (void);
-extern void insn_locators_free (void);
-extern void insn_locators_finalize (void);
-extern void set_curr_insn_source_location (location_t);
-extern location_t get_curr_insn_source_location (void);
-extern void set_curr_insn_block (tree);
-extern tree get_curr_insn_block (void);
-extern int curr_insn_locator (void);
+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);
 
Index: gcc/tree-inline.c
===================================================================
--- gcc/tree-inline.c	(revision 191083)
+++ gcc/tree-inline.c	(working copy)
@@ -830,10 +830,6 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, v
       /* Otherwise, just copy the node.  Note that copy_tree_r already
 	 knows not to copy VAR_DECLs, etc., so this is safe.  */
 
-      /* We should never have TREE_BLOCK set on non-statements.  */
-      if (EXPR_P (*tp))
-	gcc_assert (!TREE_BLOCK (*tp));
-
       if (TREE_CODE (*tp) == MEM_REF)
 	{
 	  tree ptr = TREE_OPERAND (*tp, 0);
@@ -872,13 +868,9 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, v
 	{
 	  /* Variable substitution need not be simple.  In particular,
 	     the MEM_REF substitution above.  Make sure that
-	     TREE_CONSTANT and friends are up-to-date.  But make sure
-	     to not improperly set TREE_BLOCK on some sub-expressions.  */
+	     TREE_CONSTANT and friends are up-to-date.  */
 	  int invariant = is_gimple_min_invariant (*tp);
-	  tree block = id->block;
-	  id->block = NULL_TREE;
 	  walk_tree (&TREE_OPERAND (*tp, 0), remap_gimple_op_r, data, NULL);
-	  id->block = block;
 	  recompute_tree_invariant_for_addr_expr (*tp);
 
 	  /* If this used to be invariant, but is not any longer,
@@ -890,6 +882,22 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, v
 	}
     }
 
+  /* Update the TREE_BLOCK for the cloned expr.  */
+  if (EXPR_P (*tp))
+    {
+      tree new_block = id->remapping_type_depth == 0 ? id->block : NULL;
+      tree old_block = TREE_BLOCK (*tp);
+      if (old_block)
+	{
+	  tree *n;
+	  n = (tree *) pointer_map_contains (id->decl_map,
+					     TREE_BLOCK (*tp));
+	  if (n)
+	    new_block = *n;
+	}
+      TREE_SET_BLOCK (*tp, new_block);
+    }
+
   /* Keep iterating.  */
   return NULL_TREE;
 }
@@ -1107,11 +1115,10 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, vo
 	      tree *n;
 	      n = (tree *) pointer_map_contains (id->decl_map,
 						 TREE_BLOCK (*tp));
-	      gcc_assert (n || id->remapping_type_depth != 0);
 	      if (n)
 		new_block = *n;
 	    }
-	  TREE_BLOCK (*tp) = new_block;
+	  TREE_SET_BLOCK (*tp, new_block);
 	}
 
       if (TREE_CODE (*tp) != OMP_CLAUSE)
@@ -1982,6 +1989,7 @@ copy_phis_for_bb (basic_block bb, copy_body_data *
 	      tree new_arg;
 	      tree block = id->block;
 	      edge_iterator ei2;
+	      location_t locus;
 
 	      /* When doing partial cloning, we allow PHIs on the entry block
 		 as long as all the arguments are the same.  Find any input
@@ -1993,9 +2001,7 @@ copy_phis_for_bb (basic_block bb, copy_body_data *
 
 	      arg = PHI_ARG_DEF_FROM_EDGE (phi, old_edge);
 	      new_arg = arg;
-	      id->block = NULL_TREE;
 	      walk_tree (&new_arg, copy_tree_body_r, id, NULL);
-	      id->block = block;
 	      gcc_assert (new_arg);
 	      /* With return slot optimization we can end up with
 	         non-gimple (foo *)&this->m, fix that here.  */
@@ -2008,8 +2014,19 @@ copy_phis_for_bb (basic_block bb, copy_body_data *
 		  gsi_insert_seq_on_edge (new_edge, stmts);
 		  inserted = true;
 		}
+	      locus = gimple_phi_arg_location_from_edge (phi, old_edge);
+	      block = id->block;
+	      if (LOCATION_BLOCK (locus))
+		{
+		  tree *n;
+		  n = (tree *) pointer_map_contains (id->decl_map,
+			LOCATION_BLOCK (locus));
+		  gcc_assert (n);
+		  block = *n;
+		}
+
 	      add_phi_arg (new_phi, new_arg, new_edge,
-			   gimple_phi_arg_location_from_edge (phi, old_edge));
+			   COMBINE_LOCATION_DATA (locus, block));
 	    }
 	}
     }
@@ -3874,7 +3891,8 @@ expand_call_inline (basic_block bb, gimple stmt, c
   id->block = make_node (BLOCK);
   BLOCK_ABSTRACT_ORIGIN (id->block) = fn;
   BLOCK_SOURCE_LOCATION (id->block) = input_location;
-  prepend_lexical_block (gimple_block (stmt), id->block);
+  if (gimple_block (stmt))
+    prepend_lexical_block (gimple_block (stmt), id->block);
 
   /* Local declarations will be replaced by their equivalents in this
      map.  */
Index: gcc/tree-streamer-in.c
===================================================================
--- gcc/tree-streamer-in.c	(revision 191083)
+++ gcc/tree-streamer-in.c	(working copy)
@@ -776,7 +776,7 @@ lto_input_ts_exp_tree_pointers (struct lto_input_b
 
   loc = lto_input_location (ib, data_in);
   SET_EXPR_LOCATION (expr, loc);
-  TREE_BLOCK (expr) = stream_read_tree (ib, data_in);
+  TREE_SET_BLOCK (expr, stream_read_tree (ib, data_in));
 }
 
 
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	(revision 191083)
+++ gcc/combine.c	(working copy)
@@ -2739,7 +2739,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *
 
 	  i1 = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
 			     BLOCK_FOR_INSN (i2), XVECEXP (PATTERN (i2), 0, 1),
-			     INSN_LOCATOR (i2), -1, NULL_RTX);
+			     INSN_LOCATION (i2), -1, NULL_RTX);
 
 	  SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
 	  SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
Index: gcc/tree-outof-ssa.c
===================================================================
--- gcc/tree-outof-ssa.c	(revision 191083)
+++ gcc/tree-outof-ssa.c	(working copy)
@@ -108,8 +108,7 @@ set_location_for_edge (edge e)
 {
   if (e->goto_locus)
     {
-      set_curr_insn_source_location (e->goto_locus);
-      set_curr_insn_block (e->goto_block);
+      set_curr_insn_location (e->goto_locus);
     }
   else
     {
@@ -125,8 +124,7 @@ set_location_for_edge (edge e)
 		continue;
 	      if (gimple_has_location (stmt) || gimple_block (stmt))
 		{
-		  set_curr_insn_source_location (gimple_location (stmt));
-		  set_curr_insn_block (gimple_block (stmt));
+		  set_curr_insn_location (gimple_location (stmt));
 		  return;
 		}
 	    }
@@ -191,7 +189,7 @@ insert_partition_copy_on_edge (edge e, int dest, i
   set_location_for_edge (e);
   /* If a locus is provided, override the default.  */
   if (locus)
-    set_curr_insn_source_location (locus);
+    set_curr_insn_location (locus);
 
   var = partition_to_var (SA.map, src);
   seq = emit_partition_copy (SA.partition_to_pseudo[dest],
@@ -228,7 +226,7 @@ insert_value_copy_on_edge (edge e, int dest, tree
   set_location_for_edge (e);
   /* If a locus is provided, override the default.  */
   if (locus)
-    set_curr_insn_source_location (locus);
+    set_curr_insn_location (locus);
 
   start_sequence ();
 
@@ -284,7 +282,7 @@ insert_rtx_to_part_on_edge (edge e, int dest, rtx
   set_location_for_edge (e);
   /* If a locus is provided, override the default.  */
   if (locus)
-    set_curr_insn_source_location (locus);
+    set_curr_insn_location (locus);
 
   /* We give the destination as sizeexp in case src/dest are BLKmode
      mems.  Usually we give the source.  As we result from SSA names
@@ -320,7 +318,7 @@ insert_part_to_rtx_on_edge (edge e, rtx dest, int
   set_location_for_edge (e);
   /* If a locus is provided, override the default.  */
   if (locus)
-    set_curr_insn_source_location (locus);
+    set_curr_insn_location (locus);
 
   var = partition_to_var (SA.map, src);
   seq = emit_partition_copy (dest,
Index: gcc/basic-block.h
===================================================================
--- gcc/basic-block.h	(revision 191083)
+++ gcc/basic-block.h	(working copy)
@@ -48,8 +48,7 @@ struct GTY((user)) edge_def {
   /* Auxiliary info specific to a pass.  */
   PTR aux;
 
-  /* Location of any goto implicit in the edge and associated BLOCK.  */
-  tree goto_block;
+  /* Location of any goto implicit in the edge.  */
   location_t goto_locus;
 
   /* The index number corresponding to this edge in the edge vector
Index: gcc/gimple.h
===================================================================
--- gcc/gimple.h	(revision 191083)
+++ gcc/gimple.h	(working copy)
@@ -210,10 +210,6 @@ struct GTY((chain_next ("%h.next"))) gimple_statem
      and the prev pointer being the last.  */
   gimple next;
   gimple GTY((skip)) prev;
-
-  /* [ WORD 6 ]
-     Lexical block holding this statement.  */
-  tree block;
 };
 
 
@@ -1197,7 +1193,7 @@ gimple_bb (const_gimple g)
 static inline tree
 gimple_block (const_gimple g)
 {
-  return g->gsbase.block;
+  return LOCATION_BLOCK (g->gsbase.location);
 }
 
 
@@ -1206,7 +1202,7 @@ gimple_block (const_gimple g)
 static inline void
 gimple_set_block (gimple g, tree block)
 {
-  g->gsbase.block = block;
+  g->gsbase.location = COMBINE_LOCATION_DATA (g->gsbase.location, block);
 }
 
 
@@ -1241,7 +1237,7 @@ gimple_set_location (gimple g, location_t location
 static inline bool
 gimple_has_location (const_gimple g)
 {
-  return gimple_location (g) != UNKNOWN_LOCATION;
+  return !IS_UNKNOWN_LOCATION (gimple_location (g));
 }
 
 
Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c	(revision 191083)
+++ gcc/tree-cfg.c	(working copy)
@@ -809,15 +809,11 @@ make_cond_expr_edges (basic_block 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);
     }
 
   /* We do not need the labels anymore.  */
@@ -1027,8 +1023,6 @@ make_goto_expr_edges (basic_block bb)
       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);
       return;
     }
@@ -1487,7 +1481,7 @@ gimple_can_merge_blocks_p (basic_block a, basic_bl
 
   /* When not optimizing, don't merge if we'd lose goto_locus.  */
   if (!optimize
-      && single_succ_edge (a)->goto_locus != UNKNOWN_LOCATION)
+      && single_succ_edge (a)->goto_locus)
     {
       location_t goto_locus = single_succ_edge (a)->goto_locus;
       gimple_stmt_iterator prev, next;
@@ -5980,9 +5974,21 @@ move_stmt_op (tree *tp, int *walk_subtrees, void *
   tree t = *tp;
 
   if (EXPR_P (t))
-    /* We should never have TREE_BLOCK set on non-statements.  */
-    gcc_assert (!TREE_BLOCK (t));
-
+    {
+      tree block = TREE_BLOCK (t);
+      if (p->orig_block == NULL_TREE
+	  || block == p->orig_block
+	  || block == NULL_TREE)
+	TREE_SET_BLOCK (t, p->new_block);
+#ifdef ENABLE_CHECKING
+      else if (block != p->new_block)
+	{
+	  while (block && block != p->orig_block)
+	    block = BLOCK_SUPERCONTEXT (block);
+	  gcc_assert (block);
+	}
+#endif
+    }
   else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
     {
       if (TREE_CODE (t) == SSA_NAME)
@@ -6282,12 +6288,12 @@ move_block_to_fn (struct function *dest_cfun, basi
     }
 
   FOR_EACH_EDGE (e, ei, bb->succs)
-    if (e->goto_locus)
+    if (!IS_UNKNOWN_LOCATION (e->goto_locus))
       {
-	tree block = e->goto_block;
+	tree block = LOCATION_BLOCK (e->goto_locus);
 	if (d->orig_block == NULL_TREE
 	    || block == d->orig_block)
-	  e->goto_block = d->new_block;
+	  e->goto_locus = COMBINE_LOCATION_DATA (e->goto_locus, d->new_block);
 #ifdef ENABLE_CHECKING
 	else if (block != d->new_block)
 	  {
@@ -7867,7 +7873,6 @@ gt_ggc_mx (edge_def *e)
     gt_ggc_mx (e->insns.g);
   else
     gt_ggc_mx (e->insns.r);
-  gt_ggc_mx (e->goto_block);
 }
 
 /* PCH support for edge_def.  */
@@ -7886,7 +7891,6 @@ gt_pch_nx (edge_def *e)
     gt_pch_nx (e->insns.g);
   else
     gt_pch_nx (e->insns.r);
-  gt_pch_nx (e->goto_block);
 }
 
 void
@@ -7898,5 +7902,4 @@ gt_pch_nx (edge_def *e, gt_pointer_operator op, vo
     op (&(e->insns.g), cookie);
   else
     op (&(e->insns.r), cookie);
-  op (&(e->goto_block), cookie);
 }
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	(revision 191083)
+++ gcc/config/alpha/alpha.c	(working copy)
@@ -8362,7 +8362,6 @@ alpha_output_mi_thunk_osf (FILE *file, tree thunk_
      instruction scheduling worth while.  Note that use_thunk calls
      assemble_start_function and assemble_end_function.  */
   insn = get_insns ();
-  insn_locators_alloc ();
   shorten_branches (insn);
   final_start_function (insn, file, 1);
   final (insn, file, 1);
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	(revision 191083)
+++ gcc/config/sparc/sparc.c	(working copy)
@@ -10654,7 +10654,6 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fnde
      instruction scheduling worth while.  Note that use_thunk calls
      assemble_start_function and assemble_end_function.  */
   insn = get_insns ();
-  insn_locators_alloc ();
   shorten_branches (insn);
   final_start_function (insn, file, 1);
   final (insn, file, 1);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 191083)
+++ gcc/config/i386/i386.c	(working copy)
@@ -33431,7 +33431,6 @@ x86_output_mi_thunk (FILE *file,
   /* Emit just enough of rest_of_compilation to get the insns emitted.
      Note that use_thunk calls assemble_start_function et al.  */
   tmp = get_insns ();
-  insn_locators_alloc ();
   shorten_branches (tmp);
   final_start_function (tmp, file, 1);
   final (tmp, file, 1);
Index: gcc/config/tilegx/tilegx.c
===================================================================
--- gcc/config/tilegx/tilegx.c	(revision 191083)
+++ gcc/config/tilegx/tilegx.c	(working copy)
@@ -4883,7 +4883,6 @@ tilegx_output_mi_thunk (FILE *file, tree thunk_fnd
      serial except for the tail call, so we're only wasting one cycle.
    */
   insn = get_insns ();
-  insn_locators_alloc ();
   shorten_branches (insn);
   final_start_function (insn, file, 1);
   final (insn, file, 1);
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	(revision 191083)
+++ gcc/config/sh/sh.c	(working copy)
@@ -12171,7 +12171,6 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl
      the insns emitted.  Note that use_thunk calls
      assemble_start_function and assemble_end_function.  */
 
-  insn_locators_alloc ();
   insns = get_insns ();
 
   if (optimize > 0)
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c	(revision 191083)
+++ gcc/config/ia64/ia64.c	(working copy)
@@ -10852,7 +10852,6 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRI
      instruction scheduling worth while.  Note that use_thunk calls
      assemble_start_function and assemble_end_function.  */
 
-  insn_locators_alloc ();
   emit_all_insn_group_barriers (NULL);
   insn = get_insns ();
   shorten_branches (insn);
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 191083)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -21658,7 +21658,6 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fnd
      instruction scheduling worth while.  Note that use_thunk calls
      assemble_start_function and assemble_end_function.  */
   insn = get_insns ();
-  insn_locators_alloc ();
   shorten_branches (insn);
   final_start_function (insn, file, 1);
   final (insn, file, 1);
Index: gcc/config/score/score.c
===================================================================
--- gcc/config/score/score.c	(revision 191083)
+++ gcc/config/score/score.c	(working copy)
@@ -502,7 +502,6 @@ score_output_mi_thunk (FILE *file, tree thunk_fnde
   /* Run just enough of rest_of_compilation.  This sequence was
      "borrowed" from alpha.c.  */
   insn = get_insns ();
-  insn_locators_alloc ();
   split_all_insns_noflow ();
   shorten_branches (insn);
   final_start_function (insn, file, 1);
Index: gcc/config/tilepro/tilepro.c
===================================================================
--- gcc/config/tilepro/tilepro.c	(revision 191083)
+++ gcc/config/tilepro/tilepro.c	(working copy)
@@ -4407,7 +4407,6 @@ tilepro_asm_output_mi_thunk (FILE *file, tree thun
      serial except for the tail call, so we're only wasting one cycle.
    */
   insn = get_insns ();
-  insn_locators_alloc ();
   shorten_branches (insn);
   final_start_function (insn, file, 1);
   final (insn, file, 1);
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	(revision 191083)
+++ gcc/config/mips/mips.c	(working copy)
@@ -15864,7 +15864,6 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndec
   /* Run just enough of rest_of_compilation.  This sequence was
      "borrowed" from alpha.c.  */
   insn = get_insns ();
-  insn_locators_alloc ();
   split_all_insns_noflow ();
   mips16_lay_out_constants (true);
   shorten_branches (insn);
Index: gcc/cfgrtl.c
===================================================================
--- gcc/cfgrtl.c	(revision 191083)
+++ gcc/cfgrtl.c	(working copy)
@@ -720,19 +720,19 @@ rtl_split_block (basic_block bb, void *insnp)
 static bool
 unique_locus_on_edge_between_p (basic_block a, basic_block b)
 {
-  const int goto_locus = EDGE_SUCC (a, 0)->goto_locus;
+  const location_t goto_locus = EDGE_SUCC (a, 0)->goto_locus;
   rtx insn, end;
 
-  if (!goto_locus)
+  if (IS_UNKNOWN_LOCATION (goto_locus))
     return false;
 
   /* First scan block A backward.  */
   insn = BB_END (a);
   end = PREV_INSN (BB_HEAD (a));
-  while (insn != end && (!NONDEBUG_INSN_P (insn) || INSN_LOCATOR (insn) == 0))
+  while (insn != end && (!NONDEBUG_INSN_P (insn) || !INSN_HAS_LOCATION (insn)))
     insn = PREV_INSN (insn);
 
-  if (insn != end && locator_eq (INSN_LOCATOR (insn), goto_locus))
+  if (insn != end && INSN_LOCATION (insn) == goto_locus)
     return false;
 
   /* Then scan block B forward.  */
@@ -743,8 +743,8 @@ unique_locus_on_edge_between_p (basic_block a, bas
       while (insn != end && !NONDEBUG_INSN_P (insn))
 	insn = NEXT_INSN (insn);
 
-      if (insn != end && INSN_LOCATOR (insn) != 0
-	  && locator_eq (INSN_LOCATOR (insn), goto_locus))
+      if (insn != end && INSN_HAS_LOCATION (insn)
+	  && INSN_LOCATION (insn) == goto_locus)
 	return false;
     }
 
@@ -761,7 +761,7 @@ emit_nop_for_unique_locus_between (basic_block a,
     return;
 
   BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
-  INSN_LOCATOR (BB_END (a)) = EDGE_SUCC (a, 0)->goto_locus;
+  INSN_LOCATION (BB_END (a)) = EDGE_SUCC (a, 0)->goto_locus;
 }
 
 /* Blocks A and B are to be merged into a single block A.  The insns
@@ -1477,7 +1477,7 @@ force_nonfallthru_and_redirect (edge e, basic_bloc
   else
     jump_block = e->src;
 
-  if (e->goto_locus && e->goto_block == NULL)
+  if (!IS_UNKNOWN_LOCATION (e->goto_locus))
     loc = e->goto_locus;
   else
     loc = 0;
@@ -3335,7 +3335,8 @@ fixup_reorder_chain (void)
         edge_iterator ei;
 
         FOR_EACH_EDGE (e, ei, bb->succs)
-	  if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
+	  if (!IS_UNKNOWN_LOCATION (e->goto_locus)
+	      && !(e->flags & EDGE_ABNORMAL))
 	    {
 	      edge e2;
 	      edge_iterator ei2;
@@ -3345,15 +3346,15 @@ fixup_reorder_chain (void)
 	      insn = BB_END (e->src);
 	      end = PREV_INSN (BB_HEAD (e->src));
 	      while (insn != end
-		     && (!NONDEBUG_INSN_P (insn) || INSN_LOCATOR (insn) == 0))
+		     && (!NONDEBUG_INSN_P (insn) || !INSN_HAS_LOCATION (insn)))
 		insn = PREV_INSN (insn);
 	      if (insn != end
-		  && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
+		  && INSN_LOCATION (insn) == e->goto_locus)
 		continue;
 	      if (simplejump_p (BB_END (e->src))
-		  && INSN_LOCATOR (BB_END (e->src)) == 0)
+		  && !INSN_HAS_LOCATION (BB_END (e->src)))
 		{
-		  INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
+		  INSN_LOCATION (BB_END (e->src)) = e->goto_locus;
 		  continue;
 		}
 	      dest = e->dest;
@@ -3369,24 +3370,24 @@ fixup_reorder_chain (void)
 		  end = NEXT_INSN (BB_END (dest));
 		  while (insn != end && !NONDEBUG_INSN_P (insn))
 		    insn = NEXT_INSN (insn);
-		  if (insn != end && INSN_LOCATOR (insn)
-		      && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
+		  if (insn != end && INSN_HAS_LOCATION (insn)
+		      && INSN_LOCATION (insn) == e->goto_locus)
 		    continue;
 		}
 	      nb = split_edge (e);
 	      if (!INSN_P (BB_END (nb)))
 		BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb),
 						     nb);
-	      INSN_LOCATOR (BB_END (nb)) = e->goto_locus;
+	      INSN_LOCATION (BB_END (nb)) = e->goto_locus;
 
 	      /* If there are other incoming edges to the destination block
 		 with the same goto locus, redirect them to the new block as
 		 well, this can prevent other such blocks from being created
 		 in subsequent iterations of the loop.  */
 	      for (ei2 = ei_start (dest->preds); (e2 = ei_safe_edge (ei2)); )
-		if (e2->goto_locus
+		if (!IS_UNKNOWN_LOCATION (e2->goto_locus)
 		    && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
-		    && locator_eq (e->goto_locus, e2->goto_locus))
+		    && e->goto_locus == e2->goto_locus)
 		  redirect_edge_and_branch (e2, nb);
 		else
 		  ei_next (&ei2);
@@ -4086,7 +4087,7 @@ cfg_layout_merge_blocks (basic_block a, basic_bloc
     }
 
   /* If B was a forwarder block, propagate the locus on the edge.  */
-  if (forwarder_p && !EDGE_SUCC (b, 0)->goto_locus)
+  if (forwarder_p && IS_UNKNOWN_LOCATION (EDGE_SUCC (b, 0)->goto_locus))
     EDGE_SUCC (b, 0)->goto_locus = EDGE_SUCC (a, 0)->goto_locus;
 
   if (dump_file)
Index: gcc/stmt.c
===================================================================
--- gcc/stmt.c	(revision 191083)
+++ gcc/stmt.c	(working copy)
@@ -2392,7 +2392,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rt
 		 then emit the code for one side at a time.  */
 
 	      tree test_label
-		= build_decl (CURR_INSN_LOCATION,
+		= build_decl (curr_insn_location (),
 			      LABEL_DECL, NULL_TREE, NULL_TREE);
 
 	      /* See if the value is on the right.  */
@@ -2516,7 +2516,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rt
 	      /* Right hand node requires testing.
 		 Branch to a label where we will handle it later.  */
 
-	      test_label = build_decl (CURR_INSN_LOCATION,
+	      test_label = build_decl (curr_insn_location (),
 				       LABEL_DECL, NULL_TREE, NULL_TREE);
 	      emit_cmp_and_jump_insns (index,
 				       convert_modes
Index: libcpp/include/line-map.h
===================================================================
--- libcpp/include/line-map.h	(revision 191083)
+++ libcpp/include/line-map.h	(working copy)
@@ -89,7 +89,7 @@ struct GTY(()) line_map_ordinary {
 
 /* This is the highest possible source location encoded within an
    ordinary or macro map.  */
-#define MAX_SOURCE_LOCATION 0xFFFFFFFF
+#define MAX_SOURCE_LOCATION 0x7FFFFFFF
 
 struct cpp_hashnode;
 
@@ -408,6 +408,16 @@ struct GTY(()) line_maps {
 #define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
   LINEMAPS_LAST_ALLOCATED_MAP (SET, true)
 
+extern void location_adhoc_data_init (void);
+extern void location_adhoc_data_fini (void);
+extern source_location get_combined_adhoc_loc (source_location, void *);
+extern void *get_data_from_adhoc_loc (source_location);
+extern source_location get_location_from_adhoc_loc (source_location);
+
+#define COMBINE_LOCATION_DATA(LOC, BLOCK) \
+  ((BLOCK) ? get_combined_adhoc_loc ((LOC), (BLOCK)) : (LOC))
+#define IS_ADHOC_LOC(LOC) (((LOC) & MAX_SOURCE_LOCATION) != (LOC))
+
 /* Initialize a line map set.  */
 extern void linemap_init (struct line_maps *);
 
@@ -594,6 +604,8 @@ typedef struct
 
   int column;
 
+  void *data;
+
   /* In a system header?. */
   bool sysp;
 } expanded_location;
Index: libcpp/line-map.c
===================================================================
--- libcpp/line-map.c	(revision 191083)
+++ libcpp/line-map.c	(working copy)
@@ -25,6 +25,7 @@ along with this program; see the file COPYING3.  I
 #include "line-map.h"
 #include "cpplib.h"
 #include "internal.h"
+#include "hashtab.h"
 
 static void trace_include (const struct line_maps *, const struct line_map *);
 static const struct line_map * linemap_ordinary_map_lookup (struct line_maps *,
@@ -50,6 +51,135 @@ static source_location linemap_macro_loc_to_exp_po
 extern unsigned num_expanded_macros_counter;
 extern unsigned num_macro_tokens_counter;
 
+/* Data structure to associate an arbitrary data to a source location.  */
+struct location_adhoc_data {
+  source_location locus;
+  void *data;
+};
+
+/* The following data structure encodes a location with some adhoc data
+   and maps it to a new unsigned integer (called an adhoc location)
+   that replaces the original location to represent the mapping.
+
+   The new adhoc_loc uses the highest bit as the enabling bit, i.e. if the
+   highest bit is 1, then the number is adhoc_loc. Otherwise, it serves as
+   the original location. Once identified as the adhoc_loc, the lower 31
+   bits of the integer is used to index the location_adhoc_data array,
+   in which the locus and associated data is stored.  */
+
+static htab_t location_adhoc_data_htab;
+static source_location curr_adhoc_loc;
+static struct location_adhoc_data *location_adhoc_data;
+static unsigned int allocated_location_adhoc_data;
+
+/* Hash function for location_adhoc_data hashtable.  */
+
+static hashval_t
+location_adhoc_data_hash (const void *l)
+{
+  const struct location_adhoc_data *lb =
+      (const struct location_adhoc_data *) l;
+  return (hashval_t) lb->locus + (size_t) &lb->data;
+}
+
+/* Compare function for location_adhoc_data hashtable.  */
+
+static int
+location_adhoc_data_eq (const void *l1, const void *l2)
+{
+  const struct location_adhoc_data *lb1 =
+      (const struct location_adhoc_data *) l1;
+  const struct location_adhoc_data *lb2 =
+      (const struct location_adhoc_data *) l2;
+  return lb1->locus == lb2->locus && lb1->data == lb2->data;
+}
+
+/* Update the hashtable when location_adhoc_data is reallocated.  */
+
+static int
+location_adhoc_data_update (void **slot, void *data)
+{
+  *((char **) slot) += ((char *) location_adhoc_data - (char *) data);
+  return 1;
+}
+
+/* Combine LOCUS and DATA to a combined adhoc loc.  */
+
+source_location
+get_combined_adhoc_loc (source_location locus, void *data)
+{
+  struct location_adhoc_data lb;
+  struct location_adhoc_data **slot;
+
+  linemap_assert (data);
+
+  if (IS_ADHOC_LOC (locus))
+    locus = location_adhoc_data[locus & MAX_SOURCE_LOCATION].locus;
+  if (locus == 0 && data == NULL)
+    return 0;
+  lb.locus = locus;
+  lb.data = data;
+  slot = (struct location_adhoc_data **)
+      htab_find_slot (location_adhoc_data_htab, &lb, INSERT);
+  if (*slot == NULL)
+    {
+      *slot = location_adhoc_data + curr_adhoc_loc;
+      location_adhoc_data[curr_adhoc_loc] = lb;
+      if (++curr_adhoc_loc >= allocated_location_adhoc_data)
+	{
+	  char *orig_location_adhoc_data = (char *) location_adhoc_data;
+	  allocated_location_adhoc_data *= 2;
+	  location_adhoc_data = XRESIZEVEC (struct location_adhoc_data,
+					    location_adhoc_data,
+					    allocated_location_adhoc_data);
+	  htab_traverse (location_adhoc_data_htab, location_adhoc_data_update,
+			 orig_location_adhoc_data);
+	}
+    }
+  return ((*slot) - location_adhoc_data) | 0x80000000;
+}
+
+/* Return the data for the adhoc loc.  */
+
+void *
+get_data_from_adhoc_loc (source_location loc)
+{
+  linemap_assert (IS_ADHOC_LOC (loc));
+  return location_adhoc_data[loc & MAX_SOURCE_LOCATION].data;
+}
+
+/* Return the location for the adhoc loc.  */
+
+source_location
+get_location_from_adhoc_loc (source_location loc)
+{
+  linemap_assert (IS_ADHOC_LOC (loc));
+  return location_adhoc_data[loc & MAX_SOURCE_LOCATION].locus;
+}
+
+/* Initialize the location_adhoc_data structure.  */
+
+void
+location_adhoc_data_init (void)
+{
+  location_adhoc_data_htab = htab_create (100, location_adhoc_data_hash,
+					  location_adhoc_data_eq, NULL);
+  curr_adhoc_loc = 0;
+  allocated_location_adhoc_data = 100;
+  location_adhoc_data = XNEWVEC (struct location_adhoc_data,
+				 allocated_location_adhoc_data);
+}
+
+/* Finalize the location_adhoc_data structure.  */
+
+void
+location_adhoc_data_fini (void)
+{
+  allocated_location_adhoc_data = 0;
+  XDELETEVEC (location_adhoc_data);
+  htab_delete (location_adhoc_data_htab);
+}
+
 /* Initialize a line map set.  */
 
 void
@@ -509,6 +639,8 @@ linemap_position_for_line_and_column (struct line_
 const struct line_map*
 linemap_lookup (struct line_maps *set, source_location line)
 {
+  if (IS_ADHOC_LOC (line))
+    line = location_adhoc_data[line & MAX_SOURCE_LOCATION].locus;
   if (linemap_location_from_macro_expansion_p (set, line))
     return linemap_macro_map_lookup (set, line);
   return linemap_ordinary_map_lookup (set, line);
@@ -525,6 +657,9 @@ linemap_ordinary_map_lookup (struct line_maps *set
   unsigned int md, mn, mx;
   const struct line_map *cached, *result;
 
+  if (IS_ADHOC_LOC (line))
+    line = location_adhoc_data[line & MAX_SOURCE_LOCATION].locus;
+
   if (set ==  NULL || line < RESERVED_LOCATION_COUNT)
     return NULL;
 
@@ -570,6 +705,9 @@ linemap_macro_map_lookup (struct line_maps *set, s
   unsigned int md, mn, mx;
   const struct line_map *cached, *result;
 
+  if (IS_ADHOC_LOC (line))
+    line = location_adhoc_data[line & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
 
   if (set ==  NULL)
@@ -648,6 +786,9 @@ linemap_macro_map_loc_to_def_point (const struct l
 {
   unsigned token_no;
 
+  if (IS_ADHOC_LOC (location))
+    location = location_adhoc_data[location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (linemap_macro_expansion_map_p (map)
 		  && location >= MAP_START_LOCATION (map));
   linemap_assert (location >= RESERVED_LOCATION_COUNT);
@@ -672,6 +813,9 @@ linemap_macro_map_loc_unwind_toward_spelling (cons
 {
   unsigned token_no;
 
+  if (IS_ADHOC_LOC (location))
+    location = location_adhoc_data[location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (linemap_macro_expansion_map_p (map)
 		  && location >= MAP_START_LOCATION (map));
   linemap_assert (location >= RESERVED_LOCATION_COUNT);
@@ -696,6 +840,9 @@ linemap_get_expansion_line (struct line_maps *set,
 {
   const struct line_map *map = NULL;
 
+  if (IS_ADHOC_LOC (location))
+    location = location_adhoc_data[location & MAX_SOURCE_LOCATION].locus;
+
   if (location < RESERVED_LOCATION_COUNT)
     return 0;
 
@@ -720,6 +867,9 @@ linemap_get_expansion_filename (struct line_maps *
 {
   const struct line_map *map = NULL;
 
+  if (IS_ADHOC_LOC (location))
+    location = location_adhoc_data[location & MAX_SOURCE_LOCATION].locus;
+
   if (location < RESERVED_LOCATION_COUNT)
     return NULL;
 
@@ -754,6 +904,9 @@ linemap_location_in_system_header_p (struct line_m
 {
   const struct line_map *map = NULL;
 
+  if (IS_ADHOC_LOC (location))
+    location = location_adhoc_data[location & MAX_SOURCE_LOCATION].locus;
+
   if (location < RESERVED_LOCATION_COUNT)
     return false;
 
@@ -793,6 +946,9 @@ bool
 linemap_location_from_macro_expansion_p (struct line_maps *set,
 					 source_location location)
 {
+  if (IS_ADHOC_LOC (location))
+    location = location_adhoc_data[location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (location <= MAX_SOURCE_LOCATION
 		  && (set->highest_location
 		      < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
@@ -933,6 +1089,9 @@ linemap_macro_loc_to_spelling_point (struct line_m
 {
   struct line_map *map;
 
+  if (IS_ADHOC_LOC (location))
+    location = location_adhoc_data[location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
 
   while (true)
@@ -967,6 +1126,9 @@ linemap_macro_loc_to_def_point (struct line_maps *
 {
   struct line_map *map;
 
+  if (IS_ADHOC_LOC (location))
+    location = location_adhoc_data[location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
 
   while (true)
@@ -1005,6 +1167,9 @@ linemap_macro_loc_to_exp_point (struct line_maps *
 {
   struct line_map *map;
 
+  if (IS_ADHOC_LOC (location))
+    location = location_adhoc_data[location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
 
   while (true)
@@ -1074,6 +1239,9 @@ linemap_resolve_location (struct line_maps *set,
 			  enum location_resolution_kind lrk,
 			  const struct line_map **map)
 {
+  if (IS_ADHOC_LOC (loc))
+    loc = location_adhoc_data[loc & MAX_SOURCE_LOCATION].locus;
+
   if (loc < RESERVED_LOCATION_COUNT)
     {
       /* A reserved location wasn't encoded in a map.  Let's return a
@@ -1121,6 +1289,9 @@ linemap_unwind_toward_expansion (struct line_maps
   source_location resolved_location;
   const struct line_map *resolved_map;
 
+  if (IS_ADHOC_LOC (loc))
+    loc = location_adhoc_data[loc & MAX_SOURCE_LOCATION].locus;
+
   resolved_location =
     linemap_macro_map_loc_unwind_toward_spelling (*map, loc);
   resolved_map = linemap_lookup (set, resolved_location);
@@ -1157,6 +1328,9 @@ linemap_unwind_to_first_non_reserved_loc (struct l
   source_location resolved_loc;
   const struct line_map *map0 = NULL, *map1 = NULL;
 
+  if (IS_ADHOC_LOC (loc))
+    loc = location_adhoc_data[loc & MAX_SOURCE_LOCATION].locus;
+
   map0 = linemap_lookup (set, loc);
   if (!linemap_macro_expansion_map_p (map0))
     return loc;
@@ -1198,6 +1372,11 @@ linemap_expand_location (struct line_maps *set,
   expanded_location xloc;
 
   memset (&xloc, 0, sizeof (xloc));
+  if (IS_ADHOC_LOC (loc))
+    {
+      loc = location_adhoc_data[loc & MAX_SOURCE_LOCATION].locus;
+      xloc.data = location_adhoc_data[loc & MAX_SOURCE_LOCATION].data;
+    }
 
   if (loc < RESERVED_LOCATION_COUNT)
     /* The location for this token wasn't generated from a line map.
@@ -1290,6 +1469,9 @@ linemap_dump_location (struct line_maps *set,
   const char *path = "", *from = "";
   int l = -1, c = -1, s = -1, e = -1;
 
+  if (IS_ADHOC_LOC (loc))
+    loc = location_adhoc_data[loc & MAX_SOURCE_LOCATION].locus;
+
   if (loc == 0)
     return;

Comments

Richard Biener Sept. 10, 2012, 10:01 a.m. UTC | #1
On Sun, Sep 9, 2012 at 12:26 AM, Dehao Chen <dehao@google.com> wrote:
> Hi, Diego,
>
> Thanks a lot for the review. I've updated the patch.
>
> This patch is large and may easily break builds because it reserves
> more complete information for TREE_BLOCK as well as gimple_block (may
> trigger bugs that was hided when these info are unavailable). I've
> done more rigorous testing to ensure that most bugs are caught before
> checking in.
>
> * Sync to the head and retest all gcc testsuite.
> * Port the patch to google-4_7 branch to retest all gcc testsuite, as
> well as build many large applications.
>
> Through these tests, I've found two additional bugs that was omitted
> in the original implementation. A new patch is attached (patch.txt) to
> fix these problems. After this fix, all gcc testsuites pass for both
> trunk and google-4_7 branch. I've also copy pasted the new fixes
> (lto.c and tree-cfg.c) below. Now I'd say this patch is in good shape.
> But it may not be perfect. I'll look into build failures as soon as it
> arises.
>
> Richard and Diego, could you help me take a look at the following two fixes?
>
> Thanks,
> Dehao
>
> New fixes:
> --- gcc/lto/lto.c       (revision 191083)
> +++ gcc/lto/lto.c       (working copy)
> @@ -1559,8 +1559,6 @@ lto_fixup_prevailing_decls (tree t)
>  {
>    enum tree_code code = TREE_CODE (t);
>    LTO_NO_PREVAIL (TREE_TYPE (t));
> -  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
> -    LTO_NO_PREVAIL (TREE_CHAIN (t));

That change is odd.  Can you show us how it breaks?

>    if (DECL_P (t))
>      {
>        LTO_NO_PREVAIL (DECL_NAME (t));
>
> Index: gcc/tree-cfg.c
> ===================================================================
> --- gcc/tree-cfg.c      (revision 191083)
> +++ gcc/tree-cfg.c      (working copy)
> @@ -5980,9 +5974,21 @@ move_stmt_op (tree *tp, int *walk_subtrees, void *
>    tree t = *tp;
>
>    if (EXPR_P (t))
> -    /* We should never have TREE_BLOCK set on non-statements.  */
> -    gcc_assert (!TREE_BLOCK (t));
> -
> +    {
> +      tree block = TREE_BLOCK (t);
> +      if (p->orig_block == NULL_TREE
> +         || block == p->orig_block
> +         || block == NULL_TREE)
> +       TREE_SET_BLOCK (t, p->new_block);
> +#ifdef ENABLE_CHECKING
> +      else if (block != p->new_block)
> +       {
> +         while (block && block != p->orig_block)
> +           block = BLOCK_SUPERCONTEXT (block);
> +         gcc_assert (block);
> +       }
> +#endif

I think what this means is that TREE_BLOCK on non-stmts are meaningless
(thus only gimple_block is interesting on GIMPLE, not BLOCKs on trees).

So instead of setting a BLOCK in some cases you should clear BLOCK
if it happens to be set, or alternatively, only re-set it if there was
a block associated
with it.

Richard.

> +    }
>    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
>      {
>        if (TREE_CODE (t) == SSA_NAME)
>
> Whole patch:
> gcc/ChangeLog:
> 2012-09-08  Dehao Chen  <dehao@google.com>
>
>         * toplev.c (general_init): Init block_locations.
>         * tree.c (tree_set_block): New.
>         (tree_block): Change to use LOCATION_BLOCK.
>         * tree.h (TREE_SET_BLOCK): New.
>         * final.c (reemit_insn_block_notes): Change to use LOCATION_BLOCK.
>         (final_start_function): Likewise.
>         * input.c (expand_location_1): Likewise.
>         * input.h (LOCATION_LOCUS): New.
>         (LOCATION_BLOCK): New.
>         (IS_UNKNOWN_LOCATION): New.
>         * fold-const.c (expr_location_or): Change to use new location.
>         * reorg.c (emit_delay_sequence): Likewise.
>         (try_merge_delay_insns): Likewise.
>         * modulo-sched.c (dump_insn_location): Likewise.
>         * lto-streamer-out.c (lto_output_location_bitpack): Likewise.
>         * jump.c (rtx_renumbered_equal_p): Likewise.
>         * ifcvt.c (noce_try_move): Likewise.
>         (noce_try_store_flag): Likewise.
>         (noce_try_store_flag_constants): Likewise.
>         (noce_try_addcc): Likewise.
>         (noce_try_store_flag_mask): Likewise.
>         (noce_try_cmove): Likewise.
>         (noce_try_cmove_arith): Likewise.
>         (noce_try_minmax): Likewise.
>         (noce_try_abs): Likewise.
>         (noce_try_sign_mask): Likewise.
>         (noce_try_bitop): Likewise.
>         (noce_process_if_block): Likewise.
>         (cond_move_process_if_block): Likewise.
>         (find_cond_trap): Likewise.
>         * dwarf2out.c (add_src_coords_attributes): Likewise.
>         * expr.c (expand_expr_real): Likewise.
>         * tree-parloops.c (create_loop_fn): Likewise.
>         * recog.c (peep2_attempt): Likewise.
>         * function.c (free_after_compilation): Likewise.
>         (expand_function_end): Likewise.
>         (set_insn_locations): Likewise.
>         (thread_prologue_and_epilogue_insns): Likewise.
>         * print-rtl.c (print_rtx): Likewise.
>         * profile.c (branch_prob): Likewise.
>         * trans-mem.c (ipa_tm_scan_irr_block): Likewise.
>         * gimplify.c (gimplify_call_expr): Likewise.
>         * except.c (duplicate_eh_regions_1): Likewise.
>         * emit-rtl.c (try_split): Likewise.
>         (make_insn_raw): Likewise.
>         (make_debug_insn_raw): Likewise.
>         (make_jump_insn_raw): Likewise.
>         (make_call_insn_raw): Likewise.
>         (emit_pattern_after_setloc): Likewise.
>         (emit_pattern_after): Likewise.
>         (emit_debug_insn_after): Likewise.
>         (emit_pattern_before): Likewise.
>         (emit_insn_before_setloc): Likewise.
>         (emit_jump_insn_before): Likewise.
>         (emit_call_insn_before_setloc): Likewise.
>         (emit_call_insn_before): Likeise.
>         (emit_debug_insn_before_setloc): Likewise.
>         (emit_copy_of_insn_after): Likewise.
>         (insn_locators_alloc): Remove.
>         (insn_locators_finalize): Remove.
>         (insn_locators_free): Remove.
>         (set_curr_insn_source_location): Remove.
>         (get_curr_insn_source_location): Remove.
>         (set_curr_insn_block): Remove.
>         (get_curr_insn_block): Remove.
>         (locator_scope): Remove.
>         (insn_scope): Change to use new location.
>         (locator_location): Remove.
>         (insn_line): Change to use new location.
>         (locator_file): Remove.
>         (insn_file): Change to use new location.
>         (locator_eq): Remove.
>         (insn_locations_init): New.
>         (insn_locations_finalize): New.
>         (set_curr_insn_location): New.
>         (curr_insn_location): New.
>         * cfgexpand.c (gimple_assign_rhs_to_tree): Change to use new location.
>         (expand_gimple_cond): Likewise.
>         (expand_call_stmt): Likewise.
>         (expand_gimple_stmt_1): Likewise.
>         (expand_gimple_basic_block): Likewise.
>         (construct_exit_block): Likewise.
>         (gimple_expand_cfg): Likewise.
>         * cfgcleanup.c (try_forward_edges): Likewise.
>         * tree-ssa-live.c (remove_unused_scope_block_p): Likewise.
>         (dump_scope_block): Likewise.
>         (remove_unused_locals): Likewise.
>         * rtl.c (rtx_equal_p_cb): Likewise.
>         (rtx_equal_p): Likewise.
>         * rtl.h (XUINT): New.
>         (INSN_LOCATOR): Remove.
>         (CURR_INSN_LOCATION): Remove.
>         (INSN_LOCATION): New.
>         (INSN_HAS_LOCATION): New.
>         * tree-inline.c (remap_gimple_op_r): Change to use new location.
>         (copy_tree_body_r): Likewise.
>         (copy_phis_for_bb): Likewise.
>         (expand_call_inline): Likewise.
>         * tree-streamer-in.c (lto_input_ts_exp_tree_pointers): Likewise.
>         * tree-streamer-out.c (write_ts_decl_minimal_tree_pointers): Likewise.
>         * gimple-streamer-out.c (output_gimple_stmt): Likewise.
>         * combine.c (try_combine): Likewise.
>         * tree-outof-ssa.c (set_location_for_edge): Likewise.
>         (insert_partition_copy_on_edge): Likewise.
>         (insert_value_copy_on_edge): Likewise.
>         (insert_rtx_to_part_on_edge): Likewise.
>         (insert_part_to_rtx_on_edge): Likewise.
>         * basic-block.h (edge_def): Remove field.
>         * gimple.h (gimple_statement_base): Remove field.
>         (gimple_bb): Change to use new location.
>         (gimple_set_block): Likewise.
>         (gimple_has_location): Likewise.
>         * tree-cfg.c (make_cond_expr_edges): Likewise.
>         (make_goto_expr_edges): Likewise.
>         (gimple_can_merge_blocks_p): Likewise.
>         (move_stmt_op): Likewise.
>         (move_block_to_fn): Likewise.
>         * config/alpha/alpha.c (alpha_output_mi_thunk_osf): Likewise.
>         * config/sparc/sparc.c (sparc_output_mi_thunk): Likewise.
>         * config/i386/i386.c (x86_output_mi_thunk): Likewise.
>         * config/tilegx/tilegx.c (tilegx_output_mi_thunk): Likewise.
>         * config/sh/sh.c (sh_output_mi_thunk): Likewise.
>         * config/ia64/ia64.c (ia64_output_mi_thunk): Likewise.
>         * config/rs6000/rs6000.c (rs6000_output_mi_thunk): Likewise.
>         * config/score/score.c (score_output_mi_thunk): Likewise.
>         * config/tilepro/tilepro.c (tilepro_asm_output_mi_thunk): Likewise.
>         * config/mips/mips.c (mips_output_mi_thunk): Likewise.
>         * cfgrtl.c (unique_locus_on_edge_between_p): Likewise.
>         (unique_locus_on_edge_between_p): Likewise.
>         (emit_nop_for_unique_locus_between): Likewise.
>         (force_nonfallthru_and_redirect): Likewise.
>         (fixup_reorder_chain): Likewise.
>         (cfg_layout_merge_blocks): Likewise.
>         * stmt.c (emit_case_nodes): Likewise.
>
> gcc/lto/ChangeLog:
> 2012-09-08  Dehao Chen  <dehao@google.com>
>
>         * lto/lto.c (lto_fixup_prevailing_decls): Remove tree.exp.block field.
>
> libcpp/ChangeLog:
> 2012-09-08  Dehao Chen  <dehao@google.com>
>
>         * include/line-map.h (MAX_SOURCE_LOCATION): New value.
>         (location_adhoc_data_init): New.
>         (location_adhoc_data_fini): New.
>         (get_combined_adhoc_loc): New.
>         (get_data_from_adhoc_loc): New.
>         (get_location_from_adhoc_loc): New.
>         (COMBINE_LOCATION_DATA): New.
>         (IS_ADHOC_LOC): New.
>         (expanded_location): New field.
>         * line-map.c (location_adhoc_data): New.
>         (location_adhoc_data_htab): New.
>         (curr_adhoc_loc): New.
>         (location_adhoc_data): New.
>         (allocated_location_adhoc_data): New.
>         (location_adhoc_data_hash): New.
>         (location_adhoc_data_eq): New.
>         (location_adhoc_data_update): New.
>         (get_combined_adhoc_loc): New.
>         (get_data_from_adhoc_loc): New.
>         (get_location_from_adhoc_loc): New.
>         (location_adhoc_data_init): New.
>         (location_adhoc_data_fini): New.
>         (linemap_lookup): Change to use new location.
>         (linemap_ordinary_map_lookup): Likewise.
>         (linemap_macro_map_lookup): Likewise.
>         (linemap_macro_map_loc_to_def_point): Likewise.
>         (linemap_macro_map_loc_unwind_toward_spel): Likewise.
>         (linemap_get_expansion_line): Likewise.
>         (linemap_get_expansion_filename): Likewise.
>         (linemap_location_in_system_header_p): Likewise.
>         (linemap_location_from_macro_expansion_p): Likewise.
>         (linemap_macro_loc_to_spelling_point): Likewise.
>         (linemap_macro_loc_to_def_point): Likewise.
>         (linemap_macro_loc_to_exp_point): Likewise.
>         (linemap_resolve_location): Likewise.
>         (linemap_unwind_toward_expansion): Likewise.
>         (linemap_unwind_to_first_non_reserved_loc): Likewise.
>         (linemap_expand_location): Likewise.
>         (linemap_dump_location): Likewise.
Dehao Chen Sept. 10, 2012, 3:27 p.m. UTC | #2
On Mon, Sep 10, 2012 at 3:01 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Sun, Sep 9, 2012 at 12:26 AM, Dehao Chen <dehao@google.com> wrote:
>> Hi, Diego,
>>
>> Thanks a lot for the review. I've updated the patch.
>>
>> This patch is large and may easily break builds because it reserves
>> more complete information for TREE_BLOCK as well as gimple_block (may
>> trigger bugs that was hided when these info are unavailable). I've
>> done more rigorous testing to ensure that most bugs are caught before
>> checking in.
>>
>> * Sync to the head and retest all gcc testsuite.
>> * Port the patch to google-4_7 branch to retest all gcc testsuite, as
>> well as build many large applications.
>>
>> Through these tests, I've found two additional bugs that was omitted
>> in the original implementation. A new patch is attached (patch.txt) to
>> fix these problems. After this fix, all gcc testsuites pass for both
>> trunk and google-4_7 branch. I've also copy pasted the new fixes
>> (lto.c and tree-cfg.c) below. Now I'd say this patch is in good shape.
>> But it may not be perfect. I'll look into build failures as soon as it
>> arises.
>>
>> Richard and Diego, could you help me take a look at the following two fixes?
>>
>> Thanks,
>> Dehao
>>
>> New fixes:
>> --- gcc/lto/lto.c       (revision 191083)
>> +++ gcc/lto/lto.c       (working copy)
>> @@ -1559,8 +1559,6 @@ lto_fixup_prevailing_decls (tree t)
>>  {
>>    enum tree_code code = TREE_CODE (t);
>>    LTO_NO_PREVAIL (TREE_TYPE (t));
>> -  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
>> -    LTO_NO_PREVAIL (TREE_CHAIN (t));
>
> That change is odd.  Can you show us how it breaks?

This will break LTO build of gcc.c-torture/execute/pr38051.c

There is data structure like:

  union { long int l; char c[sizeof (long int)]; } u;

Once the block info is reserved for this, it'll reserve this data
structure. And inside this data structure, there is VAR_DECL. Thus
LTO_NO_PREVAIL assertion does not satisfy here for TREE_CHAIN (t).

>
>>    if (DECL_P (t))
>>      {
>>        LTO_NO_PREVAIL (DECL_NAME (t));
>>
>> Index: gcc/tree-cfg.c
>> ===================================================================
>> --- gcc/tree-cfg.c      (revision 191083)
>> +++ gcc/tree-cfg.c      (working copy)
>> @@ -5980,9 +5974,21 @@ move_stmt_op (tree *tp, int *walk_subtrees, void *
>>    tree t = *tp;
>>
>>    if (EXPR_P (t))
>> -    /* We should never have TREE_BLOCK set on non-statements.  */
>> -    gcc_assert (!TREE_BLOCK (t));
>> -
>> +    {
>> +      tree block = TREE_BLOCK (t);
>> +      if (p->orig_block == NULL_TREE
>> +         || block == p->orig_block
>> +         || block == NULL_TREE)
>> +       TREE_SET_BLOCK (t, p->new_block);
>> +#ifdef ENABLE_CHECKING
>> +      else if (block != p->new_block)
>> +       {
>> +         while (block && block != p->orig_block)
>> +           block = BLOCK_SUPERCONTEXT (block);
>> +         gcc_assert (block);
>> +       }
>> +#endif
>
> I think what this means is that TREE_BLOCK on non-stmts are meaningless
> (thus only gimple_block is interesting on GIMPLE, not BLOCKs on trees).
>
> So instead of setting a BLOCK in some cases you should clear BLOCK
> if it happens to be set, or alternatively, only re-set it if there was
> a block associated
> with it.

Yeah, makes sense. New change:

@@ -5980,9 +5974,10 @@
   tree t = *tp;

   if (EXPR_P (t))
-    /* We should never have TREE_BLOCK set on non-statements.  */
-    gcc_assert (!TREE_BLOCK (t));
-
+    {
+      if (TREE_BLOCK (t))
+	TREE_SET_BLOCK (t, p->new_block);
+    }
   else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
     {
       if (TREE_CODE (t) == SSA_NAME)

Thanks,
Dehao

>
> Richard.
>
>> +    }
>>    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
>>      {
>>        if (TREE_CODE (t) == SSA_NAME)
>>
>> Whole patch:
>> gcc/ChangeLog:
>> 2012-09-08  Dehao Chen  <dehao@google.com>
>>
>>         * toplev.c (general_init): Init block_locations.
>>         * tree.c (tree_set_block): New.
>>         (tree_block): Change to use LOCATION_BLOCK.
>>         * tree.h (TREE_SET_BLOCK): New.
>>         * final.c (reemit_insn_block_notes): Change to use LOCATION_BLOCK.
>>         (final_start_function): Likewise.
>>         * input.c (expand_location_1): Likewise.
>>         * input.h (LOCATION_LOCUS): New.
>>         (LOCATION_BLOCK): New.
>>         (IS_UNKNOWN_LOCATION): New.
>>         * fold-const.c (expr_location_or): Change to use new location.
>>         * reorg.c (emit_delay_sequence): Likewise.
>>         (try_merge_delay_insns): Likewise.
>>         * modulo-sched.c (dump_insn_location): Likewise.
>>         * lto-streamer-out.c (lto_output_location_bitpack): Likewise.
>>         * jump.c (rtx_renumbered_equal_p): Likewise.
>>         * ifcvt.c (noce_try_move): Likewise.
>>         (noce_try_store_flag): Likewise.
>>         (noce_try_store_flag_constants): Likewise.
>>         (noce_try_addcc): Likewise.
>>         (noce_try_store_flag_mask): Likewise.
>>         (noce_try_cmove): Likewise.
>>         (noce_try_cmove_arith): Likewise.
>>         (noce_try_minmax): Likewise.
>>         (noce_try_abs): Likewise.
>>         (noce_try_sign_mask): Likewise.
>>         (noce_try_bitop): Likewise.
>>         (noce_process_if_block): Likewise.
>>         (cond_move_process_if_block): Likewise.
>>         (find_cond_trap): Likewise.
>>         * dwarf2out.c (add_src_coords_attributes): Likewise.
>>         * expr.c (expand_expr_real): Likewise.
>>         * tree-parloops.c (create_loop_fn): Likewise.
>>         * recog.c (peep2_attempt): Likewise.
>>         * function.c (free_after_compilation): Likewise.
>>         (expand_function_end): Likewise.
>>         (set_insn_locations): Likewise.
>>         (thread_prologue_and_epilogue_insns): Likewise.
>>         * print-rtl.c (print_rtx): Likewise.
>>         * profile.c (branch_prob): Likewise.
>>         * trans-mem.c (ipa_tm_scan_irr_block): Likewise.
>>         * gimplify.c (gimplify_call_expr): Likewise.
>>         * except.c (duplicate_eh_regions_1): Likewise.
>>         * emit-rtl.c (try_split): Likewise.
>>         (make_insn_raw): Likewise.
>>         (make_debug_insn_raw): Likewise.
>>         (make_jump_insn_raw): Likewise.
>>         (make_call_insn_raw): Likewise.
>>         (emit_pattern_after_setloc): Likewise.
>>         (emit_pattern_after): Likewise.
>>         (emit_debug_insn_after): Likewise.
>>         (emit_pattern_before): Likewise.
>>         (emit_insn_before_setloc): Likewise.
>>         (emit_jump_insn_before): Likewise.
>>         (emit_call_insn_before_setloc): Likewise.
>>         (emit_call_insn_before): Likeise.
>>         (emit_debug_insn_before_setloc): Likewise.
>>         (emit_copy_of_insn_after): Likewise.
>>         (insn_locators_alloc): Remove.
>>         (insn_locators_finalize): Remove.
>>         (insn_locators_free): Remove.
>>         (set_curr_insn_source_location): Remove.
>>         (get_curr_insn_source_location): Remove.
>>         (set_curr_insn_block): Remove.
>>         (get_curr_insn_block): Remove.
>>         (locator_scope): Remove.
>>         (insn_scope): Change to use new location.
>>         (locator_location): Remove.
>>         (insn_line): Change to use new location.
>>         (locator_file): Remove.
>>         (insn_file): Change to use new location.
>>         (locator_eq): Remove.
>>         (insn_locations_init): New.
>>         (insn_locations_finalize): New.
>>         (set_curr_insn_location): New.
>>         (curr_insn_location): New.
>>         * cfgexpand.c (gimple_assign_rhs_to_tree): Change to use new location.
>>         (expand_gimple_cond): Likewise.
>>         (expand_call_stmt): Likewise.
>>         (expand_gimple_stmt_1): Likewise.
>>         (expand_gimple_basic_block): Likewise.
>>         (construct_exit_block): Likewise.
>>         (gimple_expand_cfg): Likewise.
>>         * cfgcleanup.c (try_forward_edges): Likewise.
>>         * tree-ssa-live.c (remove_unused_scope_block_p): Likewise.
>>         (dump_scope_block): Likewise.
>>         (remove_unused_locals): Likewise.
>>         * rtl.c (rtx_equal_p_cb): Likewise.
>>         (rtx_equal_p): Likewise.
>>         * rtl.h (XUINT): New.
>>         (INSN_LOCATOR): Remove.
>>         (CURR_INSN_LOCATION): Remove.
>>         (INSN_LOCATION): New.
>>         (INSN_HAS_LOCATION): New.
>>         * tree-inline.c (remap_gimple_op_r): Change to use new location.
>>         (copy_tree_body_r): Likewise.
>>         (copy_phis_for_bb): Likewise.
>>         (expand_call_inline): Likewise.
>>         * tree-streamer-in.c (lto_input_ts_exp_tree_pointers): Likewise.
>>         * tree-streamer-out.c (write_ts_decl_minimal_tree_pointers): Likewise.
>>         * gimple-streamer-out.c (output_gimple_stmt): Likewise.
>>         * combine.c (try_combine): Likewise.
>>         * tree-outof-ssa.c (set_location_for_edge): Likewise.
>>         (insert_partition_copy_on_edge): Likewise.
>>         (insert_value_copy_on_edge): Likewise.
>>         (insert_rtx_to_part_on_edge): Likewise.
>>         (insert_part_to_rtx_on_edge): Likewise.
>>         * basic-block.h (edge_def): Remove field.
>>         * gimple.h (gimple_statement_base): Remove field.
>>         (gimple_bb): Change to use new location.
>>         (gimple_set_block): Likewise.
>>         (gimple_has_location): Likewise.
>>         * tree-cfg.c (make_cond_expr_edges): Likewise.
>>         (make_goto_expr_edges): Likewise.
>>         (gimple_can_merge_blocks_p): Likewise.
>>         (move_stmt_op): Likewise.
>>         (move_block_to_fn): Likewise.
>>         * config/alpha/alpha.c (alpha_output_mi_thunk_osf): Likewise.
>>         * config/sparc/sparc.c (sparc_output_mi_thunk): Likewise.
>>         * config/i386/i386.c (x86_output_mi_thunk): Likewise.
>>         * config/tilegx/tilegx.c (tilegx_output_mi_thunk): Likewise.
>>         * config/sh/sh.c (sh_output_mi_thunk): Likewise.
>>         * config/ia64/ia64.c (ia64_output_mi_thunk): Likewise.
>>         * config/rs6000/rs6000.c (rs6000_output_mi_thunk): Likewise.
>>         * config/score/score.c (score_output_mi_thunk): Likewise.
>>         * config/tilepro/tilepro.c (tilepro_asm_output_mi_thunk): Likewise.
>>         * config/mips/mips.c (mips_output_mi_thunk): Likewise.
>>         * cfgrtl.c (unique_locus_on_edge_between_p): Likewise.
>>         (unique_locus_on_edge_between_p): Likewise.
>>         (emit_nop_for_unique_locus_between): Likewise.
>>         (force_nonfallthru_and_redirect): Likewise.
>>         (fixup_reorder_chain): Likewise.
>>         (cfg_layout_merge_blocks): Likewise.
>>         * stmt.c (emit_case_nodes): Likewise.
>>
>> gcc/lto/ChangeLog:
>> 2012-09-08  Dehao Chen  <dehao@google.com>
>>
>>         * lto/lto.c (lto_fixup_prevailing_decls): Remove tree.exp.block field.
>>
>> libcpp/ChangeLog:
>> 2012-09-08  Dehao Chen  <dehao@google.com>
>>
>>         * include/line-map.h (MAX_SOURCE_LOCATION): New value.
>>         (location_adhoc_data_init): New.
>>         (location_adhoc_data_fini): New.
>>         (get_combined_adhoc_loc): New.
>>         (get_data_from_adhoc_loc): New.
>>         (get_location_from_adhoc_loc): New.
>>         (COMBINE_LOCATION_DATA): New.
>>         (IS_ADHOC_LOC): New.
>>         (expanded_location): New field.
>>         * line-map.c (location_adhoc_data): New.
>>         (location_adhoc_data_htab): New.
>>         (curr_adhoc_loc): New.
>>         (location_adhoc_data): New.
>>         (allocated_location_adhoc_data): New.
>>         (location_adhoc_data_hash): New.
>>         (location_adhoc_data_eq): New.
>>         (location_adhoc_data_update): New.
>>         (get_combined_adhoc_loc): New.
>>         (get_data_from_adhoc_loc): New.
>>         (get_location_from_adhoc_loc): New.
>>         (location_adhoc_data_init): New.
>>         (location_adhoc_data_fini): New.
>>         (linemap_lookup): Change to use new location.
>>         (linemap_ordinary_map_lookup): Likewise.
>>         (linemap_macro_map_lookup): Likewise.
>>         (linemap_macro_map_loc_to_def_point): Likewise.
>>         (linemap_macro_map_loc_unwind_toward_spel): Likewise.
>>         (linemap_get_expansion_line): Likewise.
>>         (linemap_get_expansion_filename): Likewise.
>>         (linemap_location_in_system_header_p): Likewise.
>>         (linemap_location_from_macro_expansion_p): Likewise.
>>         (linemap_macro_loc_to_spelling_point): Likewise.
>>         (linemap_macro_loc_to_def_point): Likewise.
>>         (linemap_macro_loc_to_exp_point): Likewise.
>>         (linemap_resolve_location): Likewise.
>>         (linemap_unwind_toward_expansion): Likewise.
>>         (linemap_unwind_to_first_non_reserved_loc): Likewise.
>>         (linemap_expand_location): Likewise.
>>         (linemap_dump_location): Likewise.
Jan Hubicka Sept. 10, 2012, 4:41 p.m. UTC | #3
Hi,
I was curious how the patch behaves memory wise on compilling Mozilla.  It actually crashes on:
(gdb) bt
#0  0x00007fab8cd70945 in raise () from /lib64/libc.so.6
#1  0x00007fab8cd71f21 in abort () from /lib64/libc.so.6
#2  0x0000000000b52330 in linemap_location_from_macro_expansion_p (set=0x7805, location=30725) at ../../libcpp/line-map.c:952
#3  0x0000000000b526fc in linemap_lookup (set=0x7fab8dc34000, line=0) at ../../libcpp/line-map.c:644
#4  0x0000000000776745 in maybe_unwind_expanded_macro_loc (where=0, diagnostic=<optimized out>, context=<optimized out>) at ../../gcc/tree-diagnostic.c:113
#5  virt_loc_aware_diagnostic_finalizer (context=0x11b8a80, diagnostic=0x7fff4d8adf90) at ../../gcc/tree-diagnostic.c:282
#6  0x0000000000b4aa80 in diagnostic_report_diagnostic (context=0x11b8a80, diagnostic=0x7fff4d8adf90) at ../../gcc/diagnostic.c:652
#7  0x0000000000b4acd6 in internal_error (gmsgid=<optimized out>) at ../../gcc/diagnostic.c:957
#8  0x00000000007555c0 in crash_signal (signo=11) at ../../gcc/toplev.c:335
#9  <signal handler called>
#10 0x0000000000b526e8 in linemap_lookup (set=0x7fab8dc34000, line=4294967295) at ../../libcpp/line-map.c:643
#11 0x0000000000b530fa in linemap_location_in_system_header_p (set=0x7fab8dc34000, location=4294967295) at ../../libcpp/line-map.c:916
#12 0x0000000000b4a8b2 in diagnostic_report_diagnostic (context=0x11b8a80, diagnostic=0x7fff4d8ae620) at ../../gcc/diagnostic.c:513
#13 0x0000000000b4b462 in warning_at (location=<optimized out>, opt=0, gmsgid=<optimized out>) at ../../gcc/diagnostic.c:805
#14 0x0000000000699679 in lto_symtab_merge_decls_2 (diagnosed_p=<optimized out>, slot=<optimized out>) at ../../gcc/lto-symtab.c:574
#15 lto_symtab_merge_decls_1 (slot=<optimized out>, data=<optimized out>) at ../../gcc/lto-symtab.c:691
#16 0x0000000000bd32e8 in htab_traverse_noresize (htab=<optimized out>, callback=0x698ed0 <lto_symtab_merge_decls_1(void**, void*)>, info=0x0) at ../../libiberty/hashtab.c:784
#17 0x00000000004e2630 in read_cgraph_and_symbols (nfiles=2849, fnames=<optimized out>) at ../../gcc/lto/lto.c:1824
#18 0x00000000004e2b75 in lto_main () at ../../gcc/lto/lto.c:2107

It seems that warning_at is not really able to lookup the position.

Honza
Dehao Chen Sept. 10, 2012, 5:32 p.m. UTC | #4
Thanks for helping test this. I'll try to build mozzila to check the
memory consumption as well as find new bugs.

Dehao

On Tue, Sep 11, 2012 at 12:41 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> I was curious how the patch behaves memory wise on compilling Mozilla.  It actually crashes on:
> (gdb) bt
> #0  0x00007fab8cd70945 in raise () from /lib64/libc.so.6
> #1  0x00007fab8cd71f21 in abort () from /lib64/libc.so.6
> #2  0x0000000000b52330 in linemap_location_from_macro_expansion_p (set=0x7805, location=30725) at ../../libcpp/line-map.c:952
> #3  0x0000000000b526fc in linemap_lookup (set=0x7fab8dc34000, line=0) at ../../libcpp/line-map.c:644
> #4  0x0000000000776745 in maybe_unwind_expanded_macro_loc (where=0, diagnostic=<optimized out>, context=<optimized out>) at ../../gcc/tree-diagnostic.c:113
> #5  virt_loc_aware_diagnostic_finalizer (context=0x11b8a80, diagnostic=0x7fff4d8adf90) at ../../gcc/tree-diagnostic.c:282
> #6  0x0000000000b4aa80 in diagnostic_report_diagnostic (context=0x11b8a80, diagnostic=0x7fff4d8adf90) at ../../gcc/diagnostic.c:652
> #7  0x0000000000b4acd6 in internal_error (gmsgid=<optimized out>) at ../../gcc/diagnostic.c:957
> #8  0x00000000007555c0 in crash_signal (signo=11) at ../../gcc/toplev.c:335
> #9  <signal handler called>
> #10 0x0000000000b526e8 in linemap_lookup (set=0x7fab8dc34000, line=4294967295) at ../../libcpp/line-map.c:643
> #11 0x0000000000b530fa in linemap_location_in_system_header_p (set=0x7fab8dc34000, location=4294967295) at ../../libcpp/line-map.c:916
> #12 0x0000000000b4a8b2 in diagnostic_report_diagnostic (context=0x11b8a80, diagnostic=0x7fff4d8ae620) at ../../gcc/diagnostic.c:513
> #13 0x0000000000b4b462 in warning_at (location=<optimized out>, opt=0, gmsgid=<optimized out>) at ../../gcc/diagnostic.c:805
> #14 0x0000000000699679 in lto_symtab_merge_decls_2 (diagnosed_p=<optimized out>, slot=<optimized out>) at ../../gcc/lto-symtab.c:574
> #15 lto_symtab_merge_decls_1 (slot=<optimized out>, data=<optimized out>) at ../../gcc/lto-symtab.c:691
> #16 0x0000000000bd32e8 in htab_traverse_noresize (htab=<optimized out>, callback=0x698ed0 <lto_symtab_merge_decls_1(void**, void*)>, info=0x0) at ../../libiberty/hashtab.c:784
> #17 0x00000000004e2630 in read_cgraph_and_symbols (nfiles=2849, fnames=<optimized out>) at ../../gcc/lto/lto.c:1824
> #18 0x00000000004e2b75 in lto_main () at ../../gcc/lto/lto.c:2107
>
> It seems that warning_at is not really able to lookup the position.
>
> Honza
Richard Biener Sept. 11, 2012, 8:50 a.m. UTC | #5
On Mon, Sep 10, 2012 at 5:27 PM, Dehao Chen <dehao@google.com> wrote:
> On Mon, Sep 10, 2012 at 3:01 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Sun, Sep 9, 2012 at 12:26 AM, Dehao Chen <dehao@google.com> wrote:
>>> Hi, Diego,
>>>
>>> Thanks a lot for the review. I've updated the patch.
>>>
>>> This patch is large and may easily break builds because it reserves
>>> more complete information for TREE_BLOCK as well as gimple_block (may
>>> trigger bugs that was hided when these info are unavailable). I've
>>> done more rigorous testing to ensure that most bugs are caught before
>>> checking in.
>>>
>>> * Sync to the head and retest all gcc testsuite.
>>> * Port the patch to google-4_7 branch to retest all gcc testsuite, as
>>> well as build many large applications.
>>>
>>> Through these tests, I've found two additional bugs that was omitted
>>> in the original implementation. A new patch is attached (patch.txt) to
>>> fix these problems. After this fix, all gcc testsuites pass for both
>>> trunk and google-4_7 branch. I've also copy pasted the new fixes
>>> (lto.c and tree-cfg.c) below. Now I'd say this patch is in good shape.
>>> But it may not be perfect. I'll look into build failures as soon as it
>>> arises.
>>>
>>> Richard and Diego, could you help me take a look at the following two fixes?
>>>
>>> Thanks,
>>> Dehao
>>>
>>> New fixes:
>>> --- gcc/lto/lto.c       (revision 191083)
>>> +++ gcc/lto/lto.c       (working copy)
>>> @@ -1559,8 +1559,6 @@ lto_fixup_prevailing_decls (tree t)
>>>  {
>>>    enum tree_code code = TREE_CODE (t);
>>>    LTO_NO_PREVAIL (TREE_TYPE (t));
>>> -  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
>>> -    LTO_NO_PREVAIL (TREE_CHAIN (t));
>>
>> That change is odd.  Can you show us how it breaks?
>
> This will break LTO build of gcc.c-torture/execute/pr38051.c
>
> There is data structure like:
>
>   union { long int l; char c[sizeof (long int)]; } u;
>
> Once the block info is reserved for this, it'll reserve this data
> structure. And inside this data structure, there is VAR_DECL. Thus
> LTO_NO_PREVAIL assertion does not satisfy here for TREE_CHAIN (t).

I see - the issue here is that this data structure is not reached at the time
we call free_lang_data (via find_decls_types_r).  But maybe I do not understand
"once the block info is reserved for this".

So the patch papers over an issue elsewhere I believe.  Maybe Micha can
add some clarification here though, how BLOCK_VARS should be visible
here

Richard.

>>
>>>    if (DECL_P (t))
>>>      {
>>>        LTO_NO_PREVAIL (DECL_NAME (t));
>>>
>>> Index: gcc/tree-cfg.c
>>> ===================================================================
>>> --- gcc/tree-cfg.c      (revision 191083)
>>> +++ gcc/tree-cfg.c      (working copy)
>>> @@ -5980,9 +5974,21 @@ move_stmt_op (tree *tp, int *walk_subtrees, void *
>>>    tree t = *tp;
>>>
>>>    if (EXPR_P (t))
>>> -    /* We should never have TREE_BLOCK set on non-statements.  */
>>> -    gcc_assert (!TREE_BLOCK (t));
>>> -
>>> +    {
>>> +      tree block = TREE_BLOCK (t);
>>> +      if (p->orig_block == NULL_TREE
>>> +         || block == p->orig_block
>>> +         || block == NULL_TREE)
>>> +       TREE_SET_BLOCK (t, p->new_block);
>>> +#ifdef ENABLE_CHECKING
>>> +      else if (block != p->new_block)
>>> +       {
>>> +         while (block && block != p->orig_block)
>>> +           block = BLOCK_SUPERCONTEXT (block);
>>> +         gcc_assert (block);
>>> +       }
>>> +#endif
>>
>> I think what this means is that TREE_BLOCK on non-stmts are meaningless
>> (thus only gimple_block is interesting on GIMPLE, not BLOCKs on trees).
>>
>> So instead of setting a BLOCK in some cases you should clear BLOCK
>> if it happens to be set, or alternatively, only re-set it if there was
>> a block associated
>> with it.
>
> Yeah, makes sense. New change:
>
> @@ -5980,9 +5974,10 @@
>    tree t = *tp;
>
>    if (EXPR_P (t))
> -    /* We should never have TREE_BLOCK set on non-statements.  */
> -    gcc_assert (!TREE_BLOCK (t));
> -
> +    {
> +      if (TREE_BLOCK (t))
> +       TREE_SET_BLOCK (t, p->new_block);
> +    }
>    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
>      {
>        if (TREE_CODE (t) == SSA_NAME)
>
> Thanks,
> Dehao
>
>>
>> Richard.
>>
>>> +    }
>>>    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
>>>      {
>>>        if (TREE_CODE (t) == SSA_NAME)
>>>
>>> Whole patch:
>>> gcc/ChangeLog:
>>> 2012-09-08  Dehao Chen  <dehao@google.com>
>>>
>>>         * toplev.c (general_init): Init block_locations.
>>>         * tree.c (tree_set_block): New.
>>>         (tree_block): Change to use LOCATION_BLOCK.
>>>         * tree.h (TREE_SET_BLOCK): New.
>>>         * final.c (reemit_insn_block_notes): Change to use LOCATION_BLOCK.
>>>         (final_start_function): Likewise.
>>>         * input.c (expand_location_1): Likewise.
>>>         * input.h (LOCATION_LOCUS): New.
>>>         (LOCATION_BLOCK): New.
>>>         (IS_UNKNOWN_LOCATION): New.
>>>         * fold-const.c (expr_location_or): Change to use new location.
>>>         * reorg.c (emit_delay_sequence): Likewise.
>>>         (try_merge_delay_insns): Likewise.
>>>         * modulo-sched.c (dump_insn_location): Likewise.
>>>         * lto-streamer-out.c (lto_output_location_bitpack): Likewise.
>>>         * jump.c (rtx_renumbered_equal_p): Likewise.
>>>         * ifcvt.c (noce_try_move): Likewise.
>>>         (noce_try_store_flag): Likewise.
>>>         (noce_try_store_flag_constants): Likewise.
>>>         (noce_try_addcc): Likewise.
>>>         (noce_try_store_flag_mask): Likewise.
>>>         (noce_try_cmove): Likewise.
>>>         (noce_try_cmove_arith): Likewise.
>>>         (noce_try_minmax): Likewise.
>>>         (noce_try_abs): Likewise.
>>>         (noce_try_sign_mask): Likewise.
>>>         (noce_try_bitop): Likewise.
>>>         (noce_process_if_block): Likewise.
>>>         (cond_move_process_if_block): Likewise.
>>>         (find_cond_trap): Likewise.
>>>         * dwarf2out.c (add_src_coords_attributes): Likewise.
>>>         * expr.c (expand_expr_real): Likewise.
>>>         * tree-parloops.c (create_loop_fn): Likewise.
>>>         * recog.c (peep2_attempt): Likewise.
>>>         * function.c (free_after_compilation): Likewise.
>>>         (expand_function_end): Likewise.
>>>         (set_insn_locations): Likewise.
>>>         (thread_prologue_and_epilogue_insns): Likewise.
>>>         * print-rtl.c (print_rtx): Likewise.
>>>         * profile.c (branch_prob): Likewise.
>>>         * trans-mem.c (ipa_tm_scan_irr_block): Likewise.
>>>         * gimplify.c (gimplify_call_expr): Likewise.
>>>         * except.c (duplicate_eh_regions_1): Likewise.
>>>         * emit-rtl.c (try_split): Likewise.
>>>         (make_insn_raw): Likewise.
>>>         (make_debug_insn_raw): Likewise.
>>>         (make_jump_insn_raw): Likewise.
>>>         (make_call_insn_raw): Likewise.
>>>         (emit_pattern_after_setloc): Likewise.
>>>         (emit_pattern_after): Likewise.
>>>         (emit_debug_insn_after): Likewise.
>>>         (emit_pattern_before): Likewise.
>>>         (emit_insn_before_setloc): Likewise.
>>>         (emit_jump_insn_before): Likewise.
>>>         (emit_call_insn_before_setloc): Likewise.
>>>         (emit_call_insn_before): Likeise.
>>>         (emit_debug_insn_before_setloc): Likewise.
>>>         (emit_copy_of_insn_after): Likewise.
>>>         (insn_locators_alloc): Remove.
>>>         (insn_locators_finalize): Remove.
>>>         (insn_locators_free): Remove.
>>>         (set_curr_insn_source_location): Remove.
>>>         (get_curr_insn_source_location): Remove.
>>>         (set_curr_insn_block): Remove.
>>>         (get_curr_insn_block): Remove.
>>>         (locator_scope): Remove.
>>>         (insn_scope): Change to use new location.
>>>         (locator_location): Remove.
>>>         (insn_line): Change to use new location.
>>>         (locator_file): Remove.
>>>         (insn_file): Change to use new location.
>>>         (locator_eq): Remove.
>>>         (insn_locations_init): New.
>>>         (insn_locations_finalize): New.
>>>         (set_curr_insn_location): New.
>>>         (curr_insn_location): New.
>>>         * cfgexpand.c (gimple_assign_rhs_to_tree): Change to use new location.
>>>         (expand_gimple_cond): Likewise.
>>>         (expand_call_stmt): Likewise.
>>>         (expand_gimple_stmt_1): Likewise.
>>>         (expand_gimple_basic_block): Likewise.
>>>         (construct_exit_block): Likewise.
>>>         (gimple_expand_cfg): Likewise.
>>>         * cfgcleanup.c (try_forward_edges): Likewise.
>>>         * tree-ssa-live.c (remove_unused_scope_block_p): Likewise.
>>>         (dump_scope_block): Likewise.
>>>         (remove_unused_locals): Likewise.
>>>         * rtl.c (rtx_equal_p_cb): Likewise.
>>>         (rtx_equal_p): Likewise.
>>>         * rtl.h (XUINT): New.
>>>         (INSN_LOCATOR): Remove.
>>>         (CURR_INSN_LOCATION): Remove.
>>>         (INSN_LOCATION): New.
>>>         (INSN_HAS_LOCATION): New.
>>>         * tree-inline.c (remap_gimple_op_r): Change to use new location.
>>>         (copy_tree_body_r): Likewise.
>>>         (copy_phis_for_bb): Likewise.
>>>         (expand_call_inline): Likewise.
>>>         * tree-streamer-in.c (lto_input_ts_exp_tree_pointers): Likewise.
>>>         * tree-streamer-out.c (write_ts_decl_minimal_tree_pointers): Likewise.
>>>         * gimple-streamer-out.c (output_gimple_stmt): Likewise.
>>>         * combine.c (try_combine): Likewise.
>>>         * tree-outof-ssa.c (set_location_for_edge): Likewise.
>>>         (insert_partition_copy_on_edge): Likewise.
>>>         (insert_value_copy_on_edge): Likewise.
>>>         (insert_rtx_to_part_on_edge): Likewise.
>>>         (insert_part_to_rtx_on_edge): Likewise.
>>>         * basic-block.h (edge_def): Remove field.
>>>         * gimple.h (gimple_statement_base): Remove field.
>>>         (gimple_bb): Change to use new location.
>>>         (gimple_set_block): Likewise.
>>>         (gimple_has_location): Likewise.
>>>         * tree-cfg.c (make_cond_expr_edges): Likewise.
>>>         (make_goto_expr_edges): Likewise.
>>>         (gimple_can_merge_blocks_p): Likewise.
>>>         (move_stmt_op): Likewise.
>>>         (move_block_to_fn): Likewise.
>>>         * config/alpha/alpha.c (alpha_output_mi_thunk_osf): Likewise.
>>>         * config/sparc/sparc.c (sparc_output_mi_thunk): Likewise.
>>>         * config/i386/i386.c (x86_output_mi_thunk): Likewise.
>>>         * config/tilegx/tilegx.c (tilegx_output_mi_thunk): Likewise.
>>>         * config/sh/sh.c (sh_output_mi_thunk): Likewise.
>>>         * config/ia64/ia64.c (ia64_output_mi_thunk): Likewise.
>>>         * config/rs6000/rs6000.c (rs6000_output_mi_thunk): Likewise.
>>>         * config/score/score.c (score_output_mi_thunk): Likewise.
>>>         * config/tilepro/tilepro.c (tilepro_asm_output_mi_thunk): Likewise.
>>>         * config/mips/mips.c (mips_output_mi_thunk): Likewise.
>>>         * cfgrtl.c (unique_locus_on_edge_between_p): Likewise.
>>>         (unique_locus_on_edge_between_p): Likewise.
>>>         (emit_nop_for_unique_locus_between): Likewise.
>>>         (force_nonfallthru_and_redirect): Likewise.
>>>         (fixup_reorder_chain): Likewise.
>>>         (cfg_layout_merge_blocks): Likewise.
>>>         * stmt.c (emit_case_nodes): Likewise.
>>>
>>> gcc/lto/ChangeLog:
>>> 2012-09-08  Dehao Chen  <dehao@google.com>
>>>
>>>         * lto/lto.c (lto_fixup_prevailing_decls): Remove tree.exp.block field.
>>>
>>> libcpp/ChangeLog:
>>> 2012-09-08  Dehao Chen  <dehao@google.com>
>>>
>>>         * include/line-map.h (MAX_SOURCE_LOCATION): New value.
>>>         (location_adhoc_data_init): New.
>>>         (location_adhoc_data_fini): New.
>>>         (get_combined_adhoc_loc): New.
>>>         (get_data_from_adhoc_loc): New.
>>>         (get_location_from_adhoc_loc): New.
>>>         (COMBINE_LOCATION_DATA): New.
>>>         (IS_ADHOC_LOC): New.
>>>         (expanded_location): New field.
>>>         * line-map.c (location_adhoc_data): New.
>>>         (location_adhoc_data_htab): New.
>>>         (curr_adhoc_loc): New.
>>>         (location_adhoc_data): New.
>>>         (allocated_location_adhoc_data): New.
>>>         (location_adhoc_data_hash): New.
>>>         (location_adhoc_data_eq): New.
>>>         (location_adhoc_data_update): New.
>>>         (get_combined_adhoc_loc): New.
>>>         (get_data_from_adhoc_loc): New.
>>>         (get_location_from_adhoc_loc): New.
>>>         (location_adhoc_data_init): New.
>>>         (location_adhoc_data_fini): New.
>>>         (linemap_lookup): Change to use new location.
>>>         (linemap_ordinary_map_lookup): Likewise.
>>>         (linemap_macro_map_lookup): Likewise.
>>>         (linemap_macro_map_loc_to_def_point): Likewise.
>>>         (linemap_macro_map_loc_unwind_toward_spel): Likewise.
>>>         (linemap_get_expansion_line): Likewise.
>>>         (linemap_get_expansion_filename): Likewise.
>>>         (linemap_location_in_system_header_p): Likewise.
>>>         (linemap_location_from_macro_expansion_p): Likewise.
>>>         (linemap_macro_loc_to_spelling_point): Likewise.
>>>         (linemap_macro_loc_to_def_point): Likewise.
>>>         (linemap_macro_loc_to_exp_point): Likewise.
>>>         (linemap_resolve_location): Likewise.
>>>         (linemap_unwind_toward_expansion): Likewise.
>>>         (linemap_unwind_to_first_non_reserved_loc): Likewise.
>>>         (linemap_expand_location): Likewise.
>>>         (linemap_dump_location): Likewise.
Michael Matz Sept. 11, 2012, 1:30 p.m. UTC | #6
Hi,

On Tue, 11 Sep 2012, Richard Guenther wrote:

> >>> +++ gcc/lto/lto.c       (working copy)
> >>> @@ -1559,8 +1559,6 @@ lto_fixup_prevailing_decls (tree t)
> >>>  {
> >>>    enum tree_code code = TREE_CODE (t);
> >>>    LTO_NO_PREVAIL (TREE_TYPE (t));
> >>> -  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
> >>> -    LTO_NO_PREVAIL (TREE_CHAIN (t));
> >>
> >> That change is odd.  Can you show us how it breaks?
> >
> > This will break LTO build of gcc.c-torture/execute/pr38051.c
> >
> > There is data structure like:
> >
> >   union { long int l; char c[sizeof (long int)]; } u;
> >
> > Once the block info is reserved for this, it'll reserve this data
> > structure. And inside this data structure, there is VAR_DECL. Thus
> > LTO_NO_PREVAIL assertion does not satisfy here for TREE_CHAIN (t).
> 
> I see - the issue here is that this data structure is not reached at the 
> time we call free_lang_data (via find_decls_types_r).

It should be reached just fine.  The problem is that TREE_CHAIN of that 
union type contains random garbage (in this case the var_decl 'u').  This 
is not supposed to happen.  It's set as part of reading back a BLOCK_VARS 
chain, so the type_decl itself is in such a chain (and 'u' is part of it 
via the TREE_CHAIN pointer).

I have no idea why this is no problem without the patch.  Possibly because 
of the hunk in remove_unused_scope_block_p that makes more blocks stay.

> But maybe I do not understand "once the block info is reserved for 
> this".
> 
> So the patch papers over an issue elsewhere I believe.  Maybe Micha can 
> add some clarification here though, how BLOCK_VARS should be visible 
> here

Hmm.  Without the half-hearted tries to support debug info with LTO the 
block_vars list was no problem, it simply wouldn't be streamed.  Now I 
think it is a problem, and we need to fix it up with the prevailing decls 
if there are multiple ones.  I.e. instead of removing the two lines, 
replace LTO_NO_PREVAIL (TREE_CHAIN (t)) with LTO_SET_PREVAIL.

This is quite unfortunate as we really rather want to make sure that 
TREE_CHAIN isn't randomly set to something.  But as long as block_vars are 
implemented via TREE_CHAIN, and we want to preserve block_vars we don't 
have much choice :-(


Ciao,
Michael.
Richard Biener Sept. 11, 2012, 2:09 p.m. UTC | #7
On Tue, Sep 11, 2012 at 3:30 PM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> On Tue, 11 Sep 2012, Richard Guenther wrote:
>
>> >>> +++ gcc/lto/lto.c       (working copy)
>> >>> @@ -1559,8 +1559,6 @@ lto_fixup_prevailing_decls (tree t)
>> >>>  {
>> >>>    enum tree_code code = TREE_CODE (t);
>> >>>    LTO_NO_PREVAIL (TREE_TYPE (t));
>> >>> -  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
>> >>> -    LTO_NO_PREVAIL (TREE_CHAIN (t));
>> >>
>> >> That change is odd.  Can you show us how it breaks?
>> >
>> > This will break LTO build of gcc.c-torture/execute/pr38051.c
>> >
>> > There is data structure like:
>> >
>> >   union { long int l; char c[sizeof (long int)]; } u;
>> >
>> > Once the block info is reserved for this, it'll reserve this data
>> > structure. And inside this data structure, there is VAR_DECL. Thus
>> > LTO_NO_PREVAIL assertion does not satisfy here for TREE_CHAIN (t).
>>
>> I see - the issue here is that this data structure is not reached at the
>> time we call free_lang_data (via find_decls_types_r).
>
> It should be reached just fine.  The problem is that TREE_CHAIN of that
> union type contains random garbage (in this case the var_decl 'u').  This
> is not supposed to happen.  It's set as part of reading back a BLOCK_VARS
> chain, so the type_decl itself is in such a chain (and 'u' is part of it
> via the TREE_CHAIN pointer).
>
> I have no idea why this is no problem without the patch.  Possibly because
> of the hunk in remove_unused_scope_block_p that makes more blocks stay.
>
>> But maybe I do not understand "once the block info is reserved for
>> this".
>>
>> So the patch papers over an issue elsewhere I believe.  Maybe Micha can
>> add some clarification here though, how BLOCK_VARS should be visible
>> here
>
> Hmm.  Without the half-hearted tries to support debug info with LTO the
> block_vars list was no problem, it simply wouldn't be streamed.  Now I
> think it is a problem, and we need to fix it up with the prevailing decls
> if there are multiple ones.  I.e. instead of removing the two lines,
> replace LTO_NO_PREVAIL (TREE_CHAIN (t)) with LTO_SET_PREVAIL.
>
> This is quite unfortunate as we really rather want to make sure that
> TREE_CHAIN isn't randomly set to something.  But as long as block_vars are
> implemented via TREE_CHAIN, and we want to preserve block_vars we don't
> have much choice :-(

I don't think we can fixup TREE_CHAIN - the things cannot be in multiple
lists after all.  Unifying/fixing up would need to happen at a BLOCK level.
But as you say - only TYPE_DECLs should be in BLOCK_VARS, but never
global ones, so there would be nothing to replace.  Which means we shouldn't
even try to merge those.  Hmm.

Richard.

>
> Ciao,
> Michael.
Michael Matz Sept. 11, 2012, 3:32 p.m. UTC | #8
Hi,

On Tue, 11 Sep 2012, Dehao Chen wrote:

> Looks like we have two choices:
> 
> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)

This will actually not work correctly in some cases.  The problem is, if 
the prevailing decl is already part of another chain (say in another 
block_var list) you would break the current chain.  Hence block vars need 
special handling in the lto streamer (another reason why tree_chain is not 
the most clever think to use for this chain).  This problem area needs to 
be solved somehow if block info is to be preserved correctly.

> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
> (TREE_CHAIN (t)).

That's also a large hammer as it basically will mean no debug info after 
LTO :-/ Sigh, at this point I have no good solution that doesn't involve 
quite some work, perhaps your hack is good enough for the time being, 
though I hate it :)


Ciao,
Michael.
Dehao Chen Sept. 11, 2012, 4 p.m. UTC | #9
I saw comments in tree-streamer-out.c:

  /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
     for early inlining so drop it on the floor instead of ICEing in
     dwarf2out.c.  */
  streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);

However, what the code is doing seemed contradictory with the comment.
Or am I missing something?



On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> On Tue, 11 Sep 2012, Dehao Chen wrote:
>
>> Looks like we have two choices:
>>
>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>
> This will actually not work correctly in some cases.  The problem is, if
> the prevailing decl is already part of another chain (say in another
> block_var list) you would break the current chain.  Hence block vars need
> special handling in the lto streamer (another reason why tree_chain is not
> the most clever think to use for this chain).  This problem area needs to
> be solved somehow if block info is to be preserved correctly.
>
>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>> (TREE_CHAIN (t)).
>
> That's also a large hammer as it basically will mean no debug info after
> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
> quite some work, perhaps your hack is good enough for the time being,
> though I hate it :)

I got it. Then I'll keep the patch as it is (remove the
LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
then we should be good to check in?

Thanks,
Dehao

>
>
> Ciao,
> Michael.
Dehao Chen Sept. 12, 2012, 5:06 a.m. UTC | #10
Now I think we are facing a more complex problem. The data structure
we use to store the location_adhoc_data are file-static in linemap.c
in libcpp. These data structures are not guarded by GTY(()).
Meanwhile, as we have removed the block data structure from
gimple.gsbase as well as tree.exp (encoding them into an location_t).
This could cause block being GCed and the LOCATION_BLOCK becoming
dangling pointers.

I tried to manipulate GTY to make it recognize the LOCATION_BLOCK from
gimple.gsbase.location. However, neigher nested_ptr nor mark_hook can
help me.

Another approach would be guard the location_adhoc_data and related
data structures in GTY(()). However, this is non-trivial because tree
is not visible in libcpp. At the same time, my implementation heavily
relies on hashtable to make the code efficient, thus it's quite tricky
to make "param_is" and "use_params" work.

The final approach, which I'll try tomorrow, would be move all my
implementation from libcpp to gcc, and guard them with GTY(()). I
still haven't thought of any potential problem of this approach. Any
comments?

Thanks,
Dehao

On Tue, Sep 11, 2012 at 9:00 AM, Dehao Chen <dehao@google.com> wrote:
> I saw comments in tree-streamer-out.c:
>
>   /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
>      for early inlining so drop it on the floor instead of ICEing in
>      dwarf2out.c.  */
>   streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
>
> However, what the code is doing seemed contradictory with the comment.
> Or am I missing something?
>
>
>
> On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
>> Hi,
>>
>> On Tue, 11 Sep 2012, Dehao Chen wrote:
>>
>>> Looks like we have two choices:
>>>
>>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>>
>> This will actually not work correctly in some cases.  The problem is, if
>> the prevailing decl is already part of another chain (say in another
>> block_var list) you would break the current chain.  Hence block vars need
>> special handling in the lto streamer (another reason why tree_chain is not
>> the most clever think to use for this chain).  This problem area needs to
>> be solved somehow if block info is to be preserved correctly.
>>
>>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>>> (TREE_CHAIN (t)).
>>
>> That's also a large hammer as it basically will mean no debug info after
>> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>> quite some work, perhaps your hack is good enough for the time being,
>> though I hate it :)
>
> I got it. Then I'll keep the patch as it is (remove the
> LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
> then we should be good to check in?
>
> Thanks,
> Dehao
>
>>
>>
>> Ciao,
>> Michael.
Xinliang David Li Sept. 12, 2012, 5:18 a.m. UTC | #11
Can you make definition of location_adhoc_data available in both
libcpp and gcc? In gcc side, the data structure will be annotated
with GTY().  The root global variables should also be visible in gcc
side.

David

On Tue, Sep 11, 2012 at 10:06 PM, Dehao Chen <dehao@google.com> wrote:
> Now I think we are facing a more complex problem. The data structure
> we use to store the location_adhoc_data are file-static in linemap.c
> in libcpp. These data structures are not guarded by GTY(()).
> Meanwhile, as we have removed the block data structure from
> gimple.gsbase as well as tree.exp (encoding them into an location_t).
> This could cause block being GCed and the LOCATION_BLOCK becoming
> dangling pointers.
>
> I tried to manipulate GTY to make it recognize the LOCATION_BLOCK from
> gimple.gsbase.location. However, neigher nested_ptr nor mark_hook can
> help me.
>
> Another approach would be guard the location_adhoc_data and related
> data structures in GTY(()). However, this is non-trivial because tree
> is not visible in libcpp. At the same time, my implementation heavily
> relies on hashtable to make the code efficient, thus it's quite tricky
> to make "param_is" and "use_params" work.
>
> The final approach, which I'll try tomorrow, would be move all my
> implementation from libcpp to gcc, and guard them with GTY(()). I
> still haven't thought of any potential problem of this approach. Any
> comments?
>
> Thanks,
> Dehao
>
> On Tue, Sep 11, 2012 at 9:00 AM, Dehao Chen <dehao@google.com> wrote:
>> I saw comments in tree-streamer-out.c:
>>
>>   /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
>>      for early inlining so drop it on the floor instead of ICEing in
>>      dwarf2out.c.  */
>>   streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
>>
>> However, what the code is doing seemed contradictory with the comment.
>> Or am I missing something?
>>
>>
>>
>> On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
>>> Hi,
>>>
>>> On Tue, 11 Sep 2012, Dehao Chen wrote:
>>>
>>>> Looks like we have two choices:
>>>>
>>>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>>>
>>> This will actually not work correctly in some cases.  The problem is, if
>>> the prevailing decl is already part of another chain (say in another
>>> block_var list) you would break the current chain.  Hence block vars need
>>> special handling in the lto streamer (another reason why tree_chain is not
>>> the most clever think to use for this chain).  This problem area needs to
>>> be solved somehow if block info is to be preserved correctly.
>>>
>>>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>>>> (TREE_CHAIN (t)).
>>>
>>> That's also a large hammer as it basically will mean no debug info after
>>> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>>> quite some work, perhaps your hack is good enough for the time being,
>>> though I hate it :)
>>
>> I got it. Then I'll keep the patch as it is (remove the
>> LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
>> then we should be good to check in?
>>
>> Thanks,
>> Dehao
>>
>>>
>>>
>>> Ciao,
>>> Michael.
Richard Biener Sept. 12, 2012, 9:08 a.m. UTC | #12
On Tue, Sep 11, 2012 at 5:32 PM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> On Tue, 11 Sep 2012, Dehao Chen wrote:
>
>> Looks like we have two choices:
>>
>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>
> This will actually not work correctly in some cases.  The problem is, if
> the prevailing decl is already part of another chain (say in another
> block_var list) you would break the current chain.  Hence block vars need
> special handling in the lto streamer (another reason why tree_chain is not
> the most clever think to use for this chain).  This problem area needs to
> be solved somehow if block info is to be preserved correctly.

Well.  The issue is that at present we stream BLOCKs in the function section
via its DECL_INTIAL.  Which means we _never_ should get a non-prevailing
DECL in BLOCK_VARS.  You need to debug why that doesn't work anymore.
Possibly the BLOCK leaks into decls it should not leak to via the location
mechanism?

>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>> (TREE_CHAIN (t)).
>
> That's also a large hammer as it basically will mean no debug info after
> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
> quite some work, perhaps your hack is good enough for the time being,
> though I hate it :)

It hides a bug.  If we replace anything in BLOCK_VARS then the risk is
that you generate an infinite chain in some BLOCK_VARS list and thus
get infinite loops somewhere in the compiler.

So, no, that's not an option.

Richard.

>
> Ciao,
> Michael.
Richard Biener Sept. 12, 2012, 9:13 a.m. UTC | #13
On Wed, Sep 12, 2012 at 7:06 AM, Dehao Chen <dehao@google.com> wrote:
> Now I think we are facing a more complex problem. The data structure
> we use to store the location_adhoc_data are file-static in linemap.c
> in libcpp. These data structures are not guarded by GTY(()).
> Meanwhile, as we have removed the block data structure from
> gimple.gsbase as well as tree.exp (encoding them into an location_t).
> This could cause block being GCed and the LOCATION_BLOCK becoming
> dangling pointers.

Uh.  Note that it is quite important that we are able to garbage-collect unused
BLOCKs, this is the whole point of removing unused BLOCK scopes in
remove_unused_locals.  So this indeed becomes much more complicated ...
What would be desired is that the garbage collector can NULL an entry in
the mapping table when it is not referenced in any other way (that other
reference would be the BLOCK tree as stored in a FUNCTION_DECLs DECL_INITIAL).

> I tried to manipulate GTY to make it recognize the LOCATION_BLOCK from
> gimple.gsbase.location. However, neigher nested_ptr nor mark_hook can
> help me.
>
> Another approach would be guard the location_adhoc_data and related
> data structures in GTY(()). However, this is non-trivial because tree
> is not visible in libcpp. At the same time, my implementation heavily
> relies on hashtable to make the code efficient, thus it's quite tricky
> to make "param_is" and "use_params" work.
>
> The final approach, which I'll try tomorrow, would be move all my
> implementation from libcpp to gcc, and guard them with GTY(()). I
> still haven't thought of any potential problem of this approach. Any
> comments?

I think moving the mapping to GC in a lazy manner as I described above
would be the way to go.  For hashtables GC already supports if_marked,
not sure if similar support is available for arrays/vecs.

Richard.

> Thanks,
> Dehao
>
> On Tue, Sep 11, 2012 at 9:00 AM, Dehao Chen <dehao@google.com> wrote:
>> I saw comments in tree-streamer-out.c:
>>
>>   /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
>>      for early inlining so drop it on the floor instead of ICEing in
>>      dwarf2out.c.  */
>>   streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
>>
>> However, what the code is doing seemed contradictory with the comment.
>> Or am I missing something?
>>
>>
>>
>> On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
>>> Hi,
>>>
>>> On Tue, 11 Sep 2012, Dehao Chen wrote:
>>>
>>>> Looks like we have two choices:
>>>>
>>>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>>>
>>> This will actually not work correctly in some cases.  The problem is, if
>>> the prevailing decl is already part of another chain (say in another
>>> block_var list) you would break the current chain.  Hence block vars need
>>> special handling in the lto streamer (another reason why tree_chain is not
>>> the most clever think to use for this chain).  This problem area needs to
>>> be solved somehow if block info is to be preserved correctly.
>>>
>>>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>>>> (TREE_CHAIN (t)).
>>>
>>> That's also a large hammer as it basically will mean no debug info after
>>> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>>> quite some work, perhaps your hack is good enough for the time being,
>>> though I hate it :)
>>
>> I got it. Then I'll keep the patch as it is (remove the
>> LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
>> then we should be good to check in?
>>
>> Thanks,
>> Dehao
>>
>>>
>>>
>>> Ciao,
>>> Michael.
Michael Matz Sept. 12, 2012, 12:14 p.m. UTC | #14
Hi,

On Wed, 12 Sep 2012, Richard Guenther wrote:

> > This will actually not work correctly in some cases.  The problem is, 
> > if the prevailing decl is already part of another chain (say in 
> > another block_var list) you would break the current chain.  Hence 
> > block vars need special handling in the lto streamer (another reason 
> > why tree_chain is not the most clever think to use for this chain).  
> > This problem area needs to be solved somehow if block info is to be 
> > preserved correctly.
> 
> Well.  The issue is that at present we stream BLOCKs in the function 
> section via its DECL_INTIAL.  Which means we _never_ should get a 
> non-prevailing DECL in BLOCK_VARS.  You need to debug why that doesn't 
> work anymore.

The assert that triggers tests that there's no var_decl in TREE_CHAIN.  
It doesn't test that it's a prevailing decl.  So we could assert that 
instead of the current check.

> >> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
> >> (TREE_CHAIN (t)).
> >
> > That's also a large hammer as it basically will mean no debug info after
> > LTO :-/ Sigh, at this point I have no good solution that doesn't involve
> > quite some work, perhaps your hack is good enough for the time being,
> > though I hate it :)
> 
> It hides a bug.  If we replace anything in BLOCK_VARS then the risk is
> that you generate an infinite chain in some BLOCK_VARS list and thus
> get infinite loops somewhere in the compiler.

That's what I said for using SET_PREVAIL.  But his hack would specifically 
not replace anything in TREE_CHAIN (and hence BLOCK_VARS), and indeed not 
check anything either.


Ciao,
Michael.
Richard Biener Sept. 12, 2012, 1:22 p.m. UTC | #15
On Wed, Sep 12, 2012 at 2:14 PM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> On Wed, 12 Sep 2012, Richard Guenther wrote:
>
>> > This will actually not work correctly in some cases.  The problem is,
>> > if the prevailing decl is already part of another chain (say in
>> > another block_var list) you would break the current chain.  Hence
>> > block vars need special handling in the lto streamer (another reason
>> > why tree_chain is not the most clever think to use for this chain).
>> > This problem area needs to be solved somehow if block info is to be
>> > preserved correctly.
>>
>> Well.  The issue is that at present we stream BLOCKs in the function
>> section via its DECL_INTIAL.  Which means we _never_ should get a
>> non-prevailing DECL in BLOCK_VARS.  You need to debug why that doesn't
>> work anymore.
>
> The assert that triggers tests that there's no var_decl in TREE_CHAIN.
> It doesn't test that it's a prevailing decl.  So we could assert that
> instead of the current check.
>
>> >> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>> >> (TREE_CHAIN (t)).
>> >
>> > That's also a large hammer as it basically will mean no debug info after
>> > LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>> > quite some work, perhaps your hack is good enough for the time being,
>> > though I hate it :)
>>
>> It hides a bug.  If we replace anything in BLOCK_VARS then the risk is
>> that you generate an infinite chain in some BLOCK_VARS list and thus
>> get infinite loops somewhere in the compiler.
>
> That's what I said for using SET_PREVAIL.  But his hack would specifically
> not replace anything in TREE_CHAIN (and hence BLOCK_VARS), and indeed not
> check anything either.

Hm, but we shouldn't end up streaming any BLOCKs at this point (nor local
TYPE_DECLs).  Those are supposed to be in the local function sections only
where no fixup for prevailing decls happens.

Richard.

>
> Ciao,
> Michael.
Michael Matz Sept. 12, 2012, 1:23 p.m. UTC | #16
Hi,

On Wed, 12 Sep 2012, Richard Guenther wrote:

> >> It hides a bug.  If we replace anything in BLOCK_VARS then the risk 
> >> is that you generate an infinite chain in some BLOCK_VARS list and 
> >> thus get infinite loops somewhere in the compiler.
> >
> > That's what I said for using SET_PREVAIL.  But his hack would 
> > specifically not replace anything in TREE_CHAIN (and hence 
> > BLOCK_VARS), and indeed not check anything either.
> 
> Hm, but we shouldn't end up streaming any BLOCKs at this point (nor 
> local TYPE_DECLs).  Those are supposed to be in the local function 
> sections only where no fixup for prevailing decls happens.

That's true, something is fishy with the patch, will try to investigate.


Ciao,
Michael.
Xinliang David Li Sept. 12, 2012, 4:39 p.m. UTC | #17
On Wed, Sep 12, 2012 at 2:13 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Sep 12, 2012 at 7:06 AM, Dehao Chen <dehao@google.com> wrote:
>> Now I think we are facing a more complex problem. The data structure
>> we use to store the location_adhoc_data are file-static in linemap.c
>> in libcpp. These data structures are not guarded by GTY(()).
>> Meanwhile, as we have removed the block data structure from
>> gimple.gsbase as well as tree.exp (encoding them into an location_t).
>> This could cause block being GCed and the LOCATION_BLOCK becoming
>> dangling pointers.
>
> Uh.  Note that it is quite important that we are able to garbage-collect unused
> BLOCKs, this is the whole point of removing unused BLOCK scopes in
> remove_unused_locals.  So this indeed becomes much more complicated ...
> What would be desired is that the garbage collector can NULL an entry in
> the mapping table when it is not referenced in any other way (that other
> reference would be the BLOCK tree as stored in a FUNCTION_DECLs DECL_INITIAL).

It would be nice to GC those unused BLOCKS. I wonder how many BLOCKS
are created for a large C++ program. This patch saves memory by
shrinking tree size, is it a net win or loss without GC those BLOCKS?

thanks,

David


>
>> I tried to manipulate GTY to make it recognize the LOCATION_BLOCK from
>> gimple.gsbase.location. However, neigher nested_ptr nor mark_hook can
>> help me.
>>
>> Another approach would be guard the location_adhoc_data and related
>> data structures in GTY(()). However, this is non-trivial because tree
>> is not visible in libcpp. At the same time, my implementation heavily
>> relies on hashtable to make the code efficient, thus it's quite tricky
>> to make "param_is" and "use_params" work.
>>
>> The final approach, which I'll try tomorrow, would be move all my
>> implementation from libcpp to gcc, and guard them with GTY(()). I
>> still haven't thought of any potential problem of this approach. Any
>> comments?
>
> I think moving the mapping to GC in a lazy manner as I described above
> would be the way to go.  For hashtables GC already supports if_marked,
> not sure if similar support is available for arrays/vecs.
>
> Richard.
>
>> Thanks,
>> Dehao
>>
>> On Tue, Sep 11, 2012 at 9:00 AM, Dehao Chen <dehao@google.com> wrote:
>>> I saw comments in tree-streamer-out.c:
>>>
>>>   /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
>>>      for early inlining so drop it on the floor instead of ICEing in
>>>      dwarf2out.c.  */
>>>   streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
>>>
>>> However, what the code is doing seemed contradictory with the comment.
>>> Or am I missing something?
>>>
>>>
>>>
>>> On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
>>>> Hi,
>>>>
>>>> On Tue, 11 Sep 2012, Dehao Chen wrote:
>>>>
>>>>> Looks like we have two choices:
>>>>>
>>>>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>>>>
>>>> This will actually not work correctly in some cases.  The problem is, if
>>>> the prevailing decl is already part of another chain (say in another
>>>> block_var list) you would break the current chain.  Hence block vars need
>>>> special handling in the lto streamer (another reason why tree_chain is not
>>>> the most clever think to use for this chain).  This problem area needs to
>>>> be solved somehow if block info is to be preserved correctly.
>>>>
>>>>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>>>>> (TREE_CHAIN (t)).
>>>>
>>>> That's also a large hammer as it basically will mean no debug info after
>>>> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>>>> quite some work, perhaps your hack is good enough for the time being,
>>>> though I hate it :)
>>>
>>> I got it. Then I'll keep the patch as it is (remove the
>>> LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
>>> then we should be good to check in?
>>>
>>> Thanks,
>>> Dehao
>>>
>>>>
>>>>
>>>> Ciao,
>>>> Michael.
Dehao Chen Sept. 12, 2012, 5:05 p.m. UTC | #18
There are two parts that needs memory management:

1. The BLOCK structure. This is managed by GC. I originally thought
that removing blocks from tree.gsbase would paralyze GC. This turned
out not to be a concern because DECL_INITIAL will still mark those
used tree nodes. This patch may decrease the memory consumption by
removing blocks from tree/gimple. However, as it makes more blocks
become used, they also increase the memory consumption.
2. The data structure in libcpp that maintains the hashtable for the
location->block mapping. This is relatively minor because for the
largest source I've seen, it only maintains less than 100K entries in
the array (less than 1M total memory consumption). However, as it is a
global data structure, it may make LTO unhappy. Honza is helping
testing the memory consumption on LTO (but we first need to make this
patch work for LTO). If the LTO result turns out ok, we probably don't
want to put these under GC because: 1. it'll make things much more
complicated. 2. using self managed memory is more efficient (as this
is frequently used in many passes). 3. not using GC actually saves
memory because even though the block is in the map, it can still be
GCed as soon as it's not reachable from DECL_INITIAL.

I've tested this on some very large C++ files (each one takes more
than 10s to build), the memory consumption does not see noticeable
increase/decrease.

Thanks,
Dehao

On Wed, Sep 12, 2012 at 9:39 AM, Xinliang David Li <davidxl@google.com> wrote:
> On Wed, Sep 12, 2012 at 2:13 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Wed, Sep 12, 2012 at 7:06 AM, Dehao Chen <dehao@google.com> wrote:
>>> Now I think we are facing a more complex problem. The data structure
>>> we use to store the location_adhoc_data are file-static in linemap.c
>>> in libcpp. These data structures are not guarded by GTY(()).
>>> Meanwhile, as we have removed the block data structure from
>>> gimple.gsbase as well as tree.exp (encoding them into an location_t).
>>> This could cause block being GCed and the LOCATION_BLOCK becoming
>>> dangling pointers.
>>
>> Uh.  Note that it is quite important that we are able to garbage-collect unused
>> BLOCKs, this is the whole point of removing unused BLOCK scopes in
>> remove_unused_locals.  So this indeed becomes much more complicated ...
>> What would be desired is that the garbage collector can NULL an entry in
>> the mapping table when it is not referenced in any other way (that other
>> reference would be the BLOCK tree as stored in a FUNCTION_DECLs DECL_INITIAL).
>
> It would be nice to GC those unused BLOCKS. I wonder how many BLOCKS
> are created for a large C++ program. This patch saves memory by
> shrinking tree size, is it a net win or loss without GC those BLOCKS?
>
> thanks,
>
> David
>
>
>>
>>> I tried to manipulate GTY to make it recognize the LOCATION_BLOCK from
>>> gimple.gsbase.location. However, neigher nested_ptr nor mark_hook can
>>> help me.
>>>
>>> Another approach would be guard the location_adhoc_data and related
>>> data structures in GTY(()). However, this is non-trivial because tree
>>> is not visible in libcpp. At the same time, my implementation heavily
>>> relies on hashtable to make the code efficient, thus it's quite tricky
>>> to make "param_is" and "use_params" work.
>>>
>>> The final approach, which I'll try tomorrow, would be move all my
>>> implementation from libcpp to gcc, and guard them with GTY(()). I
>>> still haven't thought of any potential problem of this approach. Any
>>> comments?
>>
>> I think moving the mapping to GC in a lazy manner as I described above
>> would be the way to go.  For hashtables GC already supports if_marked,
>> not sure if similar support is available for arrays/vecs.
>>
>> Richard.
>>
>>> Thanks,
>>> Dehao
>>>
>>> On Tue, Sep 11, 2012 at 9:00 AM, Dehao Chen <dehao@google.com> wrote:
>>>> I saw comments in tree-streamer-out.c:
>>>>
>>>>   /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
>>>>      for early inlining so drop it on the floor instead of ICEing in
>>>>      dwarf2out.c.  */
>>>>   streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
>>>>
>>>> However, what the code is doing seemed contradictory with the comment.
>>>> Or am I missing something?
>>>>
>>>>
>>>>
>>>> On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
>>>>> Hi,
>>>>>
>>>>> On Tue, 11 Sep 2012, Dehao Chen wrote:
>>>>>
>>>>>> Looks like we have two choices:
>>>>>>
>>>>>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>>>>>
>>>>> This will actually not work correctly in some cases.  The problem is, if
>>>>> the prevailing decl is already part of another chain (say in another
>>>>> block_var list) you would break the current chain.  Hence block vars need
>>>>> special handling in the lto streamer (another reason why tree_chain is not
>>>>> the most clever think to use for this chain).  This problem area needs to
>>>>> be solved somehow if block info is to be preserved correctly.
>>>>>
>>>>>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>>>>>> (TREE_CHAIN (t)).
>>>>>
>>>>> That's also a large hammer as it basically will mean no debug info after
>>>>> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>>>>> quite some work, perhaps your hack is good enough for the time being,
>>>>> though I hate it :)
>>>>
>>>> I got it. Then I'll keep the patch as it is (remove the
>>>> LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
>>>> then we should be good to check in?
>>>>
>>>> Thanks,
>>>> Dehao
>>>>
>>>>>
>>>>>
>>>>> Ciao,
>>>>> Michael.
Xinliang David Li Sept. 12, 2012, 5:18 p.m. UTC | #19
On Wed, Sep 12, 2012 at 10:05 AM, Dehao Chen <dehao@google.com> wrote:
> There are two parts that needs memory management:
>
> 1. The BLOCK structure. This is managed by GC. I originally thought
> that removing blocks from tree.gsbase would paralyze GC. This turned
> out not to be a concern because DECL_INITIAL will still mark those
> used tree nodes. This patch may decrease the memory consumption by
> removing blocks from tree/gimple. However, as it makes more blocks
> become used, they also increase the memory consumption.

You mean when you also make the location table GC root.

Can you share the mem-stats information for the large program with and
without your patch?

thanks,

David

> 2. The data structure in libcpp that maintains the hashtable for the
> location->block mapping. This is relatively minor because for the
> largest source I've seen, it only maintains less than 100K entries in
> the array (less than 1M total memory consumption). However, as it is a
> global data structure, it may make LTO unhappy. Honza is helping
> testing the memory consumption on LTO (but we first need to make this
> patch work for LTO). If the LTO result turns out ok, we probably don't
> want to put these under GC because: 1. it'll make things much more
> complicated. 2. using self managed memory is more efficient (as this
> is frequently used in many passes). 3. not using GC actually saves
> memory because even though the block is in the map, it can still be
> GCed as soon as it's not reachable from DECL_INITIAL.
>
> I've tested this on some very large C++ files (each one takes more
> than 10s to build), the memory consumption does not see noticeable
> increase/decrease.
>
> Thanks,
> Dehao
>
> On Wed, Sep 12, 2012 at 9:39 AM, Xinliang David Li <davidxl@google.com> wrote:
>> On Wed, Sep 12, 2012 at 2:13 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Wed, Sep 12, 2012 at 7:06 AM, Dehao Chen <dehao@google.com> wrote:
>>>> Now I think we are facing a more complex problem. The data structure
>>>> we use to store the location_adhoc_data are file-static in linemap.c
>>>> in libcpp. These data structures are not guarded by GTY(()).
>>>> Meanwhile, as we have removed the block data structure from
>>>> gimple.gsbase as well as tree.exp (encoding them into an location_t).
>>>> This could cause block being GCed and the LOCATION_BLOCK becoming
>>>> dangling pointers.
>>>
>>> Uh.  Note that it is quite important that we are able to garbage-collect unused
>>> BLOCKs, this is the whole point of removing unused BLOCK scopes in
>>> remove_unused_locals.  So this indeed becomes much more complicated ...
>>> What would be desired is that the garbage collector can NULL an entry in
>>> the mapping table when it is not referenced in any other way (that other
>>> reference would be the BLOCK tree as stored in a FUNCTION_DECLs DECL_INITIAL).
>>
>> It would be nice to GC those unused BLOCKS. I wonder how many BLOCKS
>> are created for a large C++ program. This patch saves memory by
>> shrinking tree size, is it a net win or loss without GC those BLOCKS?
>>
>> thanks,
>>
>> David
>>
>>
>>>
>>>> I tried to manipulate GTY to make it recognize the LOCATION_BLOCK from
>>>> gimple.gsbase.location. However, neigher nested_ptr nor mark_hook can
>>>> help me.
>>>>
>>>> Another approach would be guard the location_adhoc_data and related
>>>> data structures in GTY(()). However, this is non-trivial because tree
>>>> is not visible in libcpp. At the same time, my implementation heavily
>>>> relies on hashtable to make the code efficient, thus it's quite tricky
>>>> to make "param_is" and "use_params" work.
>>>>
>>>> The final approach, which I'll try tomorrow, would be move all my
>>>> implementation from libcpp to gcc, and guard them with GTY(()). I
>>>> still haven't thought of any potential problem of this approach. Any
>>>> comments?
>>>
>>> I think moving the mapping to GC in a lazy manner as I described above
>>> would be the way to go.  For hashtables GC already supports if_marked,
>>> not sure if similar support is available for arrays/vecs.
>>>
>>> Richard.
>>>
>>>> Thanks,
>>>> Dehao
>>>>
>>>> On Tue, Sep 11, 2012 at 9:00 AM, Dehao Chen <dehao@google.com> wrote:
>>>>> I saw comments in tree-streamer-out.c:
>>>>>
>>>>>   /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
>>>>>      for early inlining so drop it on the floor instead of ICEing in
>>>>>      dwarf2out.c.  */
>>>>>   streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
>>>>>
>>>>> However, what the code is doing seemed contradictory with the comment.
>>>>> Or am I missing something?
>>>>>
>>>>>
>>>>>
>>>>> On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On Tue, 11 Sep 2012, Dehao Chen wrote:
>>>>>>
>>>>>>> Looks like we have two choices:
>>>>>>>
>>>>>>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>>>>>>
>>>>>> This will actually not work correctly in some cases.  The problem is, if
>>>>>> the prevailing decl is already part of another chain (say in another
>>>>>> block_var list) you would break the current chain.  Hence block vars need
>>>>>> special handling in the lto streamer (another reason why tree_chain is not
>>>>>> the most clever think to use for this chain).  This problem area needs to
>>>>>> be solved somehow if block info is to be preserved correctly.
>>>>>>
>>>>>>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>>>>>>> (TREE_CHAIN (t)).
>>>>>>
>>>>>> That's also a large hammer as it basically will mean no debug info after
>>>>>> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>>>>>> quite some work, perhaps your hack is good enough for the time being,
>>>>>> though I hate it :)
>>>>>
>>>>> I got it. Then I'll keep the patch as it is (remove the
>>>>> LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
>>>>> then we should be good to check in?
>>>>>
>>>>> Thanks,
>>>>> Dehao
>>>>>
>>>>>>
>>>>>>
>>>>>> Ciao,
>>>>>> Michael.
Dehao Chen Sept. 12, 2012, 8:44 p.m. UTC | #20
Attached is the memory consumption report for a very large source
file. Looks like this patch actually reduced the memory consumption by
2%.

Dehao

On Thu, Sep 13, 2012 at 1:18 AM, Xinliang David Li <davidxl@google.com> wrote:
> On Wed, Sep 12, 2012 at 10:05 AM, Dehao Chen <dehao@google.com> wrote:
>> There are two parts that needs memory management:
>>
>> 1. The BLOCK structure. This is managed by GC. I originally thought
>> that removing blocks from tree.gsbase would paralyze GC. This turned
>> out not to be a concern because DECL_INITIAL will still mark those
>> used tree nodes. This patch may decrease the memory consumption by
>> removing blocks from tree/gimple. However, as it makes more blocks
>> become used, they also increase the memory consumption.
>
> You mean when you also make the location table GC root.
>
> Can you share the mem-stats information for the large program with and
> without your patch?
>
> thanks,
>
> David
>
>> 2. The data structure in libcpp that maintains the hashtable for the
>> location->block mapping. This is relatively minor because for the
>> largest source I've seen, it only maintains less than 100K entries in
>> the array (less than 1M total memory consumption). However, as it is a
>> global data structure, it may make LTO unhappy. Honza is helping
>> testing the memory consumption on LTO (but we first need to make this
>> patch work for LTO). If the LTO result turns out ok, we probably don't
>> want to put these under GC because: 1. it'll make things much more
>> complicated. 2. using self managed memory is more efficient (as this
>> is frequently used in many passes). 3. not using GC actually saves
>> memory because even though the block is in the map, it can still be
>> GCed as soon as it's not reachable from DECL_INITIAL.
>>
>> I've tested this on some very large C++ files (each one takes more
>> than 10s to build), the memory consumption does not see noticeable
>> increase/decrease.
>>
>> Thanks,
>> Dehao
>>
>> On Wed, Sep 12, 2012 at 9:39 AM, Xinliang David Li <davidxl@google.com> wrote:
>>> On Wed, Sep 12, 2012 at 2:13 AM, Richard Guenther
>>> <richard.guenther@gmail.com> wrote:
>>>> On Wed, Sep 12, 2012 at 7:06 AM, Dehao Chen <dehao@google.com> wrote:
>>>>> Now I think we are facing a more complex problem. The data structure
>>>>> we use to store the location_adhoc_data are file-static in linemap.c
>>>>> in libcpp. These data structures are not guarded by GTY(()).
>>>>> Meanwhile, as we have removed the block data structure from
>>>>> gimple.gsbase as well as tree.exp (encoding them into an location_t).
>>>>> This could cause block being GCed and the LOCATION_BLOCK becoming
>>>>> dangling pointers.
>>>>
>>>> Uh.  Note that it is quite important that we are able to garbage-collect unused
>>>> BLOCKs, this is the whole point of removing unused BLOCK scopes in
>>>> remove_unused_locals.  So this indeed becomes much more complicated ...
>>>> What would be desired is that the garbage collector can NULL an entry in
>>>> the mapping table when it is not referenced in any other way (that other
>>>> reference would be the BLOCK tree as stored in a FUNCTION_DECLs DECL_INITIAL).
>>>
>>> It would be nice to GC those unused BLOCKS. I wonder how many BLOCKS
>>> are created for a large C++ program. This patch saves memory by
>>> shrinking tree size, is it a net win or loss without GC those BLOCKS?
>>>
>>> thanks,
>>>
>>> David
>>>
>>>
>>>>
>>>>> I tried to manipulate GTY to make it recognize the LOCATION_BLOCK from
>>>>> gimple.gsbase.location. However, neigher nested_ptr nor mark_hook can
>>>>> help me.
>>>>>
>>>>> Another approach would be guard the location_adhoc_data and related
>>>>> data structures in GTY(()). However, this is non-trivial because tree
>>>>> is not visible in libcpp. At the same time, my implementation heavily
>>>>> relies on hashtable to make the code efficient, thus it's quite tricky
>>>>> to make "param_is" and "use_params" work.
>>>>>
>>>>> The final approach, which I'll try tomorrow, would be move all my
>>>>> implementation from libcpp to gcc, and guard them with GTY(()). I
>>>>> still haven't thought of any potential problem of this approach. Any
>>>>> comments?
>>>>
>>>> I think moving the mapping to GC in a lazy manner as I described above
>>>> would be the way to go.  For hashtables GC already supports if_marked,
>>>> not sure if similar support is available for arrays/vecs.
>>>>
>>>> Richard.
>>>>
>>>>> Thanks,
>>>>> Dehao
>>>>>
>>>>> On Tue, Sep 11, 2012 at 9:00 AM, Dehao Chen <dehao@google.com> wrote:
>>>>>> I saw comments in tree-streamer-out.c:
>>>>>>
>>>>>>   /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
>>>>>>      for early inlining so drop it on the floor instead of ICEing in
>>>>>>      dwarf2out.c.  */
>>>>>>   streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
>>>>>>
>>>>>> However, what the code is doing seemed contradictory with the comment.
>>>>>> Or am I missing something?
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> On Tue, 11 Sep 2012, Dehao Chen wrote:
>>>>>>>
>>>>>>>> Looks like we have two choices:
>>>>>>>>
>>>>>>>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>>>>>>>
>>>>>>> This will actually not work correctly in some cases.  The problem is, if
>>>>>>> the prevailing decl is already part of another chain (say in another
>>>>>>> block_var list) you would break the current chain.  Hence block vars need
>>>>>>> special handling in the lto streamer (another reason why tree_chain is not
>>>>>>> the most clever think to use for this chain).  This problem area needs to
>>>>>>> be solved somehow if block info is to be preserved correctly.
>>>>>>>
>>>>>>>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>>>>>>>> (TREE_CHAIN (t)).
>>>>>>>
>>>>>>> That's also a large hammer as it basically will mean no debug info after
>>>>>>> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>>>>>>> quite some work, perhaps your hack is good enough for the time being,
>>>>>>> though I hate it :)
>>>>>>
>>>>>> I got it. Then I'll keep the patch as it is (remove the
>>>>>> LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
>>>>>> then we should be good to check in?
>>>>>>
>>>>>> Thanks,
>>>>>> Dehao
>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Ciao,
>>>>>>> Michael.
Number of expanded macros:                     23481
Average number of tokens per macro expansion:     12

Line Table allocations during the compilation process
Number of ordinary maps used:         1451 
Ordinary map used size:                 56k
Number of ordinary maps allocated:    1638 
Ordinary maps allocated size:           63k
Number of macro maps used:               0 
Macro maps used size:                    0 
Macro maps locations size:               0 
Macro maps size:                         0 
Duplicated maps locations size:          0 
Total allocated maps size:              63k
Total used maps size:                   56k

Memory still allocated at the end of the compilation process
Size   Allocated        Used    Overhead
8             88k         64k       2640 
16            16M       4726k        356k
32            31M         11M        570k
64            60M         37M        960k
128         7296k       6833k         99k
256           29M         24M        417k
512         1224k        753k         16k
1024          21M         21M        301k
2048         600k        484k       8400 
4096        2660k       2660k         36k
8192        1352k       1352k       9464 
16384       2560k       2560k       8960 
32768        288k        288k        504 
65536        512k        512k        448 
131072        256k        256k        112 
262144       2048k       2048k        448 
524288       2560k       2560k        280 
1048576       4096k       4096k        224 
2097152       2048k       2048k         56 
24            48M       7165k        875k
40            66M         24M       1068k
48            21M       5121k        342k
56            14M       4309k        230k
72            30M         16M        431k
80            82M         49M       1149k
88            15M         10M        218k
104           10M       8041k        152k
112        10056k       2527k        137k
120           10M       6083k        146k
184           20M         17M        292k
152         8996k       6841k        122k
160           38M         11M        532k
168           53M         40M        754k
96            17M       6035k        251k
304           54M         49M        761k
136           35M         31M        496k
Total        726M        421M         10M

String pool
entries		187117
identifiers	111112 (59.38%)
slots		262144
deleted		67636
bytes		5237k (17592186044410M overhead)
table size	2048k
coll/search	1.3684
ins/search	0.0853
avg. entry	28.66 bytes (+/- 34.34)
longest entry	236

??? tree nodes created

(No per-node statistics)
Type hash: size 131071, 68058 elements, 1.008263 collisions
DECL_DEBUG_EXPR  hash: size 8191, 131 elements, 0.527951 collisions
DECL_VALUE_EXPR  hash: size 1021, 16 elements, 0.000000 collisions
no search statistics
decl_specializations: size 65521, 33767 elements, 1.169079 collisions
type_specializations: size 32749, 22750 elements, 1.193797 collisions
No gimple statistics

Alias oracle query stats:
  refs_may_alias_p: 8495 disambiguations, 24866 queries
  ref_maybe_used_by_call_p: 152203 disambiguations, 27333 queries
  call_may_clobber_ref_p: 151635 disambiguations, 151635 queries

PTA query stats:
  pt_solution_includes: 430 disambiguations, 17991 queries
  pt_solutions_intersect: 1291 disambiguations, 655295 queries
Number of expanded macros:                     23481
Average number of tokens per macro expansion:     12

Line Table allocations during the compilation process
Number of ordinary maps used:         1451 
Ordinary map used size:                 56k
Number of ordinary maps allocated:    1638 
Ordinary maps allocated size:           63k
Number of macro maps used:               0 
Macro maps used size:                    0 
Macro maps locations size:               0 
Macro maps size:                         0 
Duplicated maps locations size:          0 
Total allocated maps size:              63k
Total used maps size:                   56k

Memory still allocated at the end of the compilation process
Size   Allocated        Used    Overhead
8             88k         64k       2640 
16            17M       4640k        376k
32            48M         13M        865k
64            51M         34M        820k
128         8596k       6686k        117k
256           27M         23M        385k
512         1184k        753k         16k
1024          21M         21M        299k
2048         592k        484k       8288 
4096        2660k       2660k         36k
8192        1352k       1352k       9464 
16384       2560k       2560k       8960 
32768        288k        288k        504 
65536        512k        512k        448 
131072        256k        256k        112 
262144       1792k       1792k        392 
524288       3072k       3072k        336 
1048576       4096k       4096k        224 
2097152       2048k       2048k         56 
24            55M       7228k        995k
40            61M         22M        990k
48            19M       6224k        318k
56            14M       4400k        238k
72            45M         17M        643k
80            65M         42M        920k
88            12M         10M        172k
104           10M       8087k        145k
112        10124k       2468k        138k
120           10M       5958k        141k
184           21M         17M        295k
152         8348k       6826k        114k
160           19M       6792k        275k
168           54M         40M        757k
96            18M       6030k        259k
304           54M         49M        762k
136           33M         31M        473k
Total        710M        407M         10M

String pool
entries		187117
identifiers	108460 (57.96%)
slots		262144
deleted		70040
bytes		5133k (17592186044410M overhead)
table size	2048k
coll/search	1.3759
ins/search	0.0847
avg. entry	28.09 bytes (+/- 34.18)
longest entry	236

??? tree nodes created

(No per-node statistics)
Type hash: size 131071, 68058 elements, 1.009220 collisions
DECL_DEBUG_EXPR  hash: size 8191, 131 elements, 0.457233 collisions
DECL_VALUE_EXPR  hash: size 1021, 15 elements, 0.033784 collisions
no search statistics
decl_specializations: size 65521, 33767 elements, 1.169079 collisions
type_specializations: size 32749, 22750 elements, 1.193797 collisions
No gimple statistics

Alias oracle query stats:
  refs_may_alias_p: 8495 disambiguations, 24866 queries
  ref_maybe_used_by_call_p: 152240 disambiguations, 27333 queries
  call_may_clobber_ref_p: 151672 disambiguations, 151672 queries

PTA query stats:
  pt_solution_includes: 430 disambiguations, 17991 queries
  pt_solutions_intersect: 1291 disambiguations, 655295 queries
Xinliang David Li Sept. 12, 2012, 8:59 p.m. UTC | #21
For the largest bucket (size==80), the size reduction is 20%. Not bad.

David

On Wed, Sep 12, 2012 at 1:44 PM, Dehao Chen <dehao@google.com> wrote:
> Attached is the memory consumption report for a very large source
> file. Looks like this patch actually reduced the memory consumption by
> 2%.
>
> Dehao
>
> On Thu, Sep 13, 2012 at 1:18 AM, Xinliang David Li <davidxl@google.com> wrote:
>> On Wed, Sep 12, 2012 at 10:05 AM, Dehao Chen <dehao@google.com> wrote:
>>> There are two parts that needs memory management:
>>>
>>> 1. The BLOCK structure. This is managed by GC. I originally thought
>>> that removing blocks from tree.gsbase would paralyze GC. This turned
>>> out not to be a concern because DECL_INITIAL will still mark those
>>> used tree nodes. This patch may decrease the memory consumption by
>>> removing blocks from tree/gimple. However, as it makes more blocks
>>> become used, they also increase the memory consumption.
>>
>> You mean when you also make the location table GC root.
>>
>> Can you share the mem-stats information for the large program with and
>> without your patch?
>>
>> thanks,
>>
>> David
>>
>>> 2. The data structure in libcpp that maintains the hashtable for the
>>> location->block mapping. This is relatively minor because for the
>>> largest source I've seen, it only maintains less than 100K entries in
>>> the array (less than 1M total memory consumption). However, as it is a
>>> global data structure, it may make LTO unhappy. Honza is helping
>>> testing the memory consumption on LTO (but we first need to make this
>>> patch work for LTO). If the LTO result turns out ok, we probably don't
>>> want to put these under GC because: 1. it'll make things much more
>>> complicated. 2. using self managed memory is more efficient (as this
>>> is frequently used in many passes). 3. not using GC actually saves
>>> memory because even though the block is in the map, it can still be
>>> GCed as soon as it's not reachable from DECL_INITIAL.
>>>
>>> I've tested this on some very large C++ files (each one takes more
>>> than 10s to build), the memory consumption does not see noticeable
>>> increase/decrease.
>>>
>>> Thanks,
>>> Dehao
>>>
>>> On Wed, Sep 12, 2012 at 9:39 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>> On Wed, Sep 12, 2012 at 2:13 AM, Richard Guenther
>>>> <richard.guenther@gmail.com> wrote:
>>>>> On Wed, Sep 12, 2012 at 7:06 AM, Dehao Chen <dehao@google.com> wrote:
>>>>>> Now I think we are facing a more complex problem. The data structure
>>>>>> we use to store the location_adhoc_data are file-static in linemap.c
>>>>>> in libcpp. These data structures are not guarded by GTY(()).
>>>>>> Meanwhile, as we have removed the block data structure from
>>>>>> gimple.gsbase as well as tree.exp (encoding them into an location_t).
>>>>>> This could cause block being GCed and the LOCATION_BLOCK becoming
>>>>>> dangling pointers.
>>>>>
>>>>> Uh.  Note that it is quite important that we are able to garbage-collect unused
>>>>> BLOCKs, this is the whole point of removing unused BLOCK scopes in
>>>>> remove_unused_locals.  So this indeed becomes much more complicated ...
>>>>> What would be desired is that the garbage collector can NULL an entry in
>>>>> the mapping table when it is not referenced in any other way (that other
>>>>> reference would be the BLOCK tree as stored in a FUNCTION_DECLs DECL_INITIAL).
>>>>
>>>> It would be nice to GC those unused BLOCKS. I wonder how many BLOCKS
>>>> are created for a large C++ program. This patch saves memory by
>>>> shrinking tree size, is it a net win or loss without GC those BLOCKS?
>>>>
>>>> thanks,
>>>>
>>>> David
>>>>
>>>>
>>>>>
>>>>>> I tried to manipulate GTY to make it recognize the LOCATION_BLOCK from
>>>>>> gimple.gsbase.location. However, neigher nested_ptr nor mark_hook can
>>>>>> help me.
>>>>>>
>>>>>> Another approach would be guard the location_adhoc_data and related
>>>>>> data structures in GTY(()). However, this is non-trivial because tree
>>>>>> is not visible in libcpp. At the same time, my implementation heavily
>>>>>> relies on hashtable to make the code efficient, thus it's quite tricky
>>>>>> to make "param_is" and "use_params" work.
>>>>>>
>>>>>> The final approach, which I'll try tomorrow, would be move all my
>>>>>> implementation from libcpp to gcc, and guard them with GTY(()). I
>>>>>> still haven't thought of any potential problem of this approach. Any
>>>>>> comments?
>>>>>
>>>>> I think moving the mapping to GC in a lazy manner as I described above
>>>>> would be the way to go.  For hashtables GC already supports if_marked,
>>>>> not sure if similar support is available for arrays/vecs.
>>>>>
>>>>> Richard.
>>>>>
>>>>>> Thanks,
>>>>>> Dehao
>>>>>>
>>>>>> On Tue, Sep 11, 2012 at 9:00 AM, Dehao Chen <dehao@google.com> wrote:
>>>>>>> I saw comments in tree-streamer-out.c:
>>>>>>>
>>>>>>>   /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
>>>>>>>      for early inlining so drop it on the floor instead of ICEing in
>>>>>>>      dwarf2out.c.  */
>>>>>>>   streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
>>>>>>>
>>>>>>> However, what the code is doing seemed contradictory with the comment.
>>>>>>> Or am I missing something?
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> On Tue, 11 Sep 2012, Dehao Chen wrote:
>>>>>>>>
>>>>>>>>> Looks like we have two choices:
>>>>>>>>>
>>>>>>>>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>>>>>>>>
>>>>>>>> This will actually not work correctly in some cases.  The problem is, if
>>>>>>>> the prevailing decl is already part of another chain (say in another
>>>>>>>> block_var list) you would break the current chain.  Hence block vars need
>>>>>>>> special handling in the lto streamer (another reason why tree_chain is not
>>>>>>>> the most clever think to use for this chain).  This problem area needs to
>>>>>>>> be solved somehow if block info is to be preserved correctly.
>>>>>>>>
>>>>>>>>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>>>>>>>>> (TREE_CHAIN (t)).
>>>>>>>>
>>>>>>>> That's also a large hammer as it basically will mean no debug info after
>>>>>>>> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>>>>>>>> quite some work, perhaps your hack is good enough for the time being,
>>>>>>>> though I hate it :)
>>>>>>>
>>>>>>> I got it. Then I'll keep the patch as it is (remove the
>>>>>>> LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
>>>>>>> then we should be good to check in?
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Dehao
>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Ciao,
>>>>>>>> Michael.
Richard Biener Sept. 13, 2012, 12:02 p.m. UTC | #22
On Wed, Sep 12, 2012 at 6:39 PM, Xinliang David Li <davidxl@google.com> wrote:
> On Wed, Sep 12, 2012 at 2:13 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Wed, Sep 12, 2012 at 7:06 AM, Dehao Chen <dehao@google.com> wrote:
>>> Now I think we are facing a more complex problem. The data structure
>>> we use to store the location_adhoc_data are file-static in linemap.c
>>> in libcpp. These data structures are not guarded by GTY(()).
>>> Meanwhile, as we have removed the block data structure from
>>> gimple.gsbase as well as tree.exp (encoding them into an location_t).
>>> This could cause block being GCed and the LOCATION_BLOCK becoming
>>> dangling pointers.
>>
>> Uh.  Note that it is quite important that we are able to garbage-collect unused
>> BLOCKs, this is the whole point of removing unused BLOCK scopes in
>> remove_unused_locals.  So this indeed becomes much more complicated ...
>> What would be desired is that the garbage collector can NULL an entry in
>> the mapping table when it is not referenced in any other way (that other
>> reference would be the BLOCK tree as stored in a FUNCTION_DECLs DECL_INITIAL).
>
> It would be nice to GC those unused BLOCKS. I wonder how many BLOCKS
> are created for a large C++ program. This patch saves memory by
> shrinking tree size, is it a net win or loss without GC those BLOCKS?

Memory usage issues pop up with C++ code using expression templates
(try BOOST MPL or tramp3d or some larger spirit testcases).  Inlining
creates tons of "empty" BLOCK trees that just wrap others.  It is important
to be able to GC those.  Now, it might be that no expression / location
which references the BLOCK survives, and if the line-table is not scanned
by GC then we will just end up with never re-usable entries (the BLOCK address
may get re-used - can we get false sharing here?)

Richard.

> thanks,
>
> David
>
>
>>
>>> I tried to manipulate GTY to make it recognize the LOCATION_BLOCK from
>>> gimple.gsbase.location. However, neigher nested_ptr nor mark_hook can
>>> help me.
>>>
>>> Another approach would be guard the location_adhoc_data and related
>>> data structures in GTY(()). However, this is non-trivial because tree
>>> is not visible in libcpp. At the same time, my implementation heavily
>>> relies on hashtable to make the code efficient, thus it's quite tricky
>>> to make "param_is" and "use_params" work.
>>>
>>> The final approach, which I'll try tomorrow, would be move all my
>>> implementation from libcpp to gcc, and guard them with GTY(()). I
>>> still haven't thought of any potential problem of this approach. Any
>>> comments?
>>
>> I think moving the mapping to GC in a lazy manner as I described above
>> would be the way to go.  For hashtables GC already supports if_marked,
>> not sure if similar support is available for arrays/vecs.
>>
>> Richard.
>>
>>> Thanks,
>>> Dehao
>>>
>>> On Tue, Sep 11, 2012 at 9:00 AM, Dehao Chen <dehao@google.com> wrote:
>>>> I saw comments in tree-streamer-out.c:
>>>>
>>>>   /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
>>>>      for early inlining so drop it on the floor instead of ICEing in
>>>>      dwarf2out.c.  */
>>>>   streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
>>>>
>>>> However, what the code is doing seemed contradictory with the comment.
>>>> Or am I missing something?
>>>>
>>>>
>>>>
>>>> On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
>>>>> Hi,
>>>>>
>>>>> On Tue, 11 Sep 2012, Dehao Chen wrote:
>>>>>
>>>>>> Looks like we have two choices:
>>>>>>
>>>>>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>>>>>
>>>>> This will actually not work correctly in some cases.  The problem is, if
>>>>> the prevailing decl is already part of another chain (say in another
>>>>> block_var list) you would break the current chain.  Hence block vars need
>>>>> special handling in the lto streamer (another reason why tree_chain is not
>>>>> the most clever think to use for this chain).  This problem area needs to
>>>>> be solved somehow if block info is to be preserved correctly.
>>>>>
>>>>>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>>>>>> (TREE_CHAIN (t)).
>>>>>
>>>>> That's also a large hammer as it basically will mean no debug info after
>>>>> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>>>>> quite some work, perhaps your hack is good enough for the time being,
>>>>> though I hate it :)
>>>>
>>>> I got it. Then I'll keep the patch as it is (remove the
>>>> LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
>>>> then we should be good to check in?
>>>>
>>>> Thanks,
>>>> Dehao
>>>>
>>>>>
>>>>>
>>>>> Ciao,
>>>>> Michael.
Richard Biener Sept. 13, 2012, 12:04 p.m. UTC | #23
On Wed, Sep 12, 2012 at 10:44 PM, Dehao Chen <dehao@google.com> wrote:
> Attached is the memory consumption report for a very large source
> file. Looks like this patch actually reduced the memory consumption by
> 2%.

Please make sure to test large C++ expression template users.  Large
regular programs do not stress this part.

Richard.

> Dehao
>
> On Thu, Sep 13, 2012 at 1:18 AM, Xinliang David Li <davidxl@google.com> wrote:
>> On Wed, Sep 12, 2012 at 10:05 AM, Dehao Chen <dehao@google.com> wrote:
>>> There are two parts that needs memory management:
>>>
>>> 1. The BLOCK structure. This is managed by GC. I originally thought
>>> that removing blocks from tree.gsbase would paralyze GC. This turned
>>> out not to be a concern because DECL_INITIAL will still mark those
>>> used tree nodes. This patch may decrease the memory consumption by
>>> removing blocks from tree/gimple. However, as it makes more blocks
>>> become used, they also increase the memory consumption.
>>
>> You mean when you also make the location table GC root.
>>
>> Can you share the mem-stats information for the large program with and
>> without your patch?
>>
>> thanks,
>>
>> David
>>
>>> 2. The data structure in libcpp that maintains the hashtable for the
>>> location->block mapping. This is relatively minor because for the
>>> largest source I've seen, it only maintains less than 100K entries in
>>> the array (less than 1M total memory consumption). However, as it is a
>>> global data structure, it may make LTO unhappy. Honza is helping
>>> testing the memory consumption on LTO (but we first need to make this
>>> patch work for LTO). If the LTO result turns out ok, we probably don't
>>> want to put these under GC because: 1. it'll make things much more
>>> complicated. 2. using self managed memory is more efficient (as this
>>> is frequently used in many passes). 3. not using GC actually saves
>>> memory because even though the block is in the map, it can still be
>>> GCed as soon as it's not reachable from DECL_INITIAL.
>>>
>>> I've tested this on some very large C++ files (each one takes more
>>> than 10s to build), the memory consumption does not see noticeable
>>> increase/decrease.
>>>
>>> Thanks,
>>> Dehao
>>>
>>> On Wed, Sep 12, 2012 at 9:39 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>> On Wed, Sep 12, 2012 at 2:13 AM, Richard Guenther
>>>> <richard.guenther@gmail.com> wrote:
>>>>> On Wed, Sep 12, 2012 at 7:06 AM, Dehao Chen <dehao@google.com> wrote:
>>>>>> Now I think we are facing a more complex problem. The data structure
>>>>>> we use to store the location_adhoc_data are file-static in linemap.c
>>>>>> in libcpp. These data structures are not guarded by GTY(()).
>>>>>> Meanwhile, as we have removed the block data structure from
>>>>>> gimple.gsbase as well as tree.exp (encoding them into an location_t).
>>>>>> This could cause block being GCed and the LOCATION_BLOCK becoming
>>>>>> dangling pointers.
>>>>>
>>>>> Uh.  Note that it is quite important that we are able to garbage-collect unused
>>>>> BLOCKs, this is the whole point of removing unused BLOCK scopes in
>>>>> remove_unused_locals.  So this indeed becomes much more complicated ...
>>>>> What would be desired is that the garbage collector can NULL an entry in
>>>>> the mapping table when it is not referenced in any other way (that other
>>>>> reference would be the BLOCK tree as stored in a FUNCTION_DECLs DECL_INITIAL).
>>>>
>>>> It would be nice to GC those unused BLOCKS. I wonder how many BLOCKS
>>>> are created for a large C++ program. This patch saves memory by
>>>> shrinking tree size, is it a net win or loss without GC those BLOCKS?
>>>>
>>>> thanks,
>>>>
>>>> David
>>>>
>>>>
>>>>>
>>>>>> I tried to manipulate GTY to make it recognize the LOCATION_BLOCK from
>>>>>> gimple.gsbase.location. However, neigher nested_ptr nor mark_hook can
>>>>>> help me.
>>>>>>
>>>>>> Another approach would be guard the location_adhoc_data and related
>>>>>> data structures in GTY(()). However, this is non-trivial because tree
>>>>>> is not visible in libcpp. At the same time, my implementation heavily
>>>>>> relies on hashtable to make the code efficient, thus it's quite tricky
>>>>>> to make "param_is" and "use_params" work.
>>>>>>
>>>>>> The final approach, which I'll try tomorrow, would be move all my
>>>>>> implementation from libcpp to gcc, and guard them with GTY(()). I
>>>>>> still haven't thought of any potential problem of this approach. Any
>>>>>> comments?
>>>>>
>>>>> I think moving the mapping to GC in a lazy manner as I described above
>>>>> would be the way to go.  For hashtables GC already supports if_marked,
>>>>> not sure if similar support is available for arrays/vecs.
>>>>>
>>>>> Richard.
>>>>>
>>>>>> Thanks,
>>>>>> Dehao
>>>>>>
>>>>>> On Tue, Sep 11, 2012 at 9:00 AM, Dehao Chen <dehao@google.com> wrote:
>>>>>>> I saw comments in tree-streamer-out.c:
>>>>>>>
>>>>>>>   /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
>>>>>>>      for early inlining so drop it on the floor instead of ICEing in
>>>>>>>      dwarf2out.c.  */
>>>>>>>   streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
>>>>>>>
>>>>>>> However, what the code is doing seemed contradictory with the comment.
>>>>>>> Or am I missing something?
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> On Tue, 11 Sep 2012, Dehao Chen wrote:
>>>>>>>>
>>>>>>>>> Looks like we have two choices:
>>>>>>>>>
>>>>>>>>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>>>>>>>>
>>>>>>>> This will actually not work correctly in some cases.  The problem is, if
>>>>>>>> the prevailing decl is already part of another chain (say in another
>>>>>>>> block_var list) you would break the current chain.  Hence block vars need
>>>>>>>> special handling in the lto streamer (another reason why tree_chain is not
>>>>>>>> the most clever think to use for this chain).  This problem area needs to
>>>>>>>> be solved somehow if block info is to be preserved correctly.
>>>>>>>>
>>>>>>>>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>>>>>>>>> (TREE_CHAIN (t)).
>>>>>>>>
>>>>>>>> That's also a large hammer as it basically will mean no debug info after
>>>>>>>> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>>>>>>>> quite some work, perhaps your hack is good enough for the time being,
>>>>>>>> though I hate it :)
>>>>>>>
>>>>>>> I got it. Then I'll keep the patch as it is (remove the
>>>>>>> LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
>>>>>>> then we should be good to check in?
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Dehao
>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Ciao,
>>>>>>>> Michael.
Dehao Chen Sept. 13, 2012, 4:11 p.m. UTC | #24
On Thu, Sep 13, 2012 at 8:02 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Sep 12, 2012 at 6:39 PM, Xinliang David Li <davidxl@google.com> wrote:
>> On Wed, Sep 12, 2012 at 2:13 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Wed, Sep 12, 2012 at 7:06 AM, Dehao Chen <dehao@google.com> wrote:
>>>> Now I think we are facing a more complex problem. The data structure
>>>> we use to store the location_adhoc_data are file-static in linemap.c
>>>> in libcpp. These data structures are not guarded by GTY(()).
>>>> Meanwhile, as we have removed the block data structure from
>>>> gimple.gsbase as well as tree.exp (encoding them into an location_t).
>>>> This could cause block being GCed and the LOCATION_BLOCK becoming
>>>> dangling pointers.
>>>
>>> Uh.  Note that it is quite important that we are able to garbage-collect unused
>>> BLOCKs, this is the whole point of removing unused BLOCK scopes in
>>> remove_unused_locals.  So this indeed becomes much more complicated ...
>>> What would be desired is that the garbage collector can NULL an entry in
>>> the mapping table when it is not referenced in any other way (that other
>>> reference would be the BLOCK tree as stored in a FUNCTION_DECLs DECL_INITIAL).
>>
>> It would be nice to GC those unused BLOCKS. I wonder how many BLOCKS
>> are created for a large C++ program. This patch saves memory by
>> shrinking tree size, is it a net win or loss without GC those BLOCKS?
>
> Memory usage issues pop up with C++ code using expression templates
> (try BOOST MPL or tramp3d or some larger spirit testcases).  Inlining

I compared the memory consumption for tramp3d, the patched version has
a peak of 504065kB, while non-patched version has a peak of 491853kB.

> creates tons of "empty" BLOCK trees that just wrap others.  It is important
> to be able to GC those.  Now, it might be that no expression / location
> which references the BLOCK survives, and if the line-table is not scanned

Those non-used blocks will still be GCed in this patch.

> by GC then we will just end up with never re-usable entries (the BLOCK address
> may get re-used - can we get false sharing here?)

That is true (memory wasted). However, in the tramp3d case, only
409600 entries are allocated in location_adhoc_data (4.9MB, 1% of the
peak mem consumption). Thus the wasted entry should not be
significant.

Concerning re-used BLOCK, if the block address and the location are
the same, the previously allocated entry will be reused. But it'll not
affect the correctness.

Thanks,
Dehao

>
> Richard.
>
>> thanks,
>>
>> David
>>
>>
>>>
>>>> I tried to manipulate GTY to make it recognize the LOCATION_BLOCK from
>>>> gimple.gsbase.location. However, neigher nested_ptr nor mark_hook can
>>>> help me.
>>>>
>>>> Another approach would be guard the location_adhoc_data and related
>>>> data structures in GTY(()). However, this is non-trivial because tree
>>>> is not visible in libcpp. At the same time, my implementation heavily
>>>> relies on hashtable to make the code efficient, thus it's quite tricky
>>>> to make "param_is" and "use_params" work.
>>>>
>>>> The final approach, which I'll try tomorrow, would be move all my
>>>> implementation from libcpp to gcc, and guard them with GTY(()). I
>>>> still haven't thought of any potential problem of this approach. Any
>>>> comments?
>>>
>>> I think moving the mapping to GC in a lazy manner as I described above
>>> would be the way to go.  For hashtables GC already supports if_marked,
>>> not sure if similar support is available for arrays/vecs.
>>>
>>> Richard.
>>>
>>>> Thanks,
>>>> Dehao
>>>>
>>>> On Tue, Sep 11, 2012 at 9:00 AM, Dehao Chen <dehao@google.com> wrote:
>>>>> I saw comments in tree-streamer-out.c:
>>>>>
>>>>>   /* Do not stream BLOCK_SOURCE_LOCATION.  We cannot handle debug information
>>>>>      for early inlining so drop it on the floor instead of ICEing in
>>>>>      dwarf2out.c.  */
>>>>>   streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
>>>>>
>>>>> However, what the code is doing seemed contradictory with the comment.
>>>>> Or am I missing something?
>>>>>
>>>>>
>>>>>
>>>>> On Tue, Sep 11, 2012 at 8:32 AM, Michael Matz <matz@suse.de> wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On Tue, 11 Sep 2012, Dehao Chen wrote:
>>>>>>
>>>>>>> Looks like we have two choices:
>>>>>>>
>>>>>>> 1. Stream out block info, and use LTO_SET_PREVAIL for TREE_CHAIN(t)
>>>>>>
>>>>>> This will actually not work correctly in some cases.  The problem is, if
>>>>>> the prevailing decl is already part of another chain (say in another
>>>>>> block_var list) you would break the current chain.  Hence block vars need
>>>>>> special handling in the lto streamer (another reason why tree_chain is not
>>>>>> the most clever think to use for this chain).  This problem area needs to
>>>>>> be solved somehow if block info is to be preserved correctly.
>>>>>>
>>>>>>> 2. Don't stream out block info for LTO, and still call LTO_NO_PREVAIL
>>>>>>> (TREE_CHAIN (t)).
>>>>>>
>>>>>> That's also a large hammer as it basically will mean no debug info after
>>>>>> LTO :-/ Sigh, at this point I have no good solution that doesn't involve
>>>>>> quite some work, perhaps your hack is good enough for the time being,
>>>>>> though I hate it :)
>>>>>
>>>>> I got it. Then I'll keep the patch as it is (remove the
>>>>> LTO_NO_PREVAIL), and work with Honza to resolve the issue he had, and
>>>>> then we should be good to check in?
>>>>>
>>>>> Thanks,
>>>>> Dehao
>>>>>
>>>>>>
>>>>>>
>>>>>> Ciao,
>>>>>> Michael.
diff mbox

Patch

--- gcc/lto/lto.c	(revision 191083)
+++ gcc/lto/lto.c	(working copy)
@@ -1559,8 +1559,6 @@  lto_fixup_prevailing_decls (tree t)
 {
   enum tree_code code = TREE_CODE (t);
   LTO_NO_PREVAIL (TREE_TYPE (t));
-  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
-    LTO_NO_PREVAIL (TREE_CHAIN (t));
   if (DECL_P (t))
     {
       LTO_NO_PREVAIL (DECL_NAME (t));

Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c	(revision 191083)
+++ gcc/tree-cfg.c	(working copy)
@@ -5980,9 +5974,21 @@  move_stmt_op (tree *tp, int *walk_subtrees, void *
   tree t = *tp;

   if (EXPR_P (t))
-    /* We should never have TREE_BLOCK set on non-statements.  */
-    gcc_assert (!TREE_BLOCK (t));
-
+    {
+      tree block = TREE_BLOCK (t);
+      if (p->orig_block == NULL_TREE
+	  || block == p->orig_block
+	  || block == NULL_TREE)
+	TREE_SET_BLOCK (t, p->new_block);
+#ifdef ENABLE_CHECKING
+      else if (block != p->new_block)
+	{
+	  while (block && block != p->orig_block)
+	    block = BLOCK_SUPERCONTEXT (block);
+	  gcc_assert (block);
+	}
+#endif
+    }
   else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
     {
       if (TREE_CODE (t) == SSA_NAME)