public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Combine location with block using block_locations
@ 2012-08-01  5:36 Dehao Chen
  2012-08-01 18:07 ` Richard Guenther
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-08-01  5:36 UTC (permalink / raw)
  To: gcc-patches
  Cc: Richard Guenther, Dodji Seketeli, Jakub Jelinek, Jan Hubicka, David Li

Hi,

This patch:

* Integrates location with block into an integrated index.
* Removes gimple->gsbase.block and tree->exp.block fields.
* Updates inline/clone as well as tree liveness analysis to ensure the
associated blocks are updated correctly.

With this patch, the association between source location and its block
are greatly enhanced, which produces much better inline stack in the
debug info.

Bootstrapped and regression tested on x86.

OK for trunk?

Thanks,
Dehao

You can also find the patch in http://codereview.appspot.com/6454077

gcc/ChangeLog
2012-08-01  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.
	* dewarf2out.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.
	* lto/lto.c (lto_fixup_prevailing_decls): 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.
	* 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.

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

	* include/line-map.h (MAX_SOURCE_LOCATION): New value.
	(location_block_init): New.
	(location_block_fini): New.
	(get_combine_location): New.
	(get_block_from_location): New.
	(get_locus_from_location): New.
	(COMBINE_LOCATION): New.
	(IS_COMBINED_LOCATION): New.
	(expanded_location): New field.
	* line-map.c (location_block): New.
	(location_block_htab): New.
	(curr_combined_location): New.
	(location_blocks): New.
	(allocated_location_blocks): New.
	(location_block_hash): New.
	(location_block_eq): New.
	(location_block_update): New.
	(get_combine_location): New.
	(get_block_from_location): New.
	(get_locus_from_location): New.
	(location_block_init): New.
	(location_block_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/tree.c
===================================================================
--- gcc/tree.c	(revision 189835)
+++ gcc/tree.c	(working copy)
@@ -3765,7 +3765,6 @@
   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);
@@ -10867,17 +10866,28 @@
 }


-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 (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 189835)
+++ gcc/tree.h	(working copy)
@@ -999,7 +999,8 @@

 #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"

@@ -1702,7 +1703,7 @@
 #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)
@@ -1881,7 +1882,7 @@
 					      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.
@@ -1972,7 +1973,6 @@
 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];
@@ -5164,7 +5164,7 @@
 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
@@ -5539,7 +5539,8 @@
 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 189835)
+++ gcc/final.c	(working copy)
@@ -1605,7 +1605,7 @@
 					     insn_scope (XVECEXP (body, 0, i)));
 	}
       if (! this_block)
-	continue;
+	this_block = DECL_INITIAL (cfun->decl);

       if (this_block != cur_block)
 	{
@@ -1640,8 +1640,8 @@

   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 189835)
+++ gcc/input.c	(working copy)
@@ -51,6 +51,13 @@
   expanded_location xloc;
   const struct line_map *map;
   enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
+  tree block = NULL;
+
+  if (IS_COMBINED_LOCATION (loc))
+    {
+      block = LOCATION_BLOCK (loc);
+      loc = LOCATION_LOCUS (loc);
+    }

   memset (&xloc, 0, sizeof (xloc));

@@ -74,6 +81,7 @@
       xloc = linemap_expand_location (line_table, map, loc);
     }

+  xloc.block = block;
   if (loc <= BUILTINS_LOCATION)
     xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");

Index: gcc/input.h
===================================================================
--- gcc/input.h	(revision 189835)
+++ gcc/input.h	(working copy)
@@ -51,6 +51,14 @@
 #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_COMBINED_LOCATION(LOC)) ? get_locus_from_location (LOC) : (LOC))
+#define LOCATION_BLOCK(LOC) \
+  ((tree) ((IS_COMBINED_LOCATION (LOC)) ? get_block_from_location (LOC) \
+  : NULL))
+#define IS_UNKNOWN_LOCATION(LOC) \
+  ((IS_COMBINED_LOCATION (LOC)) ? get_locus_from_location (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 189835)
+++ gcc/fold-const.c	(working copy)
@@ -145,7 +145,7 @@
 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 189835)
+++ gcc/toplev.c	(working copy)
@@ -1140,6 +1140,7 @@
   linemap_init (line_table);
   line_table->reallocator = realloc_for_line_map;
   line_table->round_alloc_size = ggc_round_alloc_size;
+  location_block_init ();
   init_ttree ();

   /* Initialize register usage now so switches may override.  */
@@ -1946,6 +1947,7 @@
   invoke_plugin_callbacks (PLUGIN_FINISH, NULL);

   finalize_plugins ();
+  location_block_fini ();
   if (seen_error ())
     return (FATAL_EXIT_CODE);

Index: gcc/reorg.c
===================================================================
--- gcc/reorg.c	(revision 189835)
+++ gcc/reorg.c	(working copy)
@@ -545,7 +545,7 @@
   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 @@

       /* 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)
 	{
@@ -4087,7 +4087,7 @@
     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 189835)
+++ gcc/modulo-sched.c	(working copy)
@@ -1246,9 +1246,9 @@
 /* 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 @@
 	  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 @@
 	  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 @@
 	  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 @@
 	{
 	  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 @@
 	  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 @@

       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 @@

           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 189835)
+++ gcc/lto-streamer-out.c	(working copy)
@@ -155,6 +155,7 @@
 {
   expanded_location xloc;

+  loc = LOCATION_LOCUS (loc);
   bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
   if (loc == UNKNOWN_LOCATION)
     return;
Index: gcc/jump.c
===================================================================
--- gcc/jump.c	(revision 189835)
+++ gcc/jump.c	(working copy)
@@ -1818,8 +1818,7 @@
 	  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/ifcvt.c
===================================================================
--- gcc/ifcvt.c	(revision 189835)
+++ gcc/ifcvt.c	(working copy)
@@ -1019,7 +1019,7 @@
 	    return FALSE;

 	  emit_insn_before_setloc (seq, if_info->jump,
-				   INSN_LOCATOR (if_info->insn_a));
+				   INSN_LOCATION (if_info->insn_a));
 	}
       return TRUE;
     }
@@ -1064,7 +1064,7 @@
 	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
@@ -1195,7 +1195,7 @@
 	return FALSE;

       emit_insn_before_setloc (seq, if_info->jump,
-			       INSN_LOCATOR (if_info->insn_a));
+			       INSN_LOCATION (if_info->insn_a));
       return TRUE;
     }

@@ -1243,7 +1243,7 @@
 		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 ();
@@ -1283,7 +1283,7 @@
 		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 ();
@@ -1332,7 +1332,7 @@
 	    return FALSE;

 	  emit_insn_before_setloc (seq, if_info->jump,
-				   INSN_LOCATOR (if_info->insn_a));
+				   INSN_LOCATION (if_info->insn_a));
 	  return TRUE;
 	}

@@ -1481,7 +1481,7 @@
 	    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
@@ -1682,7 +1682,7 @@
   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:
@@ -1929,7 +1929,7 @@
   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;

@@ -2076,7 +2076,7 @@
   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;

@@ -2155,7 +2155,7 @@
   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;
 }

@@ -2255,7 +2255,7 @@
 	return FALSE;

       emit_insn_before_setloc (seq, if_info->jump,
-			       INSN_LOCATOR (if_info->insn_a));
+			       INSN_LOCATION (if_info->insn_a));
     }
   return TRUE;
 }
@@ -2656,7 +2656,7 @@
       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
@@ -2937,7 +2937,7 @@
       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)
     {
@@ -3655,7 +3655,7 @@
     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/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 189835)
+++ gcc/dwarf2out.c	(working copy)
@@ -15506,7 +15506,7 @@
 {
   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 189835)
+++ gcc/expr.c	(working copy)
@@ -7802,19 +7802,14 @@
   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);
-
-      /* Record where the insns produced belong.  */
-      set_curr_insn_block (TREE_BLOCK (exp));
+      set_curr_insn_location (input_location);

       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/predict.c
===================================================================
--- gcc/predict.c	(revision 189835)
+++ gcc/predict.c	(working copy)
@@ -2177,7 +2177,7 @@
 {
   unsigned nb_loops;

-  loop_optimizer_init (0);
+  loop_optimizer_init (LOOPS_NORMAL);
   if (dump_file && (dump_flags & TDF_DETAILS))
     flow_loops_dump (dump_file, NULL, 0);

Index: gcc/tree-parloops.c
===================================================================
--- gcc/tree-parloops.c	(revision 189835)
+++ gcc/tree-parloops.c	(working copy)
@@ -1415,6 +1415,7 @@
   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 189835)
+++ gcc/recog.c	(working copy)
@@ -3333,7 +3333,7 @@
   /* 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 189835)
+++ gcc/function.c	(working copy)
@@ -133,7 +133,7 @@
 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;
 \f
 /* Stack of nested functions.  */
 /* Keep track of the cfun stack.  */
@@ -200,7 +200,6 @@
   f->cfg = NULL;

   regno_reg_rtx = NULL;
-  insn_locators_free ();
 }
 \f
 /* Return size needed for stack frame based on slots so far allocated.
@@ -4979,7 +4978,7 @@
 	      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 @@

   /* 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 @@
   *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 @@
       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 @@

       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 @@

       /* 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 @@
 	     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 189835)
+++ gcc/print-rtl.c	(working copy)
@@ -416,10 +416,10 @@
 	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 @@
 	  {
 #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 189835)
+++ gcc/profile.c	(working copy)
@@ -966,7 +966,7 @@
 	     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))
@@ -976,7 +976,6 @@
 	      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)
@@ -1188,7 +1187,7 @@

 	  /* 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 189835)
+++ gcc/trans-mem.c	(working copy)
@@ -3796,7 +3796,6 @@
 	    {
 	      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 189835)
+++ gcc/gimplify.c	(working copy)
@@ -2600,7 +2600,6 @@
 	    = 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 189835)
+++ gcc/except.c	(working copy)
@@ -526,7 +526,10 @@
       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 189835)
+++ gcc/emit-rtl.c	(working copy)
@@ -3634,7 +3634,7 @@
 	}
     }

-  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)
@@ -3670,7 +3670,7 @@
   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
@@ -3703,7 +3703,7 @@
   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;
@@ -3723,7 +3723,7 @@
   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;
@@ -3743,7 +3743,7 @@
   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;
@@ -4416,8 +4416,8 @@
   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);
@@ -4440,62 +4440,62 @@
       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)
 {
@@ -4525,8 +4525,8 @@
     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);
@@ -4550,7 +4550,7 @@
       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,
@@ -4558,7 +4558,7 @@
                                       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)
 {
@@ -4566,14 +4566,14 @@
 				     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)
 {
@@ -4581,7 +4581,7 @@
 				     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)
 {
@@ -4589,7 +4589,7 @@
 			      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)
 {
@@ -4598,7 +4598,7 @@
 }

 /* 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)
 {
@@ -4606,7 +4606,7 @@
 			      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)
 {
@@ -4615,7 +4615,7 @@
 }

 /* 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)
 {
@@ -5865,7 +5865,7 @@
   /* 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,
@@ -5900,250 +5900,66 @@
 	    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_O(location_t);
-DEF_VEC_ALLOC_O(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)
-{
-  if (curr_rtl_loc >= 0)
-    epilogue_locator = curr_insn_locator ();
-  curr_rtl_loc = -1;
-}
-
-/* Allocate insn locator datastructure.  */
-void
-insn_locators_free (void)
+insn_locations_finalize (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);
+  epilogue_location = curr_location;
+  curr_location = UNKNOWN_LOCATION;
 }

 /* 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;
-}
-\f
-
-/* 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 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 LOCATION_BLOCK (INSN_LOCATION (insn));
 }

 /* Return line number of the statement that produced this insn.  */
 int
 insn_line (const_rtx insn)
 {
-  return locator_line (INSN_LOCATOR (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 LOCATION_LINE (INSN_LOCATION (insn));
 }

 /* 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);
-}
-\f
-
 /* 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 189835)
+++ gcc/cfgexpand.c	(working copy)
@@ -92,8 +92,7 @@
 	   && 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 @@

   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;
 }
@@ -1804,8 +1801,7 @@
   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;
@@ -1818,13 +1814,8 @@
       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;
@@ -1834,13 +1825,8 @@
       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;
@@ -1849,13 +1835,8 @@
   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;
@@ -1880,13 +1861,11 @@

   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;
 }
@@ -1986,7 +1965,6 @@
     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))
@@ -2021,8 +1999,7 @@
 {
   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))
     {
@@ -3766,8 +3743,7 @@
 	  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).  */
@@ -3800,8 +3776,7 @@
 		    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);
@@ -3828,8 +3803,7 @@
 		      }
 		  }
 	      }
-	  set_curr_insn_source_location (sloc);
-	  set_curr_insn_block (sblock);
+	  set_curr_insn_location (sloc);
 	}

       currently_expanding_gimple_stmt = stmt;
@@ -3844,8 +3818,7 @@
 	}
       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 (;;)
@@ -3867,8 +3840,7 @@

 	      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);
@@ -3906,13 +3878,11 @@
 		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;
@@ -3920,8 +3890,7 @@

 	  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);

@@ -3939,8 +3908,7 @@
 	      PAT_VAR_LOCATION_LOC (val) = (rtx)value;
 	    }

-	  set_curr_insn_source_location (sloc);
-	  set_curr_insn_block (sblock);
+	  set_curr_insn_location (sloc);
 	}
       else
 	{
@@ -3981,13 +3949,8 @@
   /* 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));
@@ -4107,12 +4070,9 @@

   /* 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 ();

@@ -4331,20 +4291,19 @@

   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 ();
@@ -4514,8 +4473,7 @@
   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 189835)
+++ gcc/cfgcleanup.c	(working copy)
@@ -481,13 +481,15 @@
 		  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 @@
 			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 189835)
+++ gcc/tree-ssa-live.c	(working copy)
@@ -587,7 +587,7 @@
    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;
@@ -615,7 +615,7 @@
   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);
@@ -765,13 +765,18 @@
           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, global_unused_vars);
             }
         }

       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 189835)
+++ gcc/lto/lto.c	(working copy)
@@ -1603,7 +1603,6 @@
   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/rtl.c
===================================================================
--- gcc/rtl.c	(revision 189835)
+++ gcc/rtl.c	(working copy)
@@ -440,7 +440,7 @@
 #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;
@@ -579,7 +579,7 @@
 #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 189835)
+++ gcc/rtl.h	(working copy)
@@ -739,6 +739,7 @@
 #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)
@@ -802,13 +803,13 @@
 /* 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.  */
@@ -1807,12 +1808,8 @@
 /* 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);
@@ -2648,14 +2645,10 @@
 /* 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 189835)
+++ gcc/tree-inline.c	(working copy)
@@ -852,10 +852,6 @@
       /* 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);
@@ -901,13 +897,9 @@
 	{
 	  /* 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,
@@ -919,6 +911,22 @@
 	}
     }

+  /* 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;
 }
@@ -1144,11 +1152,10 @@
 	      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)
@@ -2020,6 +2027,7 @@
 	      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
@@ -2031,9 +2039,7 @@

 	      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.  */
@@ -2046,8 +2052,19 @@
 		  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 (locus, block));
 	    }
 	}
     }
@@ -3946,7 +3963,8 @@
   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 189835)
+++ gcc/tree-streamer-in.c	(working copy)
@@ -776,7 +776,7 @@

   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 189835)
+++ gcc/combine.c	(working copy)
@@ -2896,7 +2896,7 @@

 	  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 189835)
+++ gcc/tree-outof-ssa.c	(working copy)
@@ -108,8 +108,7 @@
 {
   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 @@
 		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 @@
   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 @@
   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 @@
   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 @@
   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 189835)
+++ gcc/basic-block.h	(working copy)
@@ -47,8 +47,7 @@
   /* Auxiliary info specific to a pass.  */
   PTR GTY ((skip (""))) 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 189835)
+++ gcc/gimple.h	(working copy)
@@ -210,10 +210,6 @@
      and the prev pointer being the last.  */
   gimple next;
   gimple GTY((skip)) prev;
-
-  /* [ WORD 6 ]
-     Lexical block holding this statement.  */
-  tree block;
 };


@@ -1198,7 +1194,7 @@
 static inline tree
 gimple_block (const_gimple g)
 {
-  return g->gsbase.block;
+  return LOCATION_BLOCK (g->gsbase.location);
 }


@@ -1207,7 +1203,7 @@
 static inline void
 gimple_set_block (gimple g, tree block)
 {
-  g->gsbase.block = block;
+  g->gsbase.location = COMBINE_LOCATION (g->gsbase.location, block);
 }


@@ -1242,7 +1238,7 @@
 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 189835)
+++ gcc/tree-cfg.c	(working copy)
@@ -808,15 +808,11 @@
   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.  */
@@ -1026,8 +1022,6 @@
       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;
     }
@@ -1501,7 +1495,7 @@

   /* 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;
@@ -5987,9 +5981,7 @@
   tree t = *tp;

   if (EXPR_P (t))
-    /* We should never have TREE_BLOCK set on non-statements.  */
-    gcc_assert (!TREE_BLOCK (t));
-
+    ;
   else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
     {
       if (TREE_CODE (t) == SSA_NAME)
@@ -6294,12 +6286,12 @@
     }

   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 (e->goto_locus, d->new_block);
 #ifdef ENABLE_CHECKING
 	else if (block != d->new_block)
 	  {
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	(revision 189835)
+++ gcc/config/alpha/alpha.c	(working copy)
@@ -8352,7 +8352,6 @@
      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 189835)
+++ gcc/config/sparc/sparc.c	(working copy)
@@ -10654,7 +10654,6 @@
      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 189835)
+++ gcc/config/i386/i386.c	(working copy)
@@ -33063,7 +33063,6 @@
   /* 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 189835)
+++ gcc/config/tilegx/tilegx.c	(working copy)
@@ -4804,7 +4804,6 @@
      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 189835)
+++ gcc/config/sh/sh.c	(working copy)
@@ -11979,7 +11979,6 @@
      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 189835)
+++ gcc/config/ia64/ia64.c	(working copy)
@@ -10848,7 +10848,6 @@
      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 189835)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -21664,7 +21664,6 @@
      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 189835)
+++ gcc/config/score/score.c	(working copy)
@@ -505,7 +505,6 @@
   /* 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 189835)
+++ gcc/config/tilepro/tilepro.c	(working copy)
@@ -4407,7 +4407,6 @@
      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 189835)
+++ gcc/config/mips/mips.c	(working copy)
@@ -15637,7 +15637,6 @@
   /* 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 ();
   shorten_branches (insn);
Index: gcc/cfgrtl.c
===================================================================
--- gcc/cfgrtl.c	(revision 189835)
+++ gcc/cfgrtl.c	(working copy)
@@ -720,19 +720,19 @@
 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 @@
       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 @@
     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
@@ -1478,7 +1478,7 @@
   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;
@@ -3337,7 +3337,8 @@
         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;
@@ -3347,15 +3348,15 @@
 	      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;
@@ -3371,24 +3372,24 @@
 		  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);
@@ -4088,7 +4089,7 @@
     }

   /* 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 189835)
+++ gcc/stmt.c	(working copy)
@@ -2397,7 +2397,7 @@
 		 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.  */
@@ -2521,7 +2521,7 @@
 	      /* 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 189835)
+++ libcpp/include/line-map.h	(working copy)
@@ -89,7 +89,7 @@

 /* 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 @@
 #define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
   LINEMAPS_LAST_ALLOCATED_MAP (SET, true)

+extern void location_block_init (void);
+extern void location_block_fini (void);
+extern source_location get_combine_location (source_location, void *);
+extern void *get_block_from_location (source_location);
+extern source_location get_locus_from_location (source_location);
+
+#define COMBINE_LOCATION(LOC, BLOCK) \
+  ((BLOCK) ? get_combine_location ((LOC), (BLOCK)) : (LOC))
+#define IS_COMBINED_LOCATION(LOC) (((LOC) & MAX_SOURCE_LOCATION) != (LOC))
+
 /* Initialize a line map set.  */
 extern void linemap_init (struct line_maps *);

@@ -594,6 +604,8 @@

   int column;

+  void *block;
+
   /* In a system header?. */
   bool sysp;
 } expanded_location;
Index: libcpp/line-map.c
===================================================================
--- libcpp/line-map.c	(revision 189835)
+++ libcpp/line-map.c	(working copy)
@@ -25,6 +25,7 @@
 #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,121 @@
 extern unsigned num_expanded_macros_counter;
 extern unsigned num_macro_tokens_counter;

+struct location_block {
+  source_location locus;
+  void *block;
+};
+
+static htab_t location_block_htab;
+static source_location curr_combined_location;
+static struct location_block *location_blocks;
+static unsigned int allocated_location_blocks;
+
+/* Hash function for location_block hashtable.  */
+
+static hashval_t
+location_block_hash (const void *l)
+{
+  const struct location_block *lb = (const struct location_block *) l;
+  return (hashval_t) lb->locus + (size_t) &lb->block;
+}
+
+/* Compare function for location_block hashtable.  */
+
+static int
+location_block_eq (const void *l1, const void *l2)
+{
+  const struct location_block *lb1 = (const struct location_block *) l1;
+  const struct location_block *lb2 = (const struct location_block *) l2;
+  return lb1->locus == lb2->locus && lb1->block == lb2->block;
+}
+
+/* Update the hashtable when location_blocks is reallocated.  */
+
+static int
+location_block_update (void **slot, void *data)
+{
+  *((char **) slot) += ((char *) location_blocks - (char *) data);
+  return 1;
+}
+
+/* Combine LOCUS and BLOCK to a combined location.  */
+
+source_location
+get_combine_location (source_location locus, void *block)
+{
+  struct location_block lb;
+  struct location_block **slot;
+
+  linemap_assert (block);
+
+  if (IS_COMBINED_LOCATION (locus))
+    locus = location_blocks[locus & MAX_SOURCE_LOCATION].locus;
+  if (locus == 0 && block == NULL)
+    return 0;
+  lb.locus = locus;
+  lb.block = block;
+  slot = (struct location_block **)
+      htab_find_slot (location_block_htab, &lb, INSERT);
+  if (*slot == NULL)
+    {
+      *slot = location_blocks + curr_combined_location;
+      location_blocks[curr_combined_location] = lb;
+      if (++curr_combined_location >= allocated_location_blocks)
+	{
+	  char *orig_location_blocks = (char *) location_blocks;
+	  allocated_location_blocks *= 2;
+	  location_blocks = XRESIZEVEC (struct location_block,
+				 	location_blocks,
+					allocated_location_blocks);
+	  htab_traverse (location_block_htab, location_block_update,
+			 orig_location_blocks);
+	}
+    }
+  return ((*slot) - location_blocks) | 0x80000000;
+}
+
+/* Return the block for LOCATION.  */
+
+void *
+get_block_from_location (source_location location)
+{
+  linemap_assert (IS_COMBINED_LOCATION (location));
+  return location_blocks[location & MAX_SOURCE_LOCATION].block;
+}
+
+/* Return the locus for LOCATION.  */
+
+source_location
+get_locus_from_location (source_location location)
+{
+  linemap_assert (IS_COMBINED_LOCATION (location));
+  return location_blocks[location & MAX_SOURCE_LOCATION].locus;
+}
+
+/* Initialize the location_block structure.  */
+
+void
+location_block_init (void)
+{
+  location_block_htab = htab_create (100, location_block_hash,
+				     location_block_eq, NULL);
+  curr_combined_location = 0;
+  allocated_location_blocks = 100;
+  location_blocks = XNEWVEC (struct location_block,
+			     allocated_location_blocks);
+}
+
+/* Finalize the location_block structure.  */
+
+void
+location_block_fini (void)
+{
+  allocated_location_blocks = 0;
+  XDELETEVEC (location_blocks);
+  htab_delete (location_block_htab);
+}
+
 /* Initialize a line map set.  */

 void
@@ -509,6 +625,8 @@
 const struct line_map*
 linemap_lookup (struct line_maps *set, source_location line)
 {
+  if (IS_COMBINED_LOCATION (line))
+    line = location_blocks[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 +643,9 @@
   unsigned int md, mn, mx;
   const struct line_map *cached, *result;

+  if (IS_COMBINED_LOCATION (line))
+    line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
+
   if (set ==  NULL || line < RESERVED_LOCATION_COUNT)
     return NULL;

@@ -570,6 +691,9 @@
   unsigned int md, mn, mx;
   const struct line_map *cached, *result;

+  if (IS_COMBINED_LOCATION (line))
+    line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));

   if (set ==  NULL)
@@ -648,6 +772,9 @@
 {
   unsigned token_no;

+  if (IS_COMBINED_LOCATION (location))
+    location = location_blocks[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 +799,9 @@
 {
   unsigned token_no;

+  if (IS_COMBINED_LOCATION (location))
+    location = location_blocks[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 +826,9 @@
 {
   const struct line_map *map = NULL;

+  if (IS_COMBINED_LOCATION (location))
+    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
   if (location < RESERVED_LOCATION_COUNT)
     return 0;

@@ -720,6 +853,9 @@
 {
   const struct line_map *map = NULL;

+  if (IS_COMBINED_LOCATION (location))
+    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
   if (location < RESERVED_LOCATION_COUNT)
     return NULL;

@@ -754,6 +890,9 @@
 {
   const struct line_map *map = NULL;

+  if (IS_COMBINED_LOCATION (location))
+    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
   if (location < RESERVED_LOCATION_COUNT)
     return false;

@@ -793,6 +932,9 @@
 linemap_location_from_macro_expansion_p (struct line_maps *set,
 					 source_location location)
 {
+  if (IS_COMBINED_LOCATION (location))
+    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (location <= MAX_SOURCE_LOCATION
 		  && (set->highest_location
 		      < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
@@ -933,6 +1075,9 @@
 {
   struct line_map *map;

+  if (IS_COMBINED_LOCATION (location))
+    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);

   while (true)
@@ -967,6 +1112,9 @@
 {
   struct line_map *map;

+  if (IS_COMBINED_LOCATION (location))
+    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);

   while (true)
@@ -1005,6 +1153,9 @@
 {
   struct line_map *map;

+  if (IS_COMBINED_LOCATION (location))
+    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);

   while (true)
@@ -1074,6 +1225,9 @@
 			  enum location_resolution_kind lrk,
 			  const struct line_map **map)
 {
+  if (IS_COMBINED_LOCATION (loc))
+    loc = location_blocks[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 +1275,9 @@
   source_location resolved_location;
   const struct line_map *resolved_map;

+  if (IS_COMBINED_LOCATION (loc))
+    loc = location_blocks[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 +1314,9 @@
   source_location resolved_loc;
   const struct line_map *map0 = NULL, *map1 = NULL;

+  if (IS_COMBINED_LOCATION (loc))
+    loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+
   map0 = linemap_lookup (set, loc);
   if (!linemap_macro_expansion_map_p (map0))
     return loc;
@@ -1198,6 +1358,11 @@
   expanded_location xloc;

   memset (&xloc, 0, sizeof (xloc));
+  if (IS_COMBINED_LOCATION (loc))
+    {
+      loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+      xloc.block = location_blocks[loc & MAX_SOURCE_LOCATION].block;
+    }

   if (loc < RESERVED_LOCATION_COUNT)
     /* The location for this token wasn't generated from a line map.
@@ -1290,6 +1455,9 @@
   const char *path = "", *from = "";
   int l = -1, c = -1, s = -1, e = -1;

+  if (IS_COMBINED_LOCATION (loc))
+    loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+
   if (loc == 0)
     return;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-01  5:36 [PATCH] Combine location with block using block_locations Dehao Chen
@ 2012-08-01 18:07 ` Richard Guenther
  2012-08-02  3:23   ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-08-01 18:07 UTC (permalink / raw)
  To: Dehao Chen
  Cc: gcc-patches, Dodji Seketeli, Jakub Jelinek, Jan Hubicka, David Li

On Wed, Aug 1, 2012 at 7:35 AM, Dehao Chen <dehao@google.com> wrote:
> Hi,
>
> This patch:
>
> * Integrates location with block into an integrated index.
> * Removes gimple->gsbase.block and tree->exp.block fields.
> * Updates inline/clone as well as tree liveness analysis to ensure the
> associated blocks are updated correctly.
>
> With this patch, the association between source location and its block
> are greatly enhanced, which produces much better inline stack in the
> debug info.
>
> Bootstrapped and regression tested on x86.
>
> OK for trunk?

Nice.  But the LTO changes mean that you simply drop all BLOCK
associations on the floor ...
they at least look very incomplete.  Did you actually run LTO tests?

lto/ has its own ChangeLog and I wonder why no frontends are affected
by this patch?

Richard.

> Thanks,
> Dehao
>
> You can also find the patch in http://codereview.appspot.com/6454077
>
> gcc/ChangeLog
> 2012-08-01  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.
>         * dewarf2out.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.
>         * lto/lto.c (lto_fixup_prevailing_decls): 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.
>         * 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.
>
> libcpp/ChangeLog
> 2012-08-01  Dehao Chen  <dehao@google.com>
>
>         * include/line-map.h (MAX_SOURCE_LOCATION): New value.
>         (location_block_init): New.
>         (location_block_fini): New.
>         (get_combine_location): New.
>         (get_block_from_location): New.
>         (get_locus_from_location): New.
>         (COMBINE_LOCATION): New.
>         (IS_COMBINED_LOCATION): New.
>         (expanded_location): New field.
>         * line-map.c (location_block): New.
>         (location_block_htab): New.
>         (curr_combined_location): New.
>         (location_blocks): New.
>         (allocated_location_blocks): New.
>         (location_block_hash): New.
>         (location_block_eq): New.
>         (location_block_update): New.
>         (get_combine_location): New.
>         (get_block_from_location): New.
>         (get_locus_from_location): New.
>         (location_block_init): New.
>         (location_block_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/tree.c
> ===================================================================
> --- gcc/tree.c  (revision 189835)
> +++ gcc/tree.c  (working copy)
> @@ -3765,7 +3765,6 @@
>    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);
> @@ -10867,17 +10866,28 @@
>  }
>
>
> -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 (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 189835)
> +++ gcc/tree.h  (working copy)
> @@ -999,7 +999,8 @@
>
>  #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"
>
> @@ -1702,7 +1703,7 @@
>  #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)
> @@ -1881,7 +1882,7 @@
>                                               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.
> @@ -1972,7 +1973,6 @@
>  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];
> @@ -5164,7 +5164,7 @@
>  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
> @@ -5539,7 +5539,8 @@
>  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 189835)
> +++ gcc/final.c (working copy)
> @@ -1605,7 +1605,7 @@
>                                              insn_scope (XVECEXP (body, 0, i)));
>         }
>        if (! this_block)
> -       continue;
> +       this_block = DECL_INITIAL (cfun->decl);
>
>        if (this_block != cur_block)
>         {
> @@ -1640,8 +1640,8 @@
>
>    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 189835)
> +++ gcc/input.c (working copy)
> @@ -51,6 +51,13 @@
>    expanded_location xloc;
>    const struct line_map *map;
>    enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
> +  tree block = NULL;
> +
> +  if (IS_COMBINED_LOCATION (loc))
> +    {
> +      block = LOCATION_BLOCK (loc);
> +      loc = LOCATION_LOCUS (loc);
> +    }
>
>    memset (&xloc, 0, sizeof (xloc));
>
> @@ -74,6 +81,7 @@
>        xloc = linemap_expand_location (line_table, map, loc);
>      }
>
> +  xloc.block = block;
>    if (loc <= BUILTINS_LOCATION)
>      xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
>
> Index: gcc/input.h
> ===================================================================
> --- gcc/input.h (revision 189835)
> +++ gcc/input.h (working copy)
> @@ -51,6 +51,14 @@
>  #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_COMBINED_LOCATION(LOC)) ? get_locus_from_location (LOC) : (LOC))
> +#define LOCATION_BLOCK(LOC) \
> +  ((tree) ((IS_COMBINED_LOCATION (LOC)) ? get_block_from_location (LOC) \
> +  : NULL))
> +#define IS_UNKNOWN_LOCATION(LOC) \
> +  ((IS_COMBINED_LOCATION (LOC)) ? get_locus_from_location (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 189835)
> +++ gcc/fold-const.c    (working copy)
> @@ -145,7 +145,7 @@
>  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 189835)
> +++ gcc/toplev.c        (working copy)
> @@ -1140,6 +1140,7 @@
>    linemap_init (line_table);
>    line_table->reallocator = realloc_for_line_map;
>    line_table->round_alloc_size = ggc_round_alloc_size;
> +  location_block_init ();
>    init_ttree ();
>
>    /* Initialize register usage now so switches may override.  */
> @@ -1946,6 +1947,7 @@
>    invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
>
>    finalize_plugins ();
> +  location_block_fini ();
>    if (seen_error ())
>      return (FATAL_EXIT_CODE);
>
> Index: gcc/reorg.c
> ===================================================================
> --- gcc/reorg.c (revision 189835)
> +++ gcc/reorg.c (working copy)
> @@ -545,7 +545,7 @@
>    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 @@
>
>        /* 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)
>         {
> @@ -4087,7 +4087,7 @@
>      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 189835)
> +++ gcc/modulo-sched.c  (working copy)
> @@ -1246,9 +1246,9 @@
>  /* 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 @@
>           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 @@
>           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 @@
>           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 @@
>         {
>           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 @@
>           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 @@
>
>        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 @@
>
>            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 189835)
> +++ gcc/lto-streamer-out.c      (working copy)
> @@ -155,6 +155,7 @@
>  {
>    expanded_location xloc;
>
> +  loc = LOCATION_LOCUS (loc);
>    bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
>    if (loc == UNKNOWN_LOCATION)
>      return;
> Index: gcc/jump.c
> ===================================================================
> --- gcc/jump.c  (revision 189835)
> +++ gcc/jump.c  (working copy)
> @@ -1818,8 +1818,7 @@
>           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/ifcvt.c
> ===================================================================
> --- gcc/ifcvt.c (revision 189835)
> +++ gcc/ifcvt.c (working copy)
> @@ -1019,7 +1019,7 @@
>             return FALSE;
>
>           emit_insn_before_setloc (seq, if_info->jump,
> -                                  INSN_LOCATOR (if_info->insn_a));
> +                                  INSN_LOCATION (if_info->insn_a));
>         }
>        return TRUE;
>      }
> @@ -1064,7 +1064,7 @@
>         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
> @@ -1195,7 +1195,7 @@
>         return FALSE;
>
>        emit_insn_before_setloc (seq, if_info->jump,
> -                              INSN_LOCATOR (if_info->insn_a));
> +                              INSN_LOCATION (if_info->insn_a));
>        return TRUE;
>      }
>
> @@ -1243,7 +1243,7 @@
>                 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 ();
> @@ -1283,7 +1283,7 @@
>                 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 ();
> @@ -1332,7 +1332,7 @@
>             return FALSE;
>
>           emit_insn_before_setloc (seq, if_info->jump,
> -                                  INSN_LOCATOR (if_info->insn_a));
> +                                  INSN_LOCATION (if_info->insn_a));
>           return TRUE;
>         }
>
> @@ -1481,7 +1481,7 @@
>             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
> @@ -1682,7 +1682,7 @@
>    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:
> @@ -1929,7 +1929,7 @@
>    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;
>
> @@ -2076,7 +2076,7 @@
>    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;
>
> @@ -2155,7 +2155,7 @@
>    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;
>  }
>
> @@ -2255,7 +2255,7 @@
>         return FALSE;
>
>        emit_insn_before_setloc (seq, if_info->jump,
> -                              INSN_LOCATOR (if_info->insn_a));
> +                              INSN_LOCATION (if_info->insn_a));
>      }
>    return TRUE;
>  }
> @@ -2656,7 +2656,7 @@
>        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
> @@ -2937,7 +2937,7 @@
>        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)
>      {
> @@ -3655,7 +3655,7 @@
>      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/dwarf2out.c
> ===================================================================
> --- gcc/dwarf2out.c     (revision 189835)
> +++ gcc/dwarf2out.c     (working copy)
> @@ -15506,7 +15506,7 @@
>  {
>    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 189835)
> +++ gcc/expr.c  (working copy)
> @@ -7802,19 +7802,14 @@
>    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);
> -
> -      /* Record where the insns produced belong.  */
> -      set_curr_insn_block (TREE_BLOCK (exp));
> +      set_curr_insn_location (input_location);
>
>        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/predict.c
> ===================================================================
> --- gcc/predict.c       (revision 189835)
> +++ gcc/predict.c       (working copy)
> @@ -2177,7 +2177,7 @@
>  {
>    unsigned nb_loops;
>
> -  loop_optimizer_init (0);
> +  loop_optimizer_init (LOOPS_NORMAL);
>    if (dump_file && (dump_flags & TDF_DETAILS))
>      flow_loops_dump (dump_file, NULL, 0);
>
> Index: gcc/tree-parloops.c
> ===================================================================
> --- gcc/tree-parloops.c (revision 189835)
> +++ gcc/tree-parloops.c (working copy)
> @@ -1415,6 +1415,7 @@
>    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 189835)
> +++ gcc/recog.c (working copy)
> @@ -3333,7 +3333,7 @@
>    /* 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 189835)
> +++ gcc/function.c      (working copy)
> @@ -133,7 +133,7 @@
>  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 @@
>    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 @@
>               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 @@
>
>    /* 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 @@
>    *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 @@
>        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 @@
>
>        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 @@
>
>        /* 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 @@
>              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 189835)
> +++ gcc/print-rtl.c     (working copy)
> @@ -416,10 +416,10 @@
>         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 @@
>           {
>  #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 189835)
> +++ gcc/profile.c       (working copy)
> @@ -966,7 +966,7 @@
>              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))
> @@ -976,7 +976,6 @@
>               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)
> @@ -1188,7 +1187,7 @@
>
>           /* 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 189835)
> +++ gcc/trans-mem.c     (working copy)
> @@ -3796,7 +3796,6 @@
>             {
>               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 189835)
> +++ gcc/gimplify.c      (working copy)
> @@ -2600,7 +2600,6 @@
>             = 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 189835)
> +++ gcc/except.c        (working copy)
> @@ -526,7 +526,10 @@
>        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 189835)
> +++ gcc/emit-rtl.c      (working copy)
> @@ -3634,7 +3634,7 @@
>         }
>      }
>
> -  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)
> @@ -3670,7 +3670,7 @@
>    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
> @@ -3703,7 +3703,7 @@
>    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;
> @@ -3723,7 +3723,7 @@
>    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;
> @@ -3743,7 +3743,7 @@
>    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;
> @@ -4416,8 +4416,8 @@
>    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);
> @@ -4440,62 +4440,62 @@
>        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)
>  {
> @@ -4525,8 +4525,8 @@
>      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);
> @@ -4550,7 +4550,7 @@
>        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,
> @@ -4558,7 +4558,7 @@
>                                        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)
>  {
> @@ -4566,14 +4566,14 @@
>                                      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)
>  {
> @@ -4581,7 +4581,7 @@
>                                      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)
>  {
> @@ -4589,7 +4589,7 @@
>                               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)
>  {
> @@ -4598,7 +4598,7 @@
>  }
>
>  /* 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)
>  {
> @@ -4606,7 +4606,7 @@
>                               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)
>  {
> @@ -4615,7 +4615,7 @@
>  }
>
>  /* 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)
>  {
> @@ -5865,7 +5865,7 @@
>    /* 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,
> @@ -5900,250 +5900,66 @@
>             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_O(location_t);
> -DEF_VEC_ALLOC_O(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)
> -{
> -  if (curr_rtl_loc >= 0)
> -    epilogue_locator = curr_insn_locator ();
> -  curr_rtl_loc = -1;
> -}
> -
> -/* Allocate insn locator datastructure.  */
> -void
> -insn_locators_free (void)
> +insn_locations_finalize (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);
> +  epilogue_location = curr_location;
> +  curr_location = UNKNOWN_LOCATION;
>  }
>
>  /* 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 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 LOCATION_BLOCK (INSN_LOCATION (insn));
>  }
>
>  /* Return line number of the statement that produced this insn.  */
>  int
>  insn_line (const_rtx insn)
>  {
> -  return locator_line (INSN_LOCATOR (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 LOCATION_LINE (INSN_LOCATION (insn));
>  }
>
>  /* 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 189835)
> +++ gcc/cfgexpand.c     (working copy)
> @@ -92,8 +92,7 @@
>            && 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 @@
>
>    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;
>  }
> @@ -1804,8 +1801,7 @@
>    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;
> @@ -1818,13 +1814,8 @@
>        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;
> @@ -1834,13 +1825,8 @@
>        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;
> @@ -1849,13 +1835,8 @@
>    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;
> @@ -1880,13 +1861,11 @@
>
>    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;
>  }
> @@ -1986,7 +1965,6 @@
>      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))
> @@ -2021,8 +1999,7 @@
>  {
>    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))
>      {
> @@ -3766,8 +3743,7 @@
>           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).  */
> @@ -3800,8 +3776,7 @@
>                     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);
> @@ -3828,8 +3803,7 @@
>                       }
>                   }
>               }
> -         set_curr_insn_source_location (sloc);
> -         set_curr_insn_block (sblock);
> +         set_curr_insn_location (sloc);
>         }
>
>        currently_expanding_gimple_stmt = stmt;
> @@ -3844,8 +3818,7 @@
>         }
>        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 (;;)
> @@ -3867,8 +3840,7 @@
>
>               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);
> @@ -3906,13 +3878,11 @@
>                 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;
> @@ -3920,8 +3890,7 @@
>
>           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);
>
> @@ -3939,8 +3908,7 @@
>               PAT_VAR_LOCATION_LOC (val) = (rtx)value;
>             }
>
> -         set_curr_insn_source_location (sloc);
> -         set_curr_insn_block (sblock);
> +         set_curr_insn_location (sloc);
>         }
>        else
>         {
> @@ -3981,13 +3949,8 @@
>    /* 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));
> @@ -4107,12 +4070,9 @@
>
>    /* 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 ();
>
> @@ -4331,20 +4291,19 @@
>
>    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 ();
> @@ -4514,8 +4473,7 @@
>    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 189835)
> +++ gcc/cfgcleanup.c    (working copy)
> @@ -481,13 +481,15 @@
>                   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 @@
>                         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 189835)
> +++ gcc/tree-ssa-live.c (working copy)
> @@ -587,7 +587,7 @@
>     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;
> @@ -615,7 +615,7 @@
>    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);
> @@ -765,13 +765,18 @@
>            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, global_unused_vars);
>              }
>          }
>
>        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 189835)
> +++ gcc/lto/lto.c       (working copy)
> @@ -1603,7 +1603,6 @@
>    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/rtl.c
> ===================================================================
> --- gcc/rtl.c   (revision 189835)
> +++ gcc/rtl.c   (working copy)
> @@ -440,7 +440,7 @@
>  #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;
> @@ -579,7 +579,7 @@
>  #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 189835)
> +++ gcc/rtl.h   (working copy)
> @@ -739,6 +739,7 @@
>  #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)
> @@ -802,13 +803,13 @@
>  /* 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.  */
> @@ -1807,12 +1808,8 @@
>  /* 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);
> @@ -2648,14 +2645,10 @@
>  /* 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 189835)
> +++ gcc/tree-inline.c   (working copy)
> @@ -852,10 +852,6 @@
>        /* 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);
> @@ -901,13 +897,9 @@
>         {
>           /* 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,
> @@ -919,6 +911,22 @@
>         }
>      }
>
> +  /* 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;
>  }
> @@ -1144,11 +1152,10 @@
>               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)
> @@ -2020,6 +2027,7 @@
>               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
> @@ -2031,9 +2039,7 @@
>
>               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.  */
> @@ -2046,8 +2052,19 @@
>                   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 (locus, block));
>             }
>         }
>      }
> @@ -3946,7 +3963,8 @@
>    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 189835)
> +++ gcc/tree-streamer-in.c      (working copy)
> @@ -776,7 +776,7 @@
>
>    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 189835)
> +++ gcc/combine.c       (working copy)
> @@ -2896,7 +2896,7 @@
>
>           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 189835)
> +++ gcc/tree-outof-ssa.c        (working copy)
> @@ -108,8 +108,7 @@
>  {
>    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 @@
>                 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 @@
>    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 @@
>    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 @@
>    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 @@
>    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 189835)
> +++ gcc/basic-block.h   (working copy)
> @@ -47,8 +47,7 @@
>    /* Auxiliary info specific to a pass.  */
>    PTR GTY ((skip (""))) 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 189835)
> +++ gcc/gimple.h        (working copy)
> @@ -210,10 +210,6 @@
>       and the prev pointer being the last.  */
>    gimple next;
>    gimple GTY((skip)) prev;
> -
> -  /* [ WORD 6 ]
> -     Lexical block holding this statement.  */
> -  tree block;
>  };
>
>
> @@ -1198,7 +1194,7 @@
>  static inline tree
>  gimple_block (const_gimple g)
>  {
> -  return g->gsbase.block;
> +  return LOCATION_BLOCK (g->gsbase.location);
>  }
>
>
> @@ -1207,7 +1203,7 @@
>  static inline void
>  gimple_set_block (gimple g, tree block)
>  {
> -  g->gsbase.block = block;
> +  g->gsbase.location = COMBINE_LOCATION (g->gsbase.location, block);
>  }
>
>
> @@ -1242,7 +1238,7 @@
>  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 189835)
> +++ gcc/tree-cfg.c      (working copy)
> @@ -808,15 +808,11 @@
>    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.  */
> @@ -1026,8 +1022,6 @@
>        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;
>      }
> @@ -1501,7 +1495,7 @@
>
>    /* 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;
> @@ -5987,9 +5981,7 @@
>    tree t = *tp;
>
>    if (EXPR_P (t))
> -    /* We should never have TREE_BLOCK set on non-statements.  */
> -    gcc_assert (!TREE_BLOCK (t));
> -
> +    ;
>    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
>      {
>        if (TREE_CODE (t) == SSA_NAME)
> @@ -6294,12 +6286,12 @@
>      }
>
>    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 (e->goto_locus, d->new_block);
>  #ifdef ENABLE_CHECKING
>         else if (block != d->new_block)
>           {
> Index: gcc/config/alpha/alpha.c
> ===================================================================
> --- gcc/config/alpha/alpha.c    (revision 189835)
> +++ gcc/config/alpha/alpha.c    (working copy)
> @@ -8352,7 +8352,6 @@
>       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 189835)
> +++ gcc/config/sparc/sparc.c    (working copy)
> @@ -10654,7 +10654,6 @@
>       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 189835)
> +++ gcc/config/i386/i386.c      (working copy)
> @@ -33063,7 +33063,6 @@
>    /* 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 189835)
> +++ gcc/config/tilegx/tilegx.c  (working copy)
> @@ -4804,7 +4804,6 @@
>       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 189835)
> +++ gcc/config/sh/sh.c  (working copy)
> @@ -11979,7 +11979,6 @@
>       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 189835)
> +++ gcc/config/ia64/ia64.c      (working copy)
> @@ -10848,7 +10848,6 @@
>       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 189835)
> +++ gcc/config/rs6000/rs6000.c  (working copy)
> @@ -21664,7 +21664,6 @@
>       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 189835)
> +++ gcc/config/score/score.c    (working copy)
> @@ -505,7 +505,6 @@
>    /* 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 189835)
> +++ gcc/config/tilepro/tilepro.c        (working copy)
> @@ -4407,7 +4407,6 @@
>       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 189835)
> +++ gcc/config/mips/mips.c      (working copy)
> @@ -15637,7 +15637,6 @@
>    /* 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 ();
>    shorten_branches (insn);
> Index: gcc/cfgrtl.c
> ===================================================================
> --- gcc/cfgrtl.c        (revision 189835)
> +++ gcc/cfgrtl.c        (working copy)
> @@ -720,19 +720,19 @@
>  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 @@
>        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 @@
>      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
> @@ -1478,7 +1478,7 @@
>    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;
> @@ -3337,7 +3337,8 @@
>          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;
> @@ -3347,15 +3348,15 @@
>               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;
> @@ -3371,24 +3372,24 @@
>                   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);
> @@ -4088,7 +4089,7 @@
>      }
>
>    /* 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 189835)
> +++ gcc/stmt.c  (working copy)
> @@ -2397,7 +2397,7 @@
>                  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.  */
> @@ -2521,7 +2521,7 @@
>               /* 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 189835)
> +++ libcpp/include/line-map.h   (working copy)
> @@ -89,7 +89,7 @@
>
>  /* 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 @@
>  #define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
>    LINEMAPS_LAST_ALLOCATED_MAP (SET, true)
>
> +extern void location_block_init (void);
> +extern void location_block_fini (void);
> +extern source_location get_combine_location (source_location, void *);
> +extern void *get_block_from_location (source_location);
> +extern source_location get_locus_from_location (source_location);
> +
> +#define COMBINE_LOCATION(LOC, BLOCK) \
> +  ((BLOCK) ? get_combine_location ((LOC), (BLOCK)) : (LOC))
> +#define IS_COMBINED_LOCATION(LOC) (((LOC) & MAX_SOURCE_LOCATION) != (LOC))
> +
>  /* Initialize a line map set.  */
>  extern void linemap_init (struct line_maps *);
>
> @@ -594,6 +604,8 @@
>
>    int column;
>
> +  void *block;
> +
>    /* In a system header?. */
>    bool sysp;
>  } expanded_location;
> Index: libcpp/line-map.c
> ===================================================================
> --- libcpp/line-map.c   (revision 189835)
> +++ libcpp/line-map.c   (working copy)
> @@ -25,6 +25,7 @@
>  #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,121 @@
>  extern unsigned num_expanded_macros_counter;
>  extern unsigned num_macro_tokens_counter;
>
> +struct location_block {
> +  source_location locus;
> +  void *block;
> +};
> +
> +static htab_t location_block_htab;
> +static source_location curr_combined_location;
> +static struct location_block *location_blocks;
> +static unsigned int allocated_location_blocks;
> +
> +/* Hash function for location_block hashtable.  */
> +
> +static hashval_t
> +location_block_hash (const void *l)
> +{
> +  const struct location_block *lb = (const struct location_block *) l;
> +  return (hashval_t) lb->locus + (size_t) &lb->block;
> +}
> +
> +/* Compare function for location_block hashtable.  */
> +
> +static int
> +location_block_eq (const void *l1, const void *l2)
> +{
> +  const struct location_block *lb1 = (const struct location_block *) l1;
> +  const struct location_block *lb2 = (const struct location_block *) l2;
> +  return lb1->locus == lb2->locus && lb1->block == lb2->block;
> +}
> +
> +/* Update the hashtable when location_blocks is reallocated.  */
> +
> +static int
> +location_block_update (void **slot, void *data)
> +{
> +  *((char **) slot) += ((char *) location_blocks - (char *) data);
> +  return 1;
> +}
> +
> +/* Combine LOCUS and BLOCK to a combined location.  */
> +
> +source_location
> +get_combine_location (source_location locus, void *block)
> +{
> +  struct location_block lb;
> +  struct location_block **slot;
> +
> +  linemap_assert (block);
> +
> +  if (IS_COMBINED_LOCATION (locus))
> +    locus = location_blocks[locus & MAX_SOURCE_LOCATION].locus;
> +  if (locus == 0 && block == NULL)
> +    return 0;
> +  lb.locus = locus;
> +  lb.block = block;
> +  slot = (struct location_block **)
> +      htab_find_slot (location_block_htab, &lb, INSERT);
> +  if (*slot == NULL)
> +    {
> +      *slot = location_blocks + curr_combined_location;
> +      location_blocks[curr_combined_location] = lb;
> +      if (++curr_combined_location >= allocated_location_blocks)
> +       {
> +         char *orig_location_blocks = (char *) location_blocks;
> +         allocated_location_blocks *= 2;
> +         location_blocks = XRESIZEVEC (struct location_block,
> +                                       location_blocks,
> +                                       allocated_location_blocks);
> +         htab_traverse (location_block_htab, location_block_update,
> +                        orig_location_blocks);
> +       }
> +    }
> +  return ((*slot) - location_blocks) | 0x80000000;
> +}
> +
> +/* Return the block for LOCATION.  */
> +
> +void *
> +get_block_from_location (source_location location)
> +{
> +  linemap_assert (IS_COMBINED_LOCATION (location));
> +  return location_blocks[location & MAX_SOURCE_LOCATION].block;
> +}
> +
> +/* Return the locus for LOCATION.  */
> +
> +source_location
> +get_locus_from_location (source_location location)
> +{
> +  linemap_assert (IS_COMBINED_LOCATION (location));
> +  return location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +}
> +
> +/* Initialize the location_block structure.  */
> +
> +void
> +location_block_init (void)
> +{
> +  location_block_htab = htab_create (100, location_block_hash,
> +                                    location_block_eq, NULL);
> +  curr_combined_location = 0;
> +  allocated_location_blocks = 100;
> +  location_blocks = XNEWVEC (struct location_block,
> +                            allocated_location_blocks);
> +}
> +
> +/* Finalize the location_block structure.  */
> +
> +void
> +location_block_fini (void)
> +{
> +  allocated_location_blocks = 0;
> +  XDELETEVEC (location_blocks);
> +  htab_delete (location_block_htab);
> +}
> +
>  /* Initialize a line map set.  */
>
>  void
> @@ -509,6 +625,8 @@
>  const struct line_map*
>  linemap_lookup (struct line_maps *set, source_location line)
>  {
> +  if (IS_COMBINED_LOCATION (line))
> +    line = location_blocks[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 +643,9 @@
>    unsigned int md, mn, mx;
>    const struct line_map *cached, *result;
>
> +  if (IS_COMBINED_LOCATION (line))
> +    line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
> +
>    if (set ==  NULL || line < RESERVED_LOCATION_COUNT)
>      return NULL;
>
> @@ -570,6 +691,9 @@
>    unsigned int md, mn, mx;
>    const struct line_map *cached, *result;
>
> +  if (IS_COMBINED_LOCATION (line))
> +    line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
> +
>    linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
>
>    if (set ==  NULL)
> @@ -648,6 +772,9 @@
>  {
>    unsigned token_no;
>
> +  if (IS_COMBINED_LOCATION (location))
> +    location = location_blocks[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 +799,9 @@
>  {
>    unsigned token_no;
>
> +  if (IS_COMBINED_LOCATION (location))
> +    location = location_blocks[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 +826,9 @@
>  {
>    const struct line_map *map = NULL;
>
> +  if (IS_COMBINED_LOCATION (location))
> +    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>    if (location < RESERVED_LOCATION_COUNT)
>      return 0;
>
> @@ -720,6 +853,9 @@
>  {
>    const struct line_map *map = NULL;
>
> +  if (IS_COMBINED_LOCATION (location))
> +    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>    if (location < RESERVED_LOCATION_COUNT)
>      return NULL;
>
> @@ -754,6 +890,9 @@
>  {
>    const struct line_map *map = NULL;
>
> +  if (IS_COMBINED_LOCATION (location))
> +    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>    if (location < RESERVED_LOCATION_COUNT)
>      return false;
>
> @@ -793,6 +932,9 @@
>  linemap_location_from_macro_expansion_p (struct line_maps *set,
>                                          source_location location)
>  {
> +  if (IS_COMBINED_LOCATION (location))
> +    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>    linemap_assert (location <= MAX_SOURCE_LOCATION
>                   && (set->highest_location
>                       < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
> @@ -933,6 +1075,9 @@
>  {
>    struct line_map *map;
>
> +  if (IS_COMBINED_LOCATION (location))
> +    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>    linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
>
>    while (true)
> @@ -967,6 +1112,9 @@
>  {
>    struct line_map *map;
>
> +  if (IS_COMBINED_LOCATION (location))
> +    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>    linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
>
>    while (true)
> @@ -1005,6 +1153,9 @@
>  {
>    struct line_map *map;
>
> +  if (IS_COMBINED_LOCATION (location))
> +    location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>    linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
>
>    while (true)
> @@ -1074,6 +1225,9 @@
>                           enum location_resolution_kind lrk,
>                           const struct line_map **map)
>  {
> +  if (IS_COMBINED_LOCATION (loc))
> +    loc = location_blocks[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 +1275,9 @@
>    source_location resolved_location;
>    const struct line_map *resolved_map;
>
> +  if (IS_COMBINED_LOCATION (loc))
> +    loc = location_blocks[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 +1314,9 @@
>    source_location resolved_loc;
>    const struct line_map *map0 = NULL, *map1 = NULL;
>
> +  if (IS_COMBINED_LOCATION (loc))
> +    loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
> +
>    map0 = linemap_lookup (set, loc);
>    if (!linemap_macro_expansion_map_p (map0))
>      return loc;
> @@ -1198,6 +1358,11 @@
>    expanded_location xloc;
>
>    memset (&xloc, 0, sizeof (xloc));
> +  if (IS_COMBINED_LOCATION (loc))
> +    {
> +      loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
> +      xloc.block = location_blocks[loc & MAX_SOURCE_LOCATION].block;
> +    }
>
>    if (loc < RESERVED_LOCATION_COUNT)
>      /* The location for this token wasn't generated from a line map.
> @@ -1290,6 +1455,9 @@
>    const char *path = "", *from = "";
>    int l = -1, c = -1, s = -1, e = -1;
>
> +  if (IS_COMBINED_LOCATION (loc))
> +    loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
> +
>    if (loc == 0)
>      return;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-01 18:07 ` Richard Guenther
@ 2012-08-02  3:23   ` Dehao Chen
  2012-08-02 10:06     ` Richard Guenther
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-08-02  3:23 UTC (permalink / raw)
  To: Richard Guenther
  Cc: gcc-patches, Dodji Seketeli, Jakub Jelinek, Jan Hubicka, David Li

On Thu, Aug 2, 2012 at 2:07 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Aug 1, 2012 at 7:35 AM, Dehao Chen <dehao@google.com> wrote:
>> Hi,
>>
>> This patch:
>>
>> * Integrates location with block into an integrated index.
>> * Removes gimple->gsbase.block and tree->exp.block fields.
>> * Updates inline/clone as well as tree liveness analysis to ensure the
>> associated blocks are updated correctly.
>>
>> With this patch, the association between source location and its block
>> are greatly enhanced, which produces much better inline stack in the
>> debug info.
>>
>> Bootstrapped and regression tested on x86.
>>
>> OK for trunk?
>
> Nice.  But the LTO changes mean that you simply drop all BLOCK
> associations on the floor ...

Why? I've invoked TREE_SET_BLOCK in tree-streamer-in.c to read in the
block info. So it should at least provide the same info as the
original impl.

> they at least look very incomplete.  Did you actually run LTO tests?

Thanks for the reminder, I've added the following change to this patch:

Index: gcc/tree-streamer-out.c
===================================================================
--- gcc/tree-streamer-out.c	(revision 189835)
+++ gcc/tree-streamer-out.c	(working copy)
@@ -471,7 +471,7 @@
 {
   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 @@
   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);
 }

I think BLOCK associations works fine for LTO. I've run check-gcc, and
there's no regression on LTO tests. I also manually write some tests,
and the generated final assembly has block info as expected.

>
> lto/ has its own ChangeLog

Thanks, I'll update the ChangeLog accordingly.

> and I wonder why no frontends are affected
> by this patch?

Which files are you referring to?

Thanks,
Dehao

>
> Richard.
>
>> Thanks,
>> Dehao
>>
>> You can also find the patch in http://codereview.appspot.com/6454077
>>
>> gcc/ChangeLog
>> 2012-08-01  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.
>>         * dewarf2out.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.
>>         * lto/lto.c (lto_fixup_prevailing_decls): 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.
>>         * 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.
>>
>> libcpp/ChangeLog
>> 2012-08-01  Dehao Chen  <dehao@google.com>
>>
>>         * include/line-map.h (MAX_SOURCE_LOCATION): New value.
>>         (location_block_init): New.
>>         (location_block_fini): New.
>>         (get_combine_location): New.
>>         (get_block_from_location): New.
>>         (get_locus_from_location): New.
>>         (COMBINE_LOCATION): New.
>>         (IS_COMBINED_LOCATION): New.
>>         (expanded_location): New field.
>>         * line-map.c (location_block): New.
>>         (location_block_htab): New.
>>         (curr_combined_location): New.
>>         (location_blocks): New.
>>         (allocated_location_blocks): New.
>>         (location_block_hash): New.
>>         (location_block_eq): New.
>>         (location_block_update): New.
>>         (get_combine_location): New.
>>         (get_block_from_location): New.
>>         (get_locus_from_location): New.
>>         (location_block_init): New.
>>         (location_block_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/tree.c
>> ===================================================================
>> --- gcc/tree.c  (revision 189835)
>> +++ gcc/tree.c  (working copy)
>> @@ -3765,7 +3765,6 @@
>>    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);
>> @@ -10867,17 +10866,28 @@
>>  }
>>
>>
>> -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 (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 189835)
>> +++ gcc/tree.h  (working copy)
>> @@ -999,7 +999,8 @@
>>
>>  #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"
>>
>> @@ -1702,7 +1703,7 @@
>>  #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)
>> @@ -1881,7 +1882,7 @@
>>                                               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.
>> @@ -1972,7 +1973,6 @@
>>  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];
>> @@ -5164,7 +5164,7 @@
>>  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
>> @@ -5539,7 +5539,8 @@
>>  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 189835)
>> +++ gcc/final.c (working copy)
>> @@ -1605,7 +1605,7 @@
>>                                              insn_scope (XVECEXP (body, 0, i)));
>>         }
>>        if (! this_block)
>> -       continue;
>> +       this_block = DECL_INITIAL (cfun->decl);
>>
>>        if (this_block != cur_block)
>>         {
>> @@ -1640,8 +1640,8 @@
>>
>>    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 189835)
>> +++ gcc/input.c (working copy)
>> @@ -51,6 +51,13 @@
>>    expanded_location xloc;
>>    const struct line_map *map;
>>    enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
>> +  tree block = NULL;
>> +
>> +  if (IS_COMBINED_LOCATION (loc))
>> +    {
>> +      block = LOCATION_BLOCK (loc);
>> +      loc = LOCATION_LOCUS (loc);
>> +    }
>>
>>    memset (&xloc, 0, sizeof (xloc));
>>
>> @@ -74,6 +81,7 @@
>>        xloc = linemap_expand_location (line_table, map, loc);
>>      }
>>
>> +  xloc.block = block;
>>    if (loc <= BUILTINS_LOCATION)
>>      xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
>>
>> Index: gcc/input.h
>> ===================================================================
>> --- gcc/input.h (revision 189835)
>> +++ gcc/input.h (working copy)
>> @@ -51,6 +51,14 @@
>>  #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_COMBINED_LOCATION(LOC)) ? get_locus_from_location (LOC) : (LOC))
>> +#define LOCATION_BLOCK(LOC) \
>> +  ((tree) ((IS_COMBINED_LOCATION (LOC)) ? get_block_from_location (LOC) \
>> +  : NULL))
>> +#define IS_UNKNOWN_LOCATION(LOC) \
>> +  ((IS_COMBINED_LOCATION (LOC)) ? get_locus_from_location (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 189835)
>> +++ gcc/fold-const.c    (working copy)
>> @@ -145,7 +145,7 @@
>>  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 189835)
>> +++ gcc/toplev.c        (working copy)
>> @@ -1140,6 +1140,7 @@
>>    linemap_init (line_table);
>>    line_table->reallocator = realloc_for_line_map;
>>    line_table->round_alloc_size = ggc_round_alloc_size;
>> +  location_block_init ();
>>    init_ttree ();
>>
>>    /* Initialize register usage now so switches may override.  */
>> @@ -1946,6 +1947,7 @@
>>    invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
>>
>>    finalize_plugins ();
>> +  location_block_fini ();
>>    if (seen_error ())
>>      return (FATAL_EXIT_CODE);
>>
>> Index: gcc/reorg.c
>> ===================================================================
>> --- gcc/reorg.c (revision 189835)
>> +++ gcc/reorg.c (working copy)
>> @@ -545,7 +545,7 @@
>>    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 @@
>>
>>        /* 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)
>>         {
>> @@ -4087,7 +4087,7 @@
>>      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 189835)
>> +++ gcc/modulo-sched.c  (working copy)
>> @@ -1246,9 +1246,9 @@
>>  /* 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 @@
>>           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 @@
>>           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 @@
>>           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 @@
>>         {
>>           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 @@
>>           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 @@
>>
>>        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 @@
>>
>>            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 189835)
>> +++ gcc/lto-streamer-out.c      (working copy)
>> @@ -155,6 +155,7 @@
>>  {
>>    expanded_location xloc;
>>
>> +  loc = LOCATION_LOCUS (loc);
>>    bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
>>    if (loc == UNKNOWN_LOCATION)
>>      return;
>> Index: gcc/jump.c
>> ===================================================================
>> --- gcc/jump.c  (revision 189835)
>> +++ gcc/jump.c  (working copy)
>> @@ -1818,8 +1818,7 @@
>>           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/ifcvt.c
>> ===================================================================
>> --- gcc/ifcvt.c (revision 189835)
>> +++ gcc/ifcvt.c (working copy)
>> @@ -1019,7 +1019,7 @@
>>             return FALSE;
>>
>>           emit_insn_before_setloc (seq, if_info->jump,
>> -                                  INSN_LOCATOR (if_info->insn_a));
>> +                                  INSN_LOCATION (if_info->insn_a));
>>         }
>>        return TRUE;
>>      }
>> @@ -1064,7 +1064,7 @@
>>         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
>> @@ -1195,7 +1195,7 @@
>>         return FALSE;
>>
>>        emit_insn_before_setloc (seq, if_info->jump,
>> -                              INSN_LOCATOR (if_info->insn_a));
>> +                              INSN_LOCATION (if_info->insn_a));
>>        return TRUE;
>>      }
>>
>> @@ -1243,7 +1243,7 @@
>>                 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 ();
>> @@ -1283,7 +1283,7 @@
>>                 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 ();
>> @@ -1332,7 +1332,7 @@
>>             return FALSE;
>>
>>           emit_insn_before_setloc (seq, if_info->jump,
>> -                                  INSN_LOCATOR (if_info->insn_a));
>> +                                  INSN_LOCATION (if_info->insn_a));
>>           return TRUE;
>>         }
>>
>> @@ -1481,7 +1481,7 @@
>>             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
>> @@ -1682,7 +1682,7 @@
>>    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:
>> @@ -1929,7 +1929,7 @@
>>    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;
>>
>> @@ -2076,7 +2076,7 @@
>>    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;
>>
>> @@ -2155,7 +2155,7 @@
>>    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;
>>  }
>>
>> @@ -2255,7 +2255,7 @@
>>         return FALSE;
>>
>>        emit_insn_before_setloc (seq, if_info->jump,
>> -                              INSN_LOCATOR (if_info->insn_a));
>> +                              INSN_LOCATION (if_info->insn_a));
>>      }
>>    return TRUE;
>>  }
>> @@ -2656,7 +2656,7 @@
>>        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
>> @@ -2937,7 +2937,7 @@
>>        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)
>>      {
>> @@ -3655,7 +3655,7 @@
>>      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/dwarf2out.c
>> ===================================================================
>> --- gcc/dwarf2out.c     (revision 189835)
>> +++ gcc/dwarf2out.c     (working copy)
>> @@ -15506,7 +15506,7 @@
>>  {
>>    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 189835)
>> +++ gcc/expr.c  (working copy)
>> @@ -7802,19 +7802,14 @@
>>    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);
>> -
>> -      /* Record where the insns produced belong.  */
>> -      set_curr_insn_block (TREE_BLOCK (exp));
>> +      set_curr_insn_location (input_location);
>>
>>        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/predict.c
>> ===================================================================
>> --- gcc/predict.c       (revision 189835)
>> +++ gcc/predict.c       (working copy)
>> @@ -2177,7 +2177,7 @@
>>  {
>>    unsigned nb_loops;
>>
>> -  loop_optimizer_init (0);
>> +  loop_optimizer_init (LOOPS_NORMAL);
>>    if (dump_file && (dump_flags & TDF_DETAILS))
>>      flow_loops_dump (dump_file, NULL, 0);
>>
>> Index: gcc/tree-parloops.c
>> ===================================================================
>> --- gcc/tree-parloops.c (revision 189835)
>> +++ gcc/tree-parloops.c (working copy)
>> @@ -1415,6 +1415,7 @@
>>    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 189835)
>> +++ gcc/recog.c (working copy)
>> @@ -3333,7 +3333,7 @@
>>    /* 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 189835)
>> +++ gcc/function.c      (working copy)
>> @@ -133,7 +133,7 @@
>>  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 @@
>>    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 @@
>>               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 @@
>>
>>    /* 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 @@
>>    *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 @@
>>        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 @@
>>
>>        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 @@
>>
>>        /* 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 @@
>>              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 189835)
>> +++ gcc/print-rtl.c     (working copy)
>> @@ -416,10 +416,10 @@
>>         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 @@
>>           {
>>  #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 189835)
>> +++ gcc/profile.c       (working copy)
>> @@ -966,7 +966,7 @@
>>              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))
>> @@ -976,7 +976,6 @@
>>               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)
>> @@ -1188,7 +1187,7 @@
>>
>>           /* 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 189835)
>> +++ gcc/trans-mem.c     (working copy)
>> @@ -3796,7 +3796,6 @@
>>             {
>>               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 189835)
>> +++ gcc/gimplify.c      (working copy)
>> @@ -2600,7 +2600,6 @@
>>             = 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 189835)
>> +++ gcc/except.c        (working copy)
>> @@ -526,7 +526,10 @@
>>        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 189835)
>> +++ gcc/emit-rtl.c      (working copy)
>> @@ -3634,7 +3634,7 @@
>>         }
>>      }
>>
>> -  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)
>> @@ -3670,7 +3670,7 @@
>>    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
>> @@ -3703,7 +3703,7 @@
>>    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;
>> @@ -3723,7 +3723,7 @@
>>    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;
>> @@ -3743,7 +3743,7 @@
>>    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;
>> @@ -4416,8 +4416,8 @@
>>    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);
>> @@ -4440,62 +4440,62 @@
>>        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)
>>  {
>> @@ -4525,8 +4525,8 @@
>>      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);
>> @@ -4550,7 +4550,7 @@
>>        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,
>> @@ -4558,7 +4558,7 @@
>>                                        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)
>>  {
>> @@ -4566,14 +4566,14 @@
>>                                      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)
>>  {
>> @@ -4581,7 +4581,7 @@
>>                                      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)
>>  {
>> @@ -4589,7 +4589,7 @@
>>                               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)
>>  {
>> @@ -4598,7 +4598,7 @@
>>  }
>>
>>  /* 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)
>>  {
>> @@ -4606,7 +4606,7 @@
>>                               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)
>>  {
>> @@ -4615,7 +4615,7 @@
>>  }
>>
>>  /* 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)
>>  {
>> @@ -5865,7 +5865,7 @@
>>    /* 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,
>> @@ -5900,250 +5900,66 @@
>>             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_O(location_t);
>> -DEF_VEC_ALLOC_O(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)
>> -{
>> -  if (curr_rtl_loc >= 0)
>> -    epilogue_locator = curr_insn_locator ();
>> -  curr_rtl_loc = -1;
>> -}
>> -
>> -/* Allocate insn locator datastructure.  */
>> -void
>> -insn_locators_free (void)
>> +insn_locations_finalize (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);
>> +  epilogue_location = curr_location;
>> +  curr_location = UNKNOWN_LOCATION;
>>  }
>>
>>  /* 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 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 LOCATION_BLOCK (INSN_LOCATION (insn));
>>  }
>>
>>  /* Return line number of the statement that produced this insn.  */
>>  int
>>  insn_line (const_rtx insn)
>>  {
>> -  return locator_line (INSN_LOCATOR (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 LOCATION_LINE (INSN_LOCATION (insn));
>>  }
>>
>>  /* 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 189835)
>> +++ gcc/cfgexpand.c     (working copy)
>> @@ -92,8 +92,7 @@
>>            && 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 @@
>>
>>    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;
>>  }
>> @@ -1804,8 +1801,7 @@
>>    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;
>> @@ -1818,13 +1814,8 @@
>>        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;
>> @@ -1834,13 +1825,8 @@
>>        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;
>> @@ -1849,13 +1835,8 @@
>>    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;
>> @@ -1880,13 +1861,11 @@
>>
>>    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;
>>  }
>> @@ -1986,7 +1965,6 @@
>>      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))
>> @@ -2021,8 +1999,7 @@
>>  {
>>    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))
>>      {
>> @@ -3766,8 +3743,7 @@
>>           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).  */
>> @@ -3800,8 +3776,7 @@
>>                     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);
>> @@ -3828,8 +3803,7 @@
>>                       }
>>                   }
>>               }
>> -         set_curr_insn_source_location (sloc);
>> -         set_curr_insn_block (sblock);
>> +         set_curr_insn_location (sloc);
>>         }
>>
>>        currently_expanding_gimple_stmt = stmt;
>> @@ -3844,8 +3818,7 @@
>>         }
>>        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 (;;)
>> @@ -3867,8 +3840,7 @@
>>
>>               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);
>> @@ -3906,13 +3878,11 @@
>>                 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;
>> @@ -3920,8 +3890,7 @@
>>
>>           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);
>>
>> @@ -3939,8 +3908,7 @@
>>               PAT_VAR_LOCATION_LOC (val) = (rtx)value;
>>             }
>>
>> -         set_curr_insn_source_location (sloc);
>> -         set_curr_insn_block (sblock);
>> +         set_curr_insn_location (sloc);
>>         }
>>        else
>>         {
>> @@ -3981,13 +3949,8 @@
>>    /* 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));
>> @@ -4107,12 +4070,9 @@
>>
>>    /* 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 ();
>>
>> @@ -4331,20 +4291,19 @@
>>
>>    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 ();
>> @@ -4514,8 +4473,7 @@
>>    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 189835)
>> +++ gcc/cfgcleanup.c    (working copy)
>> @@ -481,13 +481,15 @@
>>                   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 @@
>>                         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 189835)
>> +++ gcc/tree-ssa-live.c (working copy)
>> @@ -587,7 +587,7 @@
>>     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;
>> @@ -615,7 +615,7 @@
>>    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);
>> @@ -765,13 +765,18 @@
>>            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, global_unused_vars);
>>              }
>>          }
>>
>>        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 189835)
>> +++ gcc/lto/lto.c       (working copy)
>> @@ -1603,7 +1603,6 @@
>>    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/rtl.c
>> ===================================================================
>> --- gcc/rtl.c   (revision 189835)
>> +++ gcc/rtl.c   (working copy)
>> @@ -440,7 +440,7 @@
>>  #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;
>> @@ -579,7 +579,7 @@
>>  #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 189835)
>> +++ gcc/rtl.h   (working copy)
>> @@ -739,6 +739,7 @@
>>  #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)
>> @@ -802,13 +803,13 @@
>>  /* 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.  */
>> @@ -1807,12 +1808,8 @@
>>  /* 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);
>> @@ -2648,14 +2645,10 @@
>>  /* 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 189835)
>> +++ gcc/tree-inline.c   (working copy)
>> @@ -852,10 +852,6 @@
>>        /* 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);
>> @@ -901,13 +897,9 @@
>>         {
>>           /* 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,
>> @@ -919,6 +911,22 @@
>>         }
>>      }
>>
>> +  /* 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;
>>  }
>> @@ -1144,11 +1152,10 @@
>>               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)
>> @@ -2020,6 +2027,7 @@
>>               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
>> @@ -2031,9 +2039,7 @@
>>
>>               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.  */
>> @@ -2046,8 +2052,19 @@
>>                   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 (locus, block));
>>             }
>>         }
>>      }
>> @@ -3946,7 +3963,8 @@
>>    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 189835)
>> +++ gcc/tree-streamer-in.c      (working copy)
>> @@ -776,7 +776,7 @@
>>
>>    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 189835)
>> +++ gcc/combine.c       (working copy)
>> @@ -2896,7 +2896,7 @@
>>
>>           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 189835)
>> +++ gcc/tree-outof-ssa.c        (working copy)
>> @@ -108,8 +108,7 @@
>>  {
>>    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 @@
>>                 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 @@
>>    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 @@
>>    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 @@
>>    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 @@
>>    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 189835)
>> +++ gcc/basic-block.h   (working copy)
>> @@ -47,8 +47,7 @@
>>    /* Auxiliary info specific to a pass.  */
>>    PTR GTY ((skip (""))) 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 189835)
>> +++ gcc/gimple.h        (working copy)
>> @@ -210,10 +210,6 @@
>>       and the prev pointer being the last.  */
>>    gimple next;
>>    gimple GTY((skip)) prev;
>> -
>> -  /* [ WORD 6 ]
>> -     Lexical block holding this statement.  */
>> -  tree block;
>>  };
>>
>>
>> @@ -1198,7 +1194,7 @@
>>  static inline tree
>>  gimple_block (const_gimple g)
>>  {
>> -  return g->gsbase.block;
>> +  return LOCATION_BLOCK (g->gsbase.location);
>>  }
>>
>>
>> @@ -1207,7 +1203,7 @@
>>  static inline void
>>  gimple_set_block (gimple g, tree block)
>>  {
>> -  g->gsbase.block = block;
>> +  g->gsbase.location = COMBINE_LOCATION (g->gsbase.location, block);
>>  }
>>
>>
>> @@ -1242,7 +1238,7 @@
>>  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 189835)
>> +++ gcc/tree-cfg.c      (working copy)
>> @@ -808,15 +808,11 @@
>>    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.  */
>> @@ -1026,8 +1022,6 @@
>>        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;
>>      }
>> @@ -1501,7 +1495,7 @@
>>
>>    /* 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;
>> @@ -5987,9 +5981,7 @@
>>    tree t = *tp;
>>
>>    if (EXPR_P (t))
>> -    /* We should never have TREE_BLOCK set on non-statements.  */
>> -    gcc_assert (!TREE_BLOCK (t));
>> -
>> +    ;
>>    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
>>      {
>>        if (TREE_CODE (t) == SSA_NAME)
>> @@ -6294,12 +6286,12 @@
>>      }
>>
>>    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 (e->goto_locus, d->new_block);
>>  #ifdef ENABLE_CHECKING
>>         else if (block != d->new_block)
>>           {
>> Index: gcc/config/alpha/alpha.c
>> ===================================================================
>> --- gcc/config/alpha/alpha.c    (revision 189835)
>> +++ gcc/config/alpha/alpha.c    (working copy)
>> @@ -8352,7 +8352,6 @@
>>       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 189835)
>> +++ gcc/config/sparc/sparc.c    (working copy)
>> @@ -10654,7 +10654,6 @@
>>       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 189835)
>> +++ gcc/config/i386/i386.c      (working copy)
>> @@ -33063,7 +33063,6 @@
>>    /* 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 189835)
>> +++ gcc/config/tilegx/tilegx.c  (working copy)
>> @@ -4804,7 +4804,6 @@
>>       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 189835)
>> +++ gcc/config/sh/sh.c  (working copy)
>> @@ -11979,7 +11979,6 @@
>>       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 189835)
>> +++ gcc/config/ia64/ia64.c      (working copy)
>> @@ -10848,7 +10848,6 @@
>>       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 189835)
>> +++ gcc/config/rs6000/rs6000.c  (working copy)
>> @@ -21664,7 +21664,6 @@
>>       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 189835)
>> +++ gcc/config/score/score.c    (working copy)
>> @@ -505,7 +505,6 @@
>>    /* 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 189835)
>> +++ gcc/config/tilepro/tilepro.c        (working copy)
>> @@ -4407,7 +4407,6 @@
>>       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 189835)
>> +++ gcc/config/mips/mips.c      (working copy)
>> @@ -15637,7 +15637,6 @@
>>    /* 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 ();
>>    shorten_branches (insn);
>> Index: gcc/cfgrtl.c
>> ===================================================================
>> --- gcc/cfgrtl.c        (revision 189835)
>> +++ gcc/cfgrtl.c        (working copy)
>> @@ -720,19 +720,19 @@
>>  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 @@
>>        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 @@
>>      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
>> @@ -1478,7 +1478,7 @@
>>    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;
>> @@ -3337,7 +3337,8 @@
>>          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;
>> @@ -3347,15 +3348,15 @@
>>               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;
>> @@ -3371,24 +3372,24 @@
>>                   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);
>> @@ -4088,7 +4089,7 @@
>>      }
>>
>>    /* 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 189835)
>> +++ gcc/stmt.c  (working copy)
>> @@ -2397,7 +2397,7 @@
>>                  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.  */
>> @@ -2521,7 +2521,7 @@
>>               /* 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 189835)
>> +++ libcpp/include/line-map.h   (working copy)
>> @@ -89,7 +89,7 @@
>>
>>  /* 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 @@
>>  #define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
>>    LINEMAPS_LAST_ALLOCATED_MAP (SET, true)
>>
>> +extern void location_block_init (void);
>> +extern void location_block_fini (void);
>> +extern source_location get_combine_location (source_location, void *);
>> +extern void *get_block_from_location (source_location);
>> +extern source_location get_locus_from_location (source_location);
>> +
>> +#define COMBINE_LOCATION(LOC, BLOCK) \
>> +  ((BLOCK) ? get_combine_location ((LOC), (BLOCK)) : (LOC))
>> +#define IS_COMBINED_LOCATION(LOC) (((LOC) & MAX_SOURCE_LOCATION) != (LOC))
>> +
>>  /* Initialize a line map set.  */
>>  extern void linemap_init (struct line_maps *);
>>
>> @@ -594,6 +604,8 @@
>>
>>    int column;
>>
>> +  void *block;
>> +
>>    /* In a system header?. */
>>    bool sysp;
>>  } expanded_location;
>> Index: libcpp/line-map.c
>> ===================================================================
>> --- libcpp/line-map.c   (revision 189835)
>> +++ libcpp/line-map.c   (working copy)
>> @@ -25,6 +25,7 @@
>>  #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,121 @@
>>  extern unsigned num_expanded_macros_counter;
>>  extern unsigned num_macro_tokens_counter;
>>
>> +struct location_block {
>> +  source_location locus;
>> +  void *block;
>> +};
>> +
>> +static htab_t location_block_htab;
>> +static source_location curr_combined_location;
>> +static struct location_block *location_blocks;
>> +static unsigned int allocated_location_blocks;
>> +
>> +/* Hash function for location_block hashtable.  */
>> +
>> +static hashval_t
>> +location_block_hash (const void *l)
>> +{
>> +  const struct location_block *lb = (const struct location_block *) l;
>> +  return (hashval_t) lb->locus + (size_t) &lb->block;
>> +}
>> +
>> +/* Compare function for location_block hashtable.  */
>> +
>> +static int
>> +location_block_eq (const void *l1, const void *l2)
>> +{
>> +  const struct location_block *lb1 = (const struct location_block *) l1;
>> +  const struct location_block *lb2 = (const struct location_block *) l2;
>> +  return lb1->locus == lb2->locus && lb1->block == lb2->block;
>> +}
>> +
>> +/* Update the hashtable when location_blocks is reallocated.  */
>> +
>> +static int
>> +location_block_update (void **slot, void *data)
>> +{
>> +  *((char **) slot) += ((char *) location_blocks - (char *) data);
>> +  return 1;
>> +}
>> +
>> +/* Combine LOCUS and BLOCK to a combined location.  */
>> +
>> +source_location
>> +get_combine_location (source_location locus, void *block)
>> +{
>> +  struct location_block lb;
>> +  struct location_block **slot;
>> +
>> +  linemap_assert (block);
>> +
>> +  if (IS_COMBINED_LOCATION (locus))
>> +    locus = location_blocks[locus & MAX_SOURCE_LOCATION].locus;
>> +  if (locus == 0 && block == NULL)
>> +    return 0;
>> +  lb.locus = locus;
>> +  lb.block = block;
>> +  slot = (struct location_block **)
>> +      htab_find_slot (location_block_htab, &lb, INSERT);
>> +  if (*slot == NULL)
>> +    {
>> +      *slot = location_blocks + curr_combined_location;
>> +      location_blocks[curr_combined_location] = lb;
>> +      if (++curr_combined_location >= allocated_location_blocks)
>> +       {
>> +         char *orig_location_blocks = (char *) location_blocks;
>> +         allocated_location_blocks *= 2;
>> +         location_blocks = XRESIZEVEC (struct location_block,
>> +                                       location_blocks,
>> +                                       allocated_location_blocks);
>> +         htab_traverse (location_block_htab, location_block_update,
>> +                        orig_location_blocks);
>> +       }
>> +    }
>> +  return ((*slot) - location_blocks) | 0x80000000;
>> +}
>> +
>> +/* Return the block for LOCATION.  */
>> +
>> +void *
>> +get_block_from_location (source_location location)
>> +{
>> +  linemap_assert (IS_COMBINED_LOCATION (location));
>> +  return location_blocks[location & MAX_SOURCE_LOCATION].block;
>> +}
>> +
>> +/* Return the locus for LOCATION.  */
>> +
>> +source_location
>> +get_locus_from_location (source_location location)
>> +{
>> +  linemap_assert (IS_COMBINED_LOCATION (location));
>> +  return location_blocks[location & MAX_SOURCE_LOCATION].locus;
>> +}
>> +
>> +/* Initialize the location_block structure.  */
>> +
>> +void
>> +location_block_init (void)
>> +{
>> +  location_block_htab = htab_create (100, location_block_hash,
>> +                                    location_block_eq, NULL);
>> +  curr_combined_location = 0;
>> +  allocated_location_blocks = 100;
>> +  location_blocks = XNEWVEC (struct location_block,
>> +                            allocated_location_blocks);
>> +}
>> +
>> +/* Finalize the location_block structure.  */
>> +
>> +void
>> +location_block_fini (void)
>> +{
>> +  allocated_location_blocks = 0;
>> +  XDELETEVEC (location_blocks);
>> +  htab_delete (location_block_htab);
>> +}
>> +
>>  /* Initialize a line map set.  */
>>
>>  void
>> @@ -509,6 +625,8 @@
>>  const struct line_map*
>>  linemap_lookup (struct line_maps *set, source_location line)
>>  {
>> +  if (IS_COMBINED_LOCATION (line))
>> +    line = location_blocks[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 +643,9 @@
>>    unsigned int md, mn, mx;
>>    const struct line_map *cached, *result;
>>
>> +  if (IS_COMBINED_LOCATION (line))
>> +    line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
>> +
>>    if (set ==  NULL || line < RESERVED_LOCATION_COUNT)
>>      return NULL;
>>
>> @@ -570,6 +691,9 @@
>>    unsigned int md, mn, mx;
>>    const struct line_map *cached, *result;
>>
>> +  if (IS_COMBINED_LOCATION (line))
>> +    line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
>> +
>>    linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
>>
>>    if (set ==  NULL)
>> @@ -648,6 +772,9 @@
>>  {
>>    unsigned token_no;
>>
>> +  if (IS_COMBINED_LOCATION (location))
>> +    location = location_blocks[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 +799,9 @@
>>  {
>>    unsigned token_no;
>>
>> +  if (IS_COMBINED_LOCATION (location))
>> +    location = location_blocks[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 +826,9 @@
>>  {
>>    const struct line_map *map = NULL;
>>
>> +  i
> ...
>
> [Message clipped]

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-02  3:23   ` Dehao Chen
@ 2012-08-02 10:06     ` Richard Guenther
  2012-08-06 18:36       ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-08-02 10:06 UTC (permalink / raw)
  To: Dehao Chen
  Cc: gcc-patches, Dodji Seketeli, Jakub Jelinek, Jan Hubicka, David Li

On Thu, Aug 2, 2012 at 5:23 AM, Dehao Chen <dehao@google.com> wrote:
> On Thu, Aug 2, 2012 at 2:07 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Wed, Aug 1, 2012 at 7:35 AM, Dehao Chen <dehao@google.com> wrote:
>>> Hi,
>>>
>>> This patch:
>>>
>>> * Integrates location with block into an integrated index.
>>> * Removes gimple->gsbase.block and tree->exp.block fields.
>>> * Updates inline/clone as well as tree liveness analysis to ensure the
>>> associated blocks are updated correctly.
>>>
>>> With this patch, the association between source location and its block
>>> are greatly enhanced, which produces much better inline stack in the
>>> debug info.
>>>
>>> Bootstrapped and regression tested on x86.
>>>
>>> OK for trunk?
>>
>> Nice.  But the LTO changes mean that you simply drop all BLOCK
>> associations on the floor ...
>
> Why? I've invoked TREE_SET_BLOCK in tree-streamer-in.c to read in the
> block info. So it should at least provide the same info as the
> original impl.
>
>> they at least look very incomplete.  Did you actually run LTO tests?
>
> Thanks for the reminder, I've added the following change to this patch:
>
> Index: gcc/tree-streamer-out.c
> ===================================================================
> --- gcc/tree-streamer-out.c     (revision 189835)
> +++ gcc/tree-streamer-out.c     (working copy)
> @@ -471,7 +471,7 @@
>  {
>    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 @@
>    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);
>  }

That doesn't match up with the change

Index: gcc/lto-streamer-out.c
===================================================================
--- gcc/lto-streamer-out.c      (revision 189835)
+++ gcc/lto-streamer-out.c      (working copy)
@@ -155,6 +155,7 @@
 {
   expanded_location xloc;

+  loc = LOCATION_LOCUS (loc);
   bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
   if (loc == UNKNOWN_LOCATION)
     return;

(please remember to generate diffs with -p, so the function name is shown
in the diff hunk header)

> I think BLOCK associations works fine for LTO. I've run check-gcc, and
> there's no regression on LTO tests. I also manually write some tests,
> and the generated final assembly has block info as expected.

What about the lto_output_location calls in gimple-streamer-out.c?  As far as I
can see they will end up dropping the associated BLOCK on the floor (I cannot
see any change on the -input side).

>>
>> lto/ has its own ChangeLog
>
> Thanks, I'll update the ChangeLog accordingly.
>
>> and I wonder why no frontends are affected
>> by this patch?
>
> Which files are you referring to?

I was refering to the issue you brought up earlier - all the fold
routines losing
block associations.  Maybe you can elaborate some more how locator
is different from location, thus how you set up the machinery.

Thanks,
Richard.

> Thanks,
> Dehao
>
>>
>> Richard.
>>
>>> Thanks,
>>> Dehao
>>>
>>> You can also find the patch in http://codereview.appspot.com/6454077
>>>
>>> gcc/ChangeLog
>>> 2012-08-01  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.
>>>         * dewarf2out.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.
>>>         * lto/lto.c (lto_fixup_prevailing_decls): 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.
>>>         * 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.
>>>
>>> libcpp/ChangeLog
>>> 2012-08-01  Dehao Chen  <dehao@google.com>
>>>
>>>         * include/line-map.h (MAX_SOURCE_LOCATION): New value.
>>>         (location_block_init): New.
>>>         (location_block_fini): New.
>>>         (get_combine_location): New.
>>>         (get_block_from_location): New.
>>>         (get_locus_from_location): New.
>>>         (COMBINE_LOCATION): New.
>>>         (IS_COMBINED_LOCATION): New.
>>>         (expanded_location): New field.
>>>         * line-map.c (location_block): New.
>>>         (location_block_htab): New.
>>>         (curr_combined_location): New.
>>>         (location_blocks): New.
>>>         (allocated_location_blocks): New.
>>>         (location_block_hash): New.
>>>         (location_block_eq): New.
>>>         (location_block_update): New.
>>>         (get_combine_location): New.
>>>         (get_block_from_location): New.
>>>         (get_locus_from_location): New.
>>>         (location_block_init): New.
>>>         (location_block_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/tree.c
>>> ===================================================================
>>> --- gcc/tree.c  (revision 189835)
>>> +++ gcc/tree.c  (working copy)
>>> @@ -3765,7 +3765,6 @@
>>>    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);
>>> @@ -10867,17 +10866,28 @@
>>>  }
>>>
>>>
>>> -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 (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 189835)
>>> +++ gcc/tree.h  (working copy)
>>> @@ -999,7 +999,8 @@
>>>
>>>  #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"
>>>
>>> @@ -1702,7 +1703,7 @@
>>>  #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)
>>> @@ -1881,7 +1882,7 @@
>>>                                               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.
>>> @@ -1972,7 +1973,6 @@
>>>  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];
>>> @@ -5164,7 +5164,7 @@
>>>  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
>>> @@ -5539,7 +5539,8 @@
>>>  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 189835)
>>> +++ gcc/final.c (working copy)
>>> @@ -1605,7 +1605,7 @@
>>>                                              insn_scope (XVECEXP (body, 0, i)));
>>>         }
>>>        if (! this_block)
>>> -       continue;
>>> +       this_block = DECL_INITIAL (cfun->decl);
>>>
>>>        if (this_block != cur_block)
>>>         {
>>> @@ -1640,8 +1640,8 @@
>>>
>>>    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 189835)
>>> +++ gcc/input.c (working copy)
>>> @@ -51,6 +51,13 @@
>>>    expanded_location xloc;
>>>    const struct line_map *map;
>>>    enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
>>> +  tree block = NULL;
>>> +
>>> +  if (IS_COMBINED_LOCATION (loc))
>>> +    {
>>> +      block = LOCATION_BLOCK (loc);
>>> +      loc = LOCATION_LOCUS (loc);
>>> +    }
>>>
>>>    memset (&xloc, 0, sizeof (xloc));
>>>
>>> @@ -74,6 +81,7 @@
>>>        xloc = linemap_expand_location (line_table, map, loc);
>>>      }
>>>
>>> +  xloc.block = block;
>>>    if (loc <= BUILTINS_LOCATION)
>>>      xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
>>>
>>> Index: gcc/input.h
>>> ===================================================================
>>> --- gcc/input.h (revision 189835)
>>> +++ gcc/input.h (working copy)
>>> @@ -51,6 +51,14 @@
>>>  #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_COMBINED_LOCATION(LOC)) ? get_locus_from_location (LOC) : (LOC))
>>> +#define LOCATION_BLOCK(LOC) \
>>> +  ((tree) ((IS_COMBINED_LOCATION (LOC)) ? get_block_from_location (LOC) \
>>> +  : NULL))
>>> +#define IS_UNKNOWN_LOCATION(LOC) \
>>> +  ((IS_COMBINED_LOCATION (LOC)) ? get_locus_from_location (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 189835)
>>> +++ gcc/fold-const.c    (working copy)
>>> @@ -145,7 +145,7 @@
>>>  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 189835)
>>> +++ gcc/toplev.c        (working copy)
>>> @@ -1140,6 +1140,7 @@
>>>    linemap_init (line_table);
>>>    line_table->reallocator = realloc_for_line_map;
>>>    line_table->round_alloc_size = ggc_round_alloc_size;
>>> +  location_block_init ();
>>>    init_ttree ();
>>>
>>>    /* Initialize register usage now so switches may override.  */
>>> @@ -1946,6 +1947,7 @@
>>>    invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
>>>
>>>    finalize_plugins ();
>>> +  location_block_fini ();
>>>    if (seen_error ())
>>>      return (FATAL_EXIT_CODE);
>>>
>>> Index: gcc/reorg.c
>>> ===================================================================
>>> --- gcc/reorg.c (revision 189835)
>>> +++ gcc/reorg.c (working copy)
>>> @@ -545,7 +545,7 @@
>>>    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 @@
>>>
>>>        /* 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)
>>>         {
>>> @@ -4087,7 +4087,7 @@
>>>      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 189835)
>>> +++ gcc/modulo-sched.c  (working copy)
>>> @@ -1246,9 +1246,9 @@
>>>  /* 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 @@
>>>           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 @@
>>>           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 @@
>>>           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 @@
>>>         {
>>>           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 @@
>>>           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 @@
>>>
>>>        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 @@
>>>
>>>            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 189835)
>>> +++ gcc/lto-streamer-out.c      (working copy)
>>> @@ -155,6 +155,7 @@
>>>  {
>>>    expanded_location xloc;
>>>
>>> +  loc = LOCATION_LOCUS (loc);
>>>    bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
>>>    if (loc == UNKNOWN_LOCATION)
>>>      return;
>>> Index: gcc/jump.c
>>> ===================================================================
>>> --- gcc/jump.c  (revision 189835)
>>> +++ gcc/jump.c  (working copy)
>>> @@ -1818,8 +1818,7 @@
>>>           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/ifcvt.c
>>> ===================================================================
>>> --- gcc/ifcvt.c (revision 189835)
>>> +++ gcc/ifcvt.c (working copy)
>>> @@ -1019,7 +1019,7 @@
>>>             return FALSE;
>>>
>>>           emit_insn_before_setloc (seq, if_info->jump,
>>> -                                  INSN_LOCATOR (if_info->insn_a));
>>> +                                  INSN_LOCATION (if_info->insn_a));
>>>         }
>>>        return TRUE;
>>>      }
>>> @@ -1064,7 +1064,7 @@
>>>         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
>>> @@ -1195,7 +1195,7 @@
>>>         return FALSE;
>>>
>>>        emit_insn_before_setloc (seq, if_info->jump,
>>> -                              INSN_LOCATOR (if_info->insn_a));
>>> +                              INSN_LOCATION (if_info->insn_a));
>>>        return TRUE;
>>>      }
>>>
>>> @@ -1243,7 +1243,7 @@
>>>                 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 ();
>>> @@ -1283,7 +1283,7 @@
>>>                 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 ();
>>> @@ -1332,7 +1332,7 @@
>>>             return FALSE;
>>>
>>>           emit_insn_before_setloc (seq, if_info->jump,
>>> -                                  INSN_LOCATOR (if_info->insn_a));
>>> +                                  INSN_LOCATION (if_info->insn_a));
>>>           return TRUE;
>>>         }
>>>
>>> @@ -1481,7 +1481,7 @@
>>>             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
>>> @@ -1682,7 +1682,7 @@
>>>    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:
>>> @@ -1929,7 +1929,7 @@
>>>    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;
>>>
>>> @@ -2076,7 +2076,7 @@
>>>    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;
>>>
>>> @@ -2155,7 +2155,7 @@
>>>    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;
>>>  }
>>>
>>> @@ -2255,7 +2255,7 @@
>>>         return FALSE;
>>>
>>>        emit_insn_before_setloc (seq, if_info->jump,
>>> -                              INSN_LOCATOR (if_info->insn_a));
>>> +                              INSN_LOCATION (if_info->insn_a));
>>>      }
>>>    return TRUE;
>>>  }
>>> @@ -2656,7 +2656,7 @@
>>>        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
>>> @@ -2937,7 +2937,7 @@
>>>        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)
>>>      {
>>> @@ -3655,7 +3655,7 @@
>>>      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/dwarf2out.c
>>> ===================================================================
>>> --- gcc/dwarf2out.c     (revision 189835)
>>> +++ gcc/dwarf2out.c     (working copy)
>>> @@ -15506,7 +15506,7 @@
>>>  {
>>>    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 189835)
>>> +++ gcc/expr.c  (working copy)
>>> @@ -7802,19 +7802,14 @@
>>>    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);
>>> -
>>> -      /* Record where the insns produced belong.  */
>>> -      set_curr_insn_block (TREE_BLOCK (exp));
>>> +      set_curr_insn_location (input_location);
>>>
>>>        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/predict.c
>>> ===================================================================
>>> --- gcc/predict.c       (revision 189835)
>>> +++ gcc/predict.c       (working copy)
>>> @@ -2177,7 +2177,7 @@
>>>  {
>>>    unsigned nb_loops;
>>>
>>> -  loop_optimizer_init (0);
>>> +  loop_optimizer_init (LOOPS_NORMAL);
>>>    if (dump_file && (dump_flags & TDF_DETAILS))
>>>      flow_loops_dump (dump_file, NULL, 0);
>>>
>>> Index: gcc/tree-parloops.c
>>> ===================================================================
>>> --- gcc/tree-parloops.c (revision 189835)
>>> +++ gcc/tree-parloops.c (working copy)
>>> @@ -1415,6 +1415,7 @@
>>>    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 189835)
>>> +++ gcc/recog.c (working copy)
>>> @@ -3333,7 +3333,7 @@
>>>    /* 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 189835)
>>> +++ gcc/function.c      (working copy)
>>> @@ -133,7 +133,7 @@
>>>  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 @@
>>>    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 @@
>>>               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 @@
>>>
>>>    /* 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 @@
>>>    *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 @@
>>>        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 @@
>>>
>>>        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 @@
>>>
>>>        /* 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 @@
>>>              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 189835)
>>> +++ gcc/print-rtl.c     (working copy)
>>> @@ -416,10 +416,10 @@
>>>         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 @@
>>>           {
>>>  #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 189835)
>>> +++ gcc/profile.c       (working copy)
>>> @@ -966,7 +966,7 @@
>>>              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))
>>> @@ -976,7 +976,6 @@
>>>               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)
>>> @@ -1188,7 +1187,7 @@
>>>
>>>           /* 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 189835)
>>> +++ gcc/trans-mem.c     (working copy)
>>> @@ -3796,7 +3796,6 @@
>>>             {
>>>               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 189835)
>>> +++ gcc/gimplify.c      (working copy)
>>> @@ -2600,7 +2600,6 @@
>>>             = 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 189835)
>>> +++ gcc/except.c        (working copy)
>>> @@ -526,7 +526,10 @@
>>>        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 189835)
>>> +++ gcc/emit-rtl.c      (working copy)
>>> @@ -3634,7 +3634,7 @@
>>>         }
>>>      }
>>>
>>> -  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)
>>> @@ -3670,7 +3670,7 @@
>>>    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
>>> @@ -3703,7 +3703,7 @@
>>>    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;
>>> @@ -3723,7 +3723,7 @@
>>>    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;
>>> @@ -3743,7 +3743,7 @@
>>>    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;
>>> @@ -4416,8 +4416,8 @@
>>>    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);
>>> @@ -4440,62 +4440,62 @@
>>>        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)
>>>  {
>>> @@ -4525,8 +4525,8 @@
>>>      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);
>>> @@ -4550,7 +4550,7 @@
>>>        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,
>>> @@ -4558,7 +4558,7 @@
>>>                                        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)
>>>  {
>>> @@ -4566,14 +4566,14 @@
>>>                                      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)
>>>  {
>>> @@ -4581,7 +4581,7 @@
>>>                                      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)
>>>  {
>>> @@ -4589,7 +4589,7 @@
>>>                               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)
>>>  {
>>> @@ -4598,7 +4598,7 @@
>>>  }
>>>
>>>  /* 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)
>>>  {
>>> @@ -4606,7 +4606,7 @@
>>>                               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)
>>>  {
>>> @@ -4615,7 +4615,7 @@
>>>  }
>>>
>>>  /* 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)
>>>  {
>>> @@ -5865,7 +5865,7 @@
>>>    /* 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,
>>> @@ -5900,250 +5900,66 @@
>>>             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_O(location_t);
>>> -DEF_VEC_ALLOC_O(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)
>>> -{
>>> -  if (curr_rtl_loc >= 0)
>>> -    epilogue_locator = curr_insn_locator ();
>>> -  curr_rtl_loc = -1;
>>> -}
>>> -
>>> -/* Allocate insn locator datastructure.  */
>>> -void
>>> -insn_locators_free (void)
>>> +insn_locations_finalize (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);
>>> +  epilogue_location = curr_location;
>>> +  curr_location = UNKNOWN_LOCATION;
>>>  }
>>>
>>>  /* 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 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 LOCATION_BLOCK (INSN_LOCATION (insn));
>>>  }
>>>
>>>  /* Return line number of the statement that produced this insn.  */
>>>  int
>>>  insn_line (const_rtx insn)
>>>  {
>>> -  return locator_line (INSN_LOCATOR (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 LOCATION_LINE (INSN_LOCATION (insn));
>>>  }
>>>
>>>  /* 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 189835)
>>> +++ gcc/cfgexpand.c     (working copy)
>>> @@ -92,8 +92,7 @@
>>>            && 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 @@
>>>
>>>    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;
>>>  }
>>> @@ -1804,8 +1801,7 @@
>>>    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;
>>> @@ -1818,13 +1814,8 @@
>>>        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;
>>> @@ -1834,13 +1825,8 @@
>>>        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;
>>> @@ -1849,13 +1835,8 @@
>>>    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;
>>> @@ -1880,13 +1861,11 @@
>>>
>>>    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;
>>>  }
>>> @@ -1986,7 +1965,6 @@
>>>      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))
>>> @@ -2021,8 +1999,7 @@
>>>  {
>>>    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))
>>>      {
>>> @@ -3766,8 +3743,7 @@
>>>           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).  */
>>> @@ -3800,8 +3776,7 @@
>>>                     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);
>>> @@ -3828,8 +3803,7 @@
>>>                       }
>>>                   }
>>>               }
>>> -         set_curr_insn_source_location (sloc);
>>> -         set_curr_insn_block (sblock);
>>> +         set_curr_insn_location (sloc);
>>>         }
>>>
>>>        currently_expanding_gimple_stmt = stmt;
>>> @@ -3844,8 +3818,7 @@
>>>         }
>>>        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 (;;)
>>> @@ -3867,8 +3840,7 @@
>>>
>>>               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);
>>> @@ -3906,13 +3878,11 @@
>>>                 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;
>>> @@ -3920,8 +3890,7 @@
>>>
>>>           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);
>>>
>>> @@ -3939,8 +3908,7 @@
>>>               PAT_VAR_LOCATION_LOC (val) = (rtx)value;
>>>             }
>>>
>>> -         set_curr_insn_source_location (sloc);
>>> -         set_curr_insn_block (sblock);
>>> +         set_curr_insn_location (sloc);
>>>         }
>>>        else
>>>         {
>>> @@ -3981,13 +3949,8 @@
>>>    /* 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));
>>> @@ -4107,12 +4070,9 @@
>>>
>>>    /* 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 ();
>>>
>>> @@ -4331,20 +4291,19 @@
>>>
>>>    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 ();
>>> @@ -4514,8 +4473,7 @@
>>>    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 189835)
>>> +++ gcc/cfgcleanup.c    (working copy)
>>> @@ -481,13 +481,15 @@
>>>                   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 @@
>>>                         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 189835)
>>> +++ gcc/tree-ssa-live.c (working copy)
>>> @@ -587,7 +587,7 @@
>>>     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;
>>> @@ -615,7 +615,7 @@
>>>    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);
>>> @@ -765,13 +765,18 @@
>>>            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, global_unused_vars);
>>>              }
>>>          }
>>>
>>>        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 189835)
>>> +++ gcc/lto/lto.c       (working copy)
>>> @@ -1603,7 +1603,6 @@
>>>    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/rtl.c
>>> ===================================================================
>>> --- gcc/rtl.c   (revision 189835)
>>> +++ gcc/rtl.c   (working copy)
>>> @@ -440,7 +440,7 @@
>>>  #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;
>>> @@ -579,7 +579,7 @@
>>>  #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 189835)
>>> +++ gcc/rtl.h   (working copy)
>>> @@ -739,6 +739,7 @@
>>>  #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)
>>> @@ -802,13 +803,13 @@
>>>  /* 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.  */
>>> @@ -1807,12 +1808,8 @@
>>>  /* 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);
>>> @@ -2648,14 +2645,10 @@
>>>  /* 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 189835)
>>> +++ gcc/tree-inline.c   (working copy)
>>> @@ -852,10 +852,6 @@
>>>        /* 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);
>>> @@ -901,13 +897,9 @@
>>>         {
>>>           /* 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,
>>> @@ -919,6 +911,22 @@
>>>         }
>>>      }
>>>
>>> +  /* 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;
>>>  }
>>> @@ -1144,11 +1152,10 @@
>>>               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)
>>> @@ -2020,6 +2027,7 @@
>>>               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
>>> @@ -2031,9 +2039,7 @@
>>>
>>>               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.  */
>>> @@ -2046,8 +2052,19 @@
>>>                   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 (locus, block));
>>>             }
>>>         }
>>>      }
>>> @@ -3946,7 +3963,8 @@
>>>    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 189835)
>>> +++ gcc/tree-streamer-in.c      (working copy)
>>> @@ -776,7 +776,7 @@
>>>
>>>    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 189835)
>>> +++ gcc/combine.c       (working copy)
>>> @@ -2896,7 +2896,7 @@
>>>
>>>           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 189835)
>>> +++ gcc/tree-outof-ssa.c        (working copy)
>>> @@ -108,8 +108,7 @@
>>>  {
>>>    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 @@
>>>                 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 @@
>>>    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 @@
>>>    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 @@
>>>    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 @@
>>>    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 189835)
>>> +++ gcc/basic-block.h   (working copy)
>>> @@ -47,8 +47,7 @@
>>>    /* Auxiliary info specific to a pass.  */
>>>    PTR GTY ((skip (""))) 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 189835)
>>> +++ gcc/gimple.h        (working copy)
>>> @@ -210,10 +210,6 @@
>>>       and the prev pointer being the last.  */
>>>    gimple next;
>>>    gimple GTY((skip)) prev;
>>> -
>>> -  /* [ WORD 6 ]
>>> -     Lexical block holding this statement.  */
>>> -  tree block;
>>>  };
>>>
>>>
>>> @@ -1198,7 +1194,7 @@
>>>  static inline tree
>>>  gimple_block (const_gimple g)
>>>  {
>>> -  return g->gsbase.block;
>>> +  return LOCATION_BLOCK (g->gsbase.location);
>>>  }
>>>
>>>
>>> @@ -1207,7 +1203,7 @@
>>>  static inline void
>>>  gimple_set_block (gimple g, tree block)
>>>  {
>>> -  g->gsbase.block = block;
>>> +  g->gsbase.location = COMBINE_LOCATION (g->gsbase.location, block);
>>>  }
>>>
>>>
>>> @@ -1242,7 +1238,7 @@
>>>  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 189835)
>>> +++ gcc/tree-cfg.c      (working copy)
>>> @@ -808,15 +808,11 @@
>>>    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.  */
>>> @@ -1026,8 +1022,6 @@
>>>        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;
>>>      }
>>> @@ -1501,7 +1495,7 @@
>>>
>>>    /* 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;
>>> @@ -5987,9 +5981,7 @@
>>>    tree t = *tp;
>>>
>>>    if (EXPR_P (t))
>>> -    /* We should never have TREE_BLOCK set on non-statements.  */
>>> -    gcc_assert (!TREE_BLOCK (t));
>>> -
>>> +    ;
>>>    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
>>>      {
>>>        if (TREE_CODE (t) == SSA_NAME)
>>> @@ -6294,12 +6286,12 @@
>>>      }
>>>
>>>    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 (e->goto_locus, d->new_block);
>>>  #ifdef ENABLE_CHECKING
>>>         else if (block != d->new_block)
>>>           {
>>> Index: gcc/config/alpha/alpha.c
>>> ===================================================================
>>> --- gcc/config/alpha/alpha.c    (revision 189835)
>>> +++ gcc/config/alpha/alpha.c    (working copy)
>>> @@ -8352,7 +8352,6 @@
>>>       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 189835)
>>> +++ gcc/config/sparc/sparc.c    (working copy)
>>> @@ -10654,7 +10654,6 @@
>>>       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 189835)
>>> +++ gcc/config/i386/i386.c      (working copy)
>>> @@ -33063,7 +33063,6 @@
>>>    /* 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 189835)
>>> +++ gcc/config/tilegx/tilegx.c  (working copy)
>>> @@ -4804,7 +4804,6 @@
>>>       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 189835)
>>> +++ gcc/config/sh/sh.c  (working copy)
>>> @@ -11979,7 +11979,6 @@
>>>       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 189835)
>>> +++ gcc/config/ia64/ia64.c      (working copy)
>>> @@ -10848,7 +10848,6 @@
>>>       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 189835)
>>> +++ gcc/config/rs6000/rs6000.c  (working copy)
>>> @@ -21664,7 +21664,6 @@
>>>       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 189835)
>>> +++ gcc/config/score/score.c    (working copy)
>>> @@ -505,7 +505,6 @@
>>>    /* 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 189835)
>>> +++ gcc/config/tilepro/tilepro.c        (working copy)
>>> @@ -4407,7 +4407,6 @@
>>>       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 189835)
>>> +++ gcc/config/mips/mips.c      (working copy)
>>> @@ -15637,7 +15637,6 @@
>>>    /* 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 ();
>>>    shorten_branches (insn);
>>> Index: gcc/cfgrtl.c
>>> ===================================================================
>>> --- gcc/cfgrtl.c        (revision 189835)
>>> +++ gcc/cfgrtl.c        (working copy)
>>> @@ -720,19 +720,19 @@
>>>  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 @@
>>>        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 @@
>>>      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
>>> @@ -1478,7 +1478,7 @@
>>>    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;
>>> @@ -3337,7 +3337,8 @@
>>>          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;
>>> @@ -3347,15 +3348,15 @@
>>>               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;
>>> @@ -3371,24 +3372,24 @@
>>>                   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);
>>> @@ -4088,7 +4089,7 @@
>>>      }
>>>
>>>    /* 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 189835)
>>> +++ gcc/stmt.c  (working copy)
>>> @@ -2397,7 +2397,7 @@
>>>                  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.  */
>>> @@ -2521,7 +2521,7 @@
>>>               /* 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 189835)
>>> +++ libcpp/include/line-map.h   (working copy)
>>> @@ -89,7 +89,7 @@
>>>
>>>  /* 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 @@
>>>  #define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
>>>    LINEMAPS_LAST_ALLOCATED_MAP (SET, true)
>>>
>>> +extern void location_block_init (void);
>>> +extern void location_block_fini (void);
>>> +extern source_location get_combine_location (source_location, void *);
>>> +extern void *get_block_from_location (source_location);
>>> +extern source_location get_locus_from_location (source_location);
>>> +
>>> +#define COMBINE_LOCATION(LOC, BLOCK) \
>>> +  ((BLOCK) ? get_combine_location ((LOC), (BLOCK)) : (LOC))
>>> +#define IS_COMBINED_LOCATION(LOC) (((LOC) & MAX_SOURCE_LOCATION) != (LOC))
>>> +
>>>  /* Initialize a line map set.  */
>>>  extern void linemap_init (struct line_maps *);
>>>
>>> @@ -594,6 +604,8 @@
>>>
>>>    int column;
>>>
>>> +  void *block;
>>> +
>>>    /* In a system header?. */
>>>    bool sysp;
>>>  } expanded_location;
>>> Index: libcpp/line-map.c
>>> ===================================================================
>>> --- libcpp/line-map.c   (revision 189835)
>>> +++ libcpp/line-map.c   (working copy)
>>> @@ -25,6 +25,7 @@
>>>  #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,121 @@
>>>  extern unsigned num_expanded_macros_counter;
>>>  extern unsigned num_macro_tokens_counter;
>>>
>>> +struct location_block {
>>> +  source_location locus;
>>> +  void *block;
>>> +};
>>> +
>>> +static htab_t location_block_htab;
>>> +static source_location curr_combined_location;
>>> +static struct location_block *location_blocks;
>>> +static unsigned int allocated_location_blocks;
>>> +
>>> +/* Hash function for location_block hashtable.  */
>>> +
>>> +static hashval_t
>>> +location_block_hash (const void *l)
>>> +{
>>> +  const struct location_block *lb = (const struct location_block *) l;
>>> +  return (hashval_t) lb->locus + (size_t) &lb->block;
>>> +}
>>> +
>>> +/* Compare function for location_block hashtable.  */
>>> +
>>> +static int
>>> +location_block_eq (const void *l1, const void *l2)
>>> +{
>>> +  const struct location_block *lb1 = (const struct location_block *) l1;
>>> +  const struct location_block *lb2 = (const struct location_block *) l2;
>>> +  return lb1->locus == lb2->locus && lb1->block == lb2->block;
>>> +}
>>> +
>>> +/* Update the hashtable when location_blocks is reallocated.  */
>>> +
>>> +static int
>>> +location_block_update (void **slot, void *data)
>>> +{
>>> +  *((char **) slot) += ((char *) location_blocks - (char *) data);
>>> +  return 1;
>>> +}
>>> +
>>> +/* Combine LOCUS and BLOCK to a combined location.  */
>>> +
>>> +source_location
>>> +get_combine_location (source_location locus, void *block)
>>> +{
>>> +  struct location_block lb;
>>> +  struct location_block **slot;
>>> +
>>> +  linemap_assert (block);
>>> +
>>> +  if (IS_COMBINED_LOCATION (locus))
>>> +    locus = location_blocks[locus & MAX_SOURCE_LOCATION].locus;
>>> +  if (locus == 0 && block == NULL)
>>> +    return 0;
>>> +  lb.locus = locus;
>>> +  lb.block = block;
>>> +  slot = (struct location_block **)
>>> +      htab_find_slot (location_block_htab, &lb, INSERT);
>>> +  if (*slot == NULL)
>>> +    {
>>> +      *slot = location_blocks + curr_combined_location;
>>> +      location_blocks[curr_combined_location] = lb;
>>> +      if (++curr_combined_location >= allocated_location_blocks)
>>> +       {
>>> +         char *orig_location_blocks = (char *) location_blocks;
>>> +         allocated_location_blocks *= 2;
>>> +         location_blocks = XRESIZEVEC (struct location_block,
>>> +                                       location_blocks,
>>> +                                       allocated_location_blocks);
>>> +         htab_traverse (location_block_htab, location_block_update,
>>> +                        orig_location_blocks);
>>> +       }
>>> +    }
>>> +  return ((*slot) - location_blocks) | 0x80000000;
>>> +}
>>> +
>>> +/* Return the block for LOCATION.  */
>>> +
>>> +void *
>>> +get_block_from_location (source_location location)
>>> +{
>>> +  linemap_assert (IS_COMBINED_LOCATION (location));
>>> +  return location_blocks[location & MAX_SOURCE_LOCATION].block;
>>> +}
>>> +
>>> +/* Return the locus for LOCATION.  */
>>> +
>>> +source_location
>>> +get_locus_from_location (source_location location)
>>> +{
>>> +  linemap_assert (IS_COMBINED_LOCATION (location));
>>> +  return location_blocks[location & MAX_SOURCE_LOCATION].locus;
>>> +}
>>> +
>>> +/* Initialize the location_block structure.  */
>>> +
>>> +void
>>> +location_block_init (void)
>>> +{
>>> +  location_block_htab = htab_create (100, location_block_hash,
>>> +                                    location_block_eq, NULL);
>>> +  curr_combined_location = 0;
>>> +  allocated_location_blocks = 100;
>>> +  location_blocks = XNEWVEC (struct location_block,
>>> +                            allocated_location_blocks);
>>> +}
>>> +
>>> +/* Finalize the location_block structure.  */
>>> +
>>> +void
>>> +location_block_fini (void)
>>> +{
>>> +  allocated_location_blocks = 0;
>>> +  XDELETEVEC (location_blocks);
>>> +  htab_delete (location_block_htab);
>>> +}
>>> +
>>>  /* Initialize a line map set.  */
>>>
>>>  void
>>> @@ -509,6 +625,8 @@
>>>  const struct line_map*
>>>  linemap_lookup (struct line_maps *set, source_location line)
>>>  {
>>> +  if (IS_COMBINED_LOCATION (line))
>>> +    line = location_blocks[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 +643,9 @@
>>>    unsigned int md, mn, mx;
>>>    const struct line_map *cached, *result;
>>>
>>> +  if (IS_COMBINED_LOCATION (line))
>>> +    line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
>>> +
>>>    if (set ==  NULL || line < RESERVED_LOCATION_COUNT)
>>>      return NULL;
>>>
>>> @@ -570,6 +691,9 @@
>>>    unsigned int md, mn, mx;
>>>    const struct line_map *cached, *result;
>>>
>>> +  if (IS_COMBINED_LOCATION (line))
>>> +    line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
>>> +
>>>    linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
>>>
>>>    if (set ==  NULL)
>>> @@ -648,6 +772,9 @@
>>>  {
>>>    unsigned token_no;
>>>
>>> +  if (IS_COMBINED_LOCATION (location))
>>> +    location = location_blocks[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 +799,9 @@
>>>  {
>>>    unsigned token_no;
>>>
>>> +  if (IS_COMBINED_LOCATION (location))
>>> +    location = location_blocks[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 +826,9 @@
>>>  {
>>>    const struct line_map *map = NULL;
>>>
>>> +  i
>> ...
>>
>> [Message clipped]

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-02 10:06     ` Richard Guenther
@ 2012-08-06 18:36       ` Dehao Chen
  2012-08-07 15:16         ` Richard Guenther
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-08-06 18:36 UTC (permalink / raw)
  To: Richard Guenther
  Cc: gcc-patches, Dodji Seketeli, Jakub Jelinek, Jan Hubicka, David Li

On Thu, Aug 2, 2012 at 6:05 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Thu, Aug 2, 2012 at 5:23 AM, Dehao Chen <dehao@google.com> wrote:
>> On Thu, Aug 2, 2012 at 2:07 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Wed, Aug 1, 2012 at 7:35 AM, Dehao Chen <dehao@google.com> wrote:
>>>> Hi,
>>>>
>>>> This patch:
>>>>
>>>> * Integrates location with block into an integrated index.
>>>> * Removes gimple->gsbase.block and tree->exp.block fields.
>>>> * Updates inline/clone as well as tree liveness analysis to ensure the
>>>> associated blocks are updated correctly.
>>>>
>>>> With this patch, the association between source location and its block
>>>> are greatly enhanced, which produces much better inline stack in the
>>>> debug info.
>>>>
>>>> Bootstrapped and regression tested on x86.
>>>>
>>>> OK for trunk?
>>>
>>> Nice.  But the LTO changes mean that you simply drop all BLOCK
>>> associations on the floor ...
>>
>> Why? I've invoked TREE_SET_BLOCK in tree-streamer-in.c to read in the
>> block info. So it should at least provide the same info as the
>> original impl.
>>
>>> they at least look very incomplete.  Did you actually run LTO tests?
>>
>> Thanks for the reminder, I've added the following change to this patch:
>>
>> Index: gcc/tree-streamer-out.c
>> ===================================================================
>> --- gcc/tree-streamer-out.c     (revision 189835)
>> +++ gcc/tree-streamer-out.c     (working copy)
>> @@ -471,7 +471,7 @@
>>  {
>>    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 @@
>>    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);
>>  }
>
> That doesn't match up with the change
>
> Index: gcc/lto-streamer-out.c
> ===================================================================
> --- gcc/lto-streamer-out.c      (revision 189835)
> +++ gcc/lto-streamer-out.c      (working copy)
> @@ -155,6 +155,7 @@
>  {
>    expanded_location xloc;
>
> +  loc = LOCATION_LOCUS (loc);
>    bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
>    if (loc == UNKNOWN_LOCATION)
>      return;
>
> (please remember to generate diffs with -p, so the function name is shown
> in the diff hunk header)

I've attached the new patch with -p output in this mail. Also added
the change in gimple-stream-out.c

>
>> I think BLOCK associations works fine for LTO. I've run check-gcc, and
>> there's no regression on LTO tests. I also manually write some tests,
>> and the generated final assembly has block info as expected.
>
> What about the lto_output_location calls in gimple-streamer-out.c?  As far as I
> can see they will end up dropping the associated BLOCK on the floor (I cannot
> see any change on the -input side).

The beauty of this patch is that it does not need to change the input
side (except that we added tree_set_block instead of using
"tree_block(t)" as lvalue, more detail in the following illustration.

>
>>>
>>> lto/ has its own ChangeLog
>>
>> Thanks, I'll update the ChangeLog accordingly.
>>
>>> and I wonder why no frontends are affected
>>> by this patch?
>>
>> Which files are you referring to?
>
> I was refering to the issue you brought up earlier - all the fold
> routines losing
> block associations.  Maybe you can elaborate some more how locator
> is different from location, thus how you set up the machinery.

This patch defines the following terminology:
- locus: the original location_t in structures such as
gimple_location, EXPR_LOCATION, etc.
- locator: an index to the location_block array, as used in RTL in the
original implementation.
- location: an uint32 that represent the new location: if the highest
bit is 0, it serves as the locus, if the highest bit is 1, the lower
31 bits serves as the locator.

The macro LOCATION_LOCUS derives the locus from location.
The macro LOCATION_BLOCK derives the block from location.
And the gimple_set_block and tree_set_block are modified to set the
updated location for gimple/tree.

Because the interface of gimple_set_block/gimple_block does not
change, we kept frontend change minimal. Also, as we encode the block
into location, the block info can be passed without need to change the
fold_.* interface.

The downside of this approach is that we need to explicitly use
LOCATION_LOCUS when we mean to use the original locus. E.g. when LTO
streams out location, it actually streams out locus. Fortunately, only
a small portion of code need to use the locus. Most code just copy the
location from one place to one another.

Thanks,
Dehao

Updated patch:


Index: gcc/gimple-streamer-out.c
===================================================================
*** gcc/gimple-streamer-out.c	(revision 189835)
--- gcc/gimple-streamer-out.c	(working copy)
*************** output_gimple_stmt (struct output_block
*** 74,80 ****
    streamer_write_bitpack (&bp);

    /* Emit location information for the statement.  */
!   lto_output_location (ob, gimple_location (stmt));

    /* Emit the lexical block holding STMT.  */
    stream_write_tree (ob, gimple_block (stmt), true);
--- 74,80 ----
    streamer_write_bitpack (&bp);

    /* Emit location information for the statement.  */
!   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 189835)
--- gcc/tree.c	(working copy)
*************** build1_stat (enum tree_code code, tree t
*** 3765,3771 ****
    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);
--- 3765,3770 ----
*************** walk_tree_without_duplicates_1 (tree *tp
*** 10867,10883 ****
  }


! tree *
  tree_block (tree t)
  {
    char const c = TREE_CODE_CLASS (TREE_CODE (t));

    if (IS_EXPR_CODE_CLASS (c))
!     return &t->exp.block;
    gcc_unreachable ();
    return NULL;
  }

  /* 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.  */
--- 10866,10893 ----
  }


! tree
  tree_block (tree t)
  {
    char const c = TREE_CODE_CLASS (TREE_CODE (t));

    if (IS_EXPR_CODE_CLASS (c))
!     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 (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 189835)
--- gcc/tree.h	(working copy)
*************** extern void omp_clause_range_check_faile
*** 999,1005 ****

  #endif

! #define TREE_BLOCK(NODE)		*(tree_block (NODE))

  #include "tree-check.h"

--- 999,1006 ----

  #endif

! #define TREE_BLOCK(NODE)		(tree_block (NODE))
! #define TREE_SET_BLOCK(T, B)		(tree_set_block ((T), (B)))

  #include "tree-check.h"

*************** struct GTY(()) tree_constructor {
*** 1702,1708 ****
  #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)
  /* 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)
--- 1703,1709 ----
  #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) (!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)
*************** extern void protected_set_expr_location
*** 1881,1887 ****
  					      OMP_CLAUSE_PRIVATE,	\
  	                                      OMP_CLAUSE_COPYPRIVATE), 0)
  #define OMP_CLAUSE_HAS_LOCATION(NODE) \
!   ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus != UNKNOWN_LOCATION)
  #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,1888 ----
  					      OMP_CLAUSE_PRIVATE,	\
  	                                      OMP_CLAUSE_COPYPRIVATE), 0)
  #define OMP_CLAUSE_HAS_LOCATION(NODE) \
!   (!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.
*************** enum omp_clause_default_kind
*** 1972,1978 ****
  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];
--- 1973,1978 ----
*************** function_args_iter_next (function_args_i
*** 5164,5170 ****
  static inline bool
  inlined_function_outer_scope_p (const_tree block)
  {
!  return BLOCK_SOURCE_LOCATION (block) != UNKNOWN_LOCATION;
  }

  /* Loop over all function arguments of FNTYPE.  In each iteration, PTR is set
--- 5164,5170 ----
  static inline bool
  inlined_function_outer_scope_p (const_tree block)
  {
!  return !IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (block));
  }

  /* Loop over all function arguments of FNTYPE.  In each iteration, PTR is set
*************** extern bool subrange_type_for_debug_p (c
*** 5539,5545 ****
  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 location_t *block_nonartificial_location (tree);
  extern location_t tree_nonartificial_location (tree);

--- 5539,5546 ----
  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 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 189835)
--- gcc/final.c	(working copy)
*************** reemit_insn_block_notes (void)
*** 1605,1611 ****
  					     insn_scope (XVECEXP (body, 0, i)));
  	}
        if (! this_block)
! 	continue;

        if (this_block != cur_block)
  	{
--- 1605,1611 ----
  					     insn_scope (XVECEXP (body, 0, i)));
  	}
        if (! this_block)
! 	this_block = DECL_INITIAL (cfun->decl);

        if (this_block != cur_block)
  	{
*************** final_start_function (rtx first ATTRIBUT
*** 1640,1647 ****

    this_is_asm_operands = 0;

!   last_filename = locator_file (prologue_locator);
!   last_linenum = locator_line (prologue_locator);
    last_discriminator = discriminator = 0;

    high_block_linenum = high_function_linenum = last_linenum;
--- 1640,1647 ----

    this_is_asm_operands = 0;

!   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 189835)
--- gcc/input.c	(working copy)
*************** expand_location_1 (source_location loc,
*** 51,56 ****
--- 51,63 ----
    expanded_location xloc;
    const struct line_map *map;
    enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
+   tree block = NULL;
+
+   if (IS_COMBINED_LOCATION (loc))
+     {
+       block = LOCATION_BLOCK (loc);
+       loc = LOCATION_LOCUS (loc);
+     }

    memset (&xloc, 0, sizeof (xloc));

*************** expand_location_1 (source_location loc,
*** 74,79 ****
--- 81,87 ----
        xloc = linemap_expand_location (line_table, map, loc);
      }

+   xloc.block = block;
    if (loc <= BUILTINS_LOCATION)
      xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");

Index: gcc/input.h
===================================================================
*** gcc/input.h	(revision 189835)
--- gcc/input.h	(working copy)
*************** extern location_t input_location;
*** 51,56 ****
--- 51,64 ----
  #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_COMBINED_LOCATION(LOC)) ? get_locus_from_location (LOC) : (LOC))
+ #define LOCATION_BLOCK(LOC) \
+   ((tree) ((IS_COMBINED_LOCATION (LOC)) ? get_block_from_location (LOC) \
+   : NULL))
+ #define IS_UNKNOWN_LOCATION(LOC) \
+   ((IS_COMBINED_LOCATION (LOC)) ? get_locus_from_location (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 189835)
--- gcc/fold-const.c	(working copy)
*************** static location_t
*** 145,151 ****
  expr_location_or (tree t, location_t loc)
  {
    location_t tloc = EXPR_LOCATION (t);
!   return tloc != UNKNOWN_LOCATION ? tloc : loc;
  }

  /* Similar to protected_set_expr_location, but never modify x in place,
--- 145,151 ----
  expr_location_or (tree t, location_t loc)
  {
    location_t tloc = EXPR_LOCATION (t);
!   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 189835)
--- gcc/toplev.c	(working copy)
*************** general_init (const char *argv0)
*** 1140,1145 ****
--- 1140,1146 ----
    linemap_init (line_table);
    line_table->reallocator = realloc_for_line_map;
    line_table->round_alloc_size = ggc_round_alloc_size;
+   location_block_init ();
    init_ttree ();

    /* Initialize register usage now so switches may override.  */
*************** toplev_main (int argc, char **argv)
*** 1946,1951 ****
--- 1947,1953 ----
    invoke_plugin_callbacks (PLUGIN_FINISH, NULL);

    finalize_plugins ();
+   location_block_fini ();
    if (seen_error ())
      return (FATAL_EXIT_CODE);

Index: gcc/reorg.c
===================================================================
*** gcc/reorg.c	(revision 189835)
--- gcc/reorg.c	(working copy)
*************** emit_delay_sequence (rtx insn, rtx list,
*** 545,551 ****
    INSN_DELETED_P (delay_insn) = 0;
    PREV_INSN (delay_insn) = PREV_INSN (seq_insn);

!   INSN_LOCATOR (seq_insn) = INSN_LOCATOR (delay_insn);

    for (li = list; li; li = XEXP (li, 1), i++)
      {
--- 545,551 ----
    INSN_DELETED_P (delay_insn) = 0;
    PREV_INSN (delay_insn) = PREV_INSN (seq_insn);

!   INSN_LOCATION (seq_insn) = INSN_LOCATION (delay_insn);

    for (li = list; li; li = XEXP (li, 1), i++)
      {
*************** emit_delay_sequence (rtx insn, rtx list,
*** 561,569 ****

        /* 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;

        for (note = REG_NOTES (tem); note; note = next)
  	{
--- 561,569 ----

        /* SPARC assembler, for instance, emit warning when debug info is output
           into the delay slot.  */
!       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)
  	{
*************** dbr_schedule (rtx first)
*** 4087,4093 ****
      for (link = crtl->epilogue_delay_list;
           link;
           link = XEXP (link, 1))
!       INSN_LOCATOR (XEXP (link, 0)) = 0;
    }

  #endif
--- 4087,4093 ----
      for (link = crtl->epilogue_delay_list;
           link;
           link = XEXP (link, 1))
!       INSN_LOCATION (XEXP (link, 0)) = 0;
    }

  #endif
Index: gcc/modulo-sched.c
===================================================================
*** gcc/modulo-sched.c	(revision 189835)
--- gcc/modulo-sched.c	(working copy)
*************** loop_single_full_bb_p (struct loop *loop
*** 1246,1254 ****
  /* Dump file:line from INSN's location info to dump_file.  */

  static void
! dump_insn_locator (rtx insn)
  {
!   if (dump_file && INSN_LOCATOR (insn))
      {
        const char *file = insn_file (insn);
        if (file)
--- 1246,1254 ----
  /* Dump file:line from INSN's location info to dump_file.  */

  static void
! dump_insn_location (rtx insn)
  {
!   if (dump_file && INSN_LOCATION (insn))
      {
        const char *file = insn_file (insn);
        if (file)
*************** loop_canon_p (struct loop *loop)
*** 1282,1288 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many exits");
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
--- 1282,1288 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many exits");
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
*************** loop_canon_p (struct loop *loop)
*** 1295,1301 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many BBs.");
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
--- 1295,1301 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many BBs.");
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
*************** sms_schedule (void)
*** 1421,1427 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}

--- 1421,1427 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}

*************** sms_schedule (void)
*** 1450,1456 ****
  	{
  	  if (dump_file)
  	    {
! 	      dump_insn_locator (tail);
  	      fprintf (dump_file, "\nSMS single-bb-loop\n");
  	      if (profile_info && flag_branch_probabilities)
  	    	{
--- 1450,1456 ----
  	{
  	  if (dump_file)
  	    {
! 	      dump_insn_location (tail);
  	      fprintf (dump_file, "\nSMS single-bb-loop\n");
  	      if (profile_info && flag_branch_probabilities)
  	    	{
*************** sms_schedule (void)
*** 1556,1562 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");

  	  print_ddg (dump_file, g);
--- 1556,1562 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");

  	  print_ddg (dump_file, g);
*************** sms_schedule (void)
*** 1571,1577 ****

        if (dump_file)
  	{
! 	  dump_insn_locator (tail);
  	  fprintf (dump_file, "\nSMS single-bb-loop\n");
  	  if (profile_info && flag_branch_probabilities)
  	    {
--- 1571,1577 ----

        if (dump_file)
  	{
! 	  dump_insn_location (tail);
  	  fprintf (dump_file, "\nSMS single-bb-loop\n");
  	  if (profile_info && flag_branch_probabilities)
  	    {
*************** sms_schedule (void)
*** 1714,1720 ****

            if (dump_file)
              {
! 	      dump_insn_locator (tail);
  	      fprintf (dump_file, " SMS succeeded %d %d (with ii, sc)\n",
  		       ps->ii, stage_count);
  	      print_partial_schedule (ps, dump_file);
--- 1714,1720 ----

            if (dump_file)
              {
! 	      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 189835)
--- gcc/lto-streamer-out.c	(working copy)
*************** lto_output_location_bitpack (struct bitp
*** 155,160 ****
--- 155,161 ----
  {
    expanded_location xloc;

+   loc = LOCATION_LOCUS (loc);
    bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
    if (loc == UNKNOWN_LOCATION)
      return;
Index: gcc/jump.c
===================================================================
*** gcc/jump.c	(revision 189835)
--- gcc/jump.c	(working copy)
*************** rtx_renumbered_equal_p (const_rtx x, con
*** 1818,1825 ****
  	  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)))
  		break;
  	      return 0;
  	    }
--- 1818,1824 ----
  	  if (XINT (x, i) != XINT (y, i))
  	    {
  	      if (((code == ASM_OPERANDS && i == 6)
! 		   || (code == ASM_INPUT && i == 1)))
  		break;
  	      return 0;
  	    }
Index: gcc/ifcvt.c
===================================================================
*** gcc/ifcvt.c	(revision 189835)
--- gcc/ifcvt.c	(working copy)
*************** noce_try_move (struct noce_if_info *if_i
*** 1019,1025 ****
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	}
        return TRUE;
      }
--- 1019,1025 ----
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	}
        return TRUE;
      }
*************** noce_try_store_flag (struct noce_if_info
*** 1064,1070 ****
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
        return TRUE;
      }
    else
--- 1064,1070 ----
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
        return TRUE;
      }
    else
*************** noce_try_store_flag_constants (struct no
*** 1195,1201 ****
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
        return TRUE;
      }

--- 1195,1201 ----
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
        return TRUE;
      }

*************** noce_try_addcc (struct noce_if_info *if_
*** 1243,1249 ****
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATOR (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
--- 1243,1249 ----
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATION (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
*************** noce_try_addcc (struct noce_if_info *if_
*** 1283,1289 ****
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATOR (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
--- 1283,1289 ----
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATION (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
*************** noce_try_store_flag_mask (struct noce_if
*** 1332,1338 ****
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	  return TRUE;
  	}

--- 1332,1338 ----
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	  return TRUE;
  	}

*************** noce_try_cmove (struct noce_if_info *if_
*** 1481,1487 ****
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	  return TRUE;
  	}
        else
--- 1481,1487 ----
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	  return TRUE;
  	}
        else
*************** noce_try_cmove_arith (struct noce_if_inf
*** 1682,1688 ****
    if (!tmp)
      return FALSE;

!   emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    return TRUE;

   end_seq_and_fail:
--- 1682,1688 ----
    if (!tmp)
      return FALSE;

!   emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    return TRUE;

   end_seq_and_fail:
*************** noce_try_minmax (struct noce_if_info *if
*** 1929,1935 ****
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

--- 1929,1935 ----
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

*************** noce_try_abs (struct noce_if_info *if_in
*** 2076,2082 ****
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

--- 2076,2082 ----
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

*************** noce_try_sign_mask (struct noce_if_info
*** 2155,2161 ****
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    return TRUE;
  }

--- 2155,2161 ----
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    return TRUE;
  }

*************** noce_try_bitop (struct noce_if_info *if_
*** 2255,2261 ****
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
      }
    return TRUE;
  }
--- 2255,2261 ----
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
      }
    return TRUE;
  }
*************** noce_process_if_block (struct noce_if_in
*** 2656,2662 ****
        unshare_all_rtl_in_chain (seq);
        end_sequence ();

!       emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATOR (insn_a));
      }

    /* The original THEN and ELSE blocks may now be removed.  The test block
--- 2656,2662 ----
        unshare_all_rtl_in_chain (seq);
        end_sequence ();

!       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
*************** cond_move_process_if_block (struct noce_
*** 2937,2943 ****
        loc_insn = first_active_insn (else_bb);
        gcc_assert (loc_insn);
      }
!   emit_insn_before_setloc (seq, jump, INSN_LOCATOR (loc_insn));

    if (else_bb)
      {
--- 2937,2943 ----
        loc_insn = first_active_insn (else_bb);
        gcc_assert (loc_insn);
      }
!   emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));

    if (else_bb)
      {
*************** find_cond_trap (basic_block test_bb, edg
*** 3655,3661 ****
      return FALSE;

    /* Emit the new insns before cond_earliest.  */
!   emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATOR (trap));

    /* Delete the trap block if possible.  */
    remove_edge (trap_bb == then_bb ? then_edge : else_edge);
--- 3655,3661 ----
      return FALSE;

    /* Emit the new insns before cond_earliest.  */
!   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/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c	(revision 189835)
--- gcc/dwarf2out.c	(working copy)
*************** add_src_coords_attributes (dw_die_ref di
*** 15506,15512 ****
  {
    expanded_location s;

!   if (DECL_SOURCE_LOCATION (decl) == UNKNOWN_LOCATION)
      return;
    s = expand_location (DECL_SOURCE_LOCATION (decl));
    add_AT_file (die, DW_AT_decl_file, lookup_filename (s.file));
--- 15506,15512 ----
  {
    expanded_location s;

!   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 189835)
--- gcc/expr.c	(working copy)
*************** expand_expr_real (tree exp, rtx target,
*** 7802,7820 ****
    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 ();
        input_location = EXPR_LOCATION (exp);
!       set_curr_insn_source_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);
      }
    else
      {
--- 7802,7815 ----
    if (cfun && EXPR_HAS_LOCATION (exp))
      {
        location_t saved_location = input_location;
!       location_t saved_curr_loc = curr_insn_location ();
        input_location = EXPR_LOCATION (exp);
!       set_curr_insn_location (input_location);

        ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);

        input_location = saved_location;
!       set_curr_insn_location (saved_curr_loc);
      }
    else
      {
Index: gcc/predict.c
===================================================================
*** gcc/predict.c	(revision 189835)
--- gcc/predict.c	(working copy)
*************** tree_estimate_probability_driver (void)
*** 2177,2183 ****
  {
    unsigned nb_loops;

!   loop_optimizer_init (0);
    if (dump_file && (dump_flags & TDF_DETAILS))
      flow_loops_dump (dump_file, NULL, 0);

--- 2177,2183 ----
  {
    unsigned nb_loops;

!   loop_optimizer_init (LOOPS_NORMAL);
    if (dump_file && (dump_flags & TDF_DETAILS))
      flow_loops_dump (dump_file, NULL, 0);

Index: gcc/tree-parloops.c
===================================================================
*** gcc/tree-parloops.c	(revision 189835)
--- gcc/tree-parloops.c	(working copy)
*************** create_loop_fn (location_t loc)
*** 1415,1420 ****
--- 1415,1421 ----
    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 189835)
--- gcc/recog.c	(working copy)
*************** peep2_attempt (basic_block bb, rtx insn,
*** 3333,3339 ****
    /* 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));
    before_try = PREV_INSN (insn);
    delete_insn_chain (insn, peep2_insn_data[i].insn, false);

--- 3333,3339 ----
    /* Replace the old sequence with the new.  */
    last = emit_insn_after_setloc (attempt,
  				 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 189835)
--- gcc/function.c	(working copy)
*************** static bool contains (const_rtx, htab_t)
*** 133,139 ****
  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;
  \f
  /* Stack of nested functions.  */
  /* Keep track of the cfun stack.  */
--- 133,139 ----
  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_locations (rtx, int) ATTRIBUTE_UNUSED;
  \f
  /* Stack of nested functions.  */
  /* Keep track of the cfun stack.  */
*************** free_after_compilation (struct function
*** 200,206 ****
    f->cfg = NULL;

    regno_reg_rtx = NULL;
-   insn_locators_free ();
  }
  \f
  /* Return size needed for stack frame based on slots so far allocated.
--- 200,205 ----
*************** expand_function_end (void)
*** 4979,4985 ****
  	      probe_stack_range (STACK_OLD_CHECK_PROTECT, max_frame_size);
  	    seq = get_insns ();
  	    end_sequence ();
! 	    set_insn_locators (seq, prologue_locator);
  	    emit_insn_before (seq, stack_check_probe_note);
  	    break;
  	  }
--- 4978,4984 ----
  	      probe_stack_range (STACK_OLD_CHECK_PROTECT, max_frame_size);
  	    seq = get_insns ();
  	    end_sequence ();
! 	    set_insn_locations (seq, prologue_location);
  	    emit_insn_before (seq, stack_check_probe_note);
  	    break;
  	  }
*************** expand_function_end (void)
*** 4994,5000 ****

    /* Output a linenumber for the end of the function.
       SDB depends on this.  */
!   set_curr_insn_source_location (input_location);

    /* Before the return label (if any), clobber the return
       registers so that they are not propagated live to the rest of
--- 4993,4999 ----

    /* Output a linenumber for the end of the function.
       SDB depends on this.  */
!   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
*************** maybe_copy_prologue_epilogue_insn (rtx i
*** 5277,5290 ****
    *slot = copy;
  }

! /* Set the locator of the insn chain starting at INSN to LOC.  */
  static void
! set_insn_locators (rtx insn, int loc)
  {
    while (insn != NULL_RTX)
      {
        if (INSN_P (insn))
! 	INSN_LOCATOR (insn) = loc;
        insn = NEXT_INSN (insn);
      }
  }
--- 5276,5289 ----
    *slot = copy;
  }

! /* Set the location of the insn chain starting at INSN to LOC.  */
  static void
! set_insn_locations (rtx insn, int loc)
  {
    while (insn != NULL_RTX)
      {
        if (INSN_P (insn))
! 	INSN_LOCATION (insn) = loc;
        insn = NEXT_INSN (insn);
      }
  }
*************** thread_prologue_and_epilogue_insns (void
*** 5893,5899 ****
        end_sequence ();

        record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
!       set_insn_locators (split_prologue_seq, prologue_locator);
  #endif
      }

--- 5892,5898 ----
        end_sequence ();

        record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
!       set_insn_locations (split_prologue_seq, prologue_location);
  #endif
      }

*************** thread_prologue_and_epilogue_insns (void
*** 5922,5928 ****

        prologue_seq = get_insns ();
        end_sequence ();
!       set_insn_locators (prologue_seq, prologue_locator);
      }
  #endif

--- 5921,5927 ----

        prologue_seq = get_insns ();
        end_sequence ();
!       set_insn_locations (prologue_seq, prologue_location);
      }
  #endif

*************** thread_prologue_and_epilogue_insns (void
*** 6418,6424 ****

        /* Retain a map of the epilogue insns.  */
        record_insns (seq, NULL, &epilogue_insn_hash);
!       set_insn_locators (seq, epilogue_locator);

        seq = get_insns ();
        returnjump = get_last_insn ();
--- 6417,6423 ----

        /* Retain a map of the epilogue insns.  */
        record_insns (seq, NULL, &epilogue_insn_hash);
!       set_insn_locations (seq, epilogue_location);

        seq = get_insns ();
        returnjump = get_last_insn ();
*************** epilogue_done:
*** 6608,6614 ****
  	     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);

  	  emit_insn_before (seq, insn);
  	}
--- 6607,6613 ----
  	     avoid getting rid of sibcall epilogue insns.  Do this before we
  	     actually emit the sequence.  */
  	  record_insns (seq, NULL, &epilogue_insn_hash);
! 	  set_insn_locations (seq, epilogue_location);

  	  emit_insn_before (seq, insn);
  	}
Index: gcc/print-rtl.c
===================================================================
*** gcc/print-rtl.c	(revision 189835)
--- gcc/print-rtl.c	(working copy)
*************** print_rtx (const_rtx in_rtx)
*** 416,425 ****
  	if (i == 5 && INSN_P (in_rtx))
  	  {
  #ifndef GENERATOR_FILE
! 	    /*  Pretty-print insn locators.  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))
  	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
  #endif
  	  }
--- 416,425 ----
  	if (i == 5 && INSN_P (in_rtx))
  	  {
  #ifndef GENERATOR_FILE
! 	    /*  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_LOCATION (in_rtx) && insn_file (in_rtx))
  	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
  #endif
  	  }
*************** print_rtx (const_rtx in_rtx)
*** 427,442 ****
  	  {
  #ifndef GENERATOR_FILE
  	    fprintf (outfile, " %s:%i",
! 		     locator_file (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)),
! 		     locator_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)));
  #endif
  	  }
  	else if (i == 6 && NOTE_P (in_rtx))
--- 427,442 ----
  	  {
  #ifndef GENERATOR_FILE
  	    fprintf (outfile, " %s:%i",
! 		     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",
! 		     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 189835)
--- gcc/profile.c	(working copy)
*************** branch_prob (void)
*** 966,972 ****
  	     is not computed twice.  */
  	  if (last
  	      && gimple_has_location (last)
! 	      && e->goto_locus != UNKNOWN_LOCATION
  	      && !single_succ_p (bb)
  	      && (LOCATION_FILE (e->goto_locus)
  	          != LOCATION_FILE (gimple_location (last))
--- 966,972 ----
  	     is not computed twice.  */
  	  if (last
  	      && gimple_has_location (last)
! 	      && !IS_UNKNOWN_LOCATION (e->goto_locus)
  	      && !single_succ_p (bb)
  	      && (LOCATION_FILE (e->goto_locus)
  	          != LOCATION_FILE (gimple_location (last))
*************** branch_prob (void)
*** 976,982 ****
  	      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)
--- 976,981 ----
*************** branch_prob (void)
*** 1188,1194 ****

  	  /* Notice GOTO expressions eliminated while constructing the CFG.  */
  	  if (single_succ_p (bb)
! 	      && single_succ_edge (bb)->goto_locus != UNKNOWN_LOCATION)
  	    {
  	      expanded_location curr_location
  		= expand_location (single_succ_edge (bb)->goto_locus);
--- 1187,1193 ----

  	  /* Notice GOTO expressions eliminated while constructing the CFG.  */
  	  if (single_succ_p (bb)
! 	      && !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 189835)
--- gcc/trans-mem.c	(working copy)
*************** ipa_tm_scan_irr_block (basic_block bb)
*** 3796,3802 ****
  	    {
  	      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;
--- 3796,3801 ----
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c	(revision 189835)
--- gcc/gimplify.c	(working copy)
*************** gimplify_call_expr (tree *expr_p, gimple
*** 2600,2606 ****
  	    = 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;
--- 2600,2605 ----
Index: gcc/except.c
===================================================================
*** gcc/except.c	(revision 189835)
--- gcc/except.c	(working copy)
*************** duplicate_eh_regions_1 (struct duplicate
*** 526,532 ****
        break;

      case ERT_MUST_NOT_THROW:
!       new_r->u.must_not_throw = old_r->u.must_not_throw;
        break;
      }

--- 526,535 ----
        break;

      case ERT_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 189835)
--- gcc/emit-rtl.c	(working copy)
*************** try_split (rtx pat, rtx trial, int last)
*** 3634,3640 ****
  	}
      }

!   tem = emit_insn_after_setloc (seq, trial, INSN_LOCATOR (trial));

    delete_insn (trial);
    if (has_barrier)
--- 3634,3640 ----
  	}
      }

!   tem = emit_insn_after_setloc (seq, trial, INSN_LOCATION (trial));

    delete_insn (trial);
    if (has_barrier)
*************** make_insn_raw (rtx pattern)
*** 3670,3676 ****
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

  #ifdef ENABLE_RTL_CHECKING
--- 3670,3676 ----
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

  #ifdef ENABLE_RTL_CHECKING
*************** make_debug_insn_raw (rtx pattern)
*** 3703,3709 ****
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
--- 3703,3709 ----
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
*************** make_jump_insn_raw (rtx pattern)
*** 3723,3729 ****
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    JUMP_LABEL (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
--- 3723,3729 ----
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    JUMP_LABEL (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
*************** make_call_insn_raw (rtx pattern)
*** 3743,3749 ****
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    CALL_INSN_FUNCTION_USAGE (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
--- 3743,3749 ----
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    CALL_INSN_FUNCTION_USAGE (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
*************** emit_pattern_after_setloc (rtx pattern,
*** 4416,4423 ****
    after = NEXT_INSN (after);
    while (1)
      {
!       if (active_insn_p (after) && !INSN_LOCATOR (after))
! 	INSN_LOCATOR (after) = loc;
        if (after == last)
  	break;
        after = NEXT_INSN (after);
--- 4416,4423 ----
    after = NEXT_INSN (after);
    while (1)
      {
!       if (active_insn_p (after) && !INSN_LOCATION (after))
! 	INSN_LOCATION (after) = loc;
        if (after == last)
  	break;
        after = NEXT_INSN (after);
*************** emit_pattern_after (rtx pattern, rtx aft
*** 4440,4501 ****
        prev = PREV_INSN (prev);

    if (INSN_P (prev))
!     return emit_pattern_after_setloc (pattern, after, INSN_LOCATOR (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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  rtx
  emit_debug_insn_after (rtx pattern, rtx after)
  {
--- 4440,4501 ----
        prev = PREV_INSN (prev);

    if (INSN_P (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_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_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_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_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_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_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_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_LOCATION according
to AFTER.  */
  rtx
  emit_debug_insn_after (rtx pattern, rtx after)
  {
*************** emit_pattern_before_setloc (rtx pattern,
*** 4525,4532 ****
      first = NEXT_INSN (first);
    while (1)
      {
!       if (active_insn_p (first) && !INSN_LOCATOR (first))
! 	INSN_LOCATOR (first) = loc;
        if (first == last)
  	break;
        first = NEXT_INSN (first);
--- 4525,4532 ----
      first = NEXT_INSN (first);
    while (1)
      {
!       if (active_insn_p (first) && !INSN_LOCATION (first))
! 	INSN_LOCATION (first) = loc;
        if (first == last)
  	break;
        first = NEXT_INSN (first);
*************** emit_pattern_before (rtx pattern, rtx be
*** 4550,4556 ****
        next = PREV_INSN (next);

    if (INSN_P (next))
!     return emit_pattern_before_setloc (pattern, before, INSN_LOCATOR (next),
  				       insnp, make_raw);
    else
      return emit_pattern_before_noloc (pattern, before,
--- 4550,4556 ----
        next = PREV_INSN (next);

    if (INSN_P (next))
!     return emit_pattern_before_setloc (pattern, before, INSN_LOCATION (next),
  				       insnp, make_raw);
    else
      return emit_pattern_before_noloc (pattern, before,
*************** emit_pattern_before (rtx pattern, rtx be
*** 4558,4564 ****
                                        NULL, make_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4558,4564 ----
                                        NULL, make_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_insn_before_setloc (rtx pattern, rt
*** 4566,4579 ****
  				     make_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR 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.  */
  rtx
  emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4566,4579 ----
  				     make_insn_raw);
  }

! /* 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_LOCATION according to LOC.  */
  rtx
  emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_jump_insn_before_setloc (rtx patter
*** 4581,4587 ****
  				     make_jump_insn_raw);
  }

! /* Like emit_jump_insn_before_noloc, but set INSN_LOCATOR according
to BEFORE.  */
  rtx
  emit_jump_insn_before (rtx pattern, rtx before)
  {
--- 4581,4587 ----
  				     make_jump_insn_raw);
  }

! /* Like emit_jump_insn_before_noloc, but set INSN_LOCATION according
to BEFORE.  */
  rtx
  emit_jump_insn_before (rtx pattern, rtx before)
  {
*************** emit_jump_insn_before (rtx pattern, rtx
*** 4589,4595 ****
  			      make_jump_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4589,4595 ----
  			      make_jump_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_call_insn_before_setloc (rtx patter
*** 4598,4604 ****
  }

  /* Like emit_call_insn_before_noloc,
!    but set insn_locator according to BEFORE.  */
  rtx
  emit_call_insn_before (rtx pattern, rtx before)
  {
--- 4598,4604 ----
  }

  /* Like emit_call_insn_before_noloc,
!    but set insn_location according to BEFORE.  */
  rtx
  emit_call_insn_before (rtx pattern, rtx before)
  {
*************** emit_call_insn_before (rtx pattern, rtx
*** 4606,4612 ****
  			      make_call_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4606,4612 ----
  			      make_call_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_debug_insn_before_setloc (rtx patte
*** 4615,4621 ****
  }

  /* Like emit_debug_insn_before_noloc,
!    but set insn_locator according to BEFORE.  */
  rtx
  emit_debug_insn_before (rtx pattern, rtx before)
  {
--- 4615,4621 ----
  }

  /* Like emit_debug_insn_before_noloc,
!    but set insn_location according to BEFORE.  */
  rtx
  emit_debug_insn_before (rtx pattern, rtx before)
  {
*************** emit_copy_of_insn_after (rtx insn, rtx a
*** 5865,5871 ****
    /* Update LABEL_NUSES.  */
    mark_jump_label (PATTERN (new_rtx), new_rtx, 0);

!   INSN_LOCATOR (new_rtx) = INSN_LOCATOR (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,
--- 5865,5871 ----
    /* Update LABEL_NUSES.  */
    mark_jump_label (PATTERN (new_rtx), new_rtx, 0);

!   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,
*************** gen_hard_reg_clobber (enum machine_mode
*** 5900,6149 ****
  	    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_O(location_t);
! DEF_VEC_ALLOC_O(location_t,heap);
! static VEC(location_t,heap) *locations_locators_vals;
! int prologue_locator;
! int epilogue_locator;

  /* 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.  */
  void
! insn_locators_alloc (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);
!
    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)
! {
!   if (curr_rtl_loc >= 0)
!     epilogue_locator = curr_insn_locator ();
!   curr_rtl_loc = -1;
! }
!
! /* 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)
  {
-   /* 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)
  {
    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;
- }
- \f
-
- /* 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 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 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 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);
- }
- \f
-
  /* 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.  */
--- 5900,5965 ----
  	    gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
  }

! 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;

! /* Allocate insn location datastructure.  */
  void
! insn_locations_init (void)
  {
!   prologue_location = epilogue_location = 0;
    curr_location = UNKNOWN_LOCATION;
    last_location = UNKNOWN_LOCATION;
  }

  /* At the end of emit stage, clear current location.  */
  void
! insn_locations_finalize (void)
  {
!   epilogue_location = curr_location;
!   curr_location = UNKNOWN_LOCATION;
  }

  /* Set current location.  */
  void
! set_curr_insn_location (location_t location)
  {
    curr_location = location;
  }

  /* Get current location.  */
  location_t
! curr_insn_location (void)
  {
    return curr_location;
  }

  /* Return lexical scope block insn belongs to.  */
  tree
  insn_scope (const_rtx insn)
  {
!   return LOCATION_BLOCK (INSN_LOCATION (insn));
  }

  /* Return line number of the statement that produced this insn.  */
  int
  insn_line (const_rtx insn)
  {
!   return LOCATION_LINE (INSN_LOCATION (insn));
  }

  /* Return source file of the statement that produced this insn.  */
  const char *
  insn_file (const_rtx insn)
  {
!   return LOCATION_FILE (INSN_LOCATION (insn));
  }

  /* 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 189835)
--- gcc/cfgexpand.c	(working copy)
*************** gimple_assign_rhs_to_tree (gimple stmt)
*** 92,99 ****
  	   && gimple_location (stmt) != EXPR_LOCATION (t))
  	  || (gimple_block (stmt)
  	      && currently_expanding_to_rtl
! 	      && EXPR_P (t)
! 	      && gimple_block (stmt) != TREE_BLOCK (t)))
  	t = copy_node (t);
      }
    else
--- 92,98 ----
  	   && gimple_location (stmt) != EXPR_LOCATION (t))
  	  || (gimple_block (stmt)
  	      && currently_expanding_to_rtl
! 	      && EXPR_P (t)))
  	t = copy_node (t);
      }
    else
*************** gimple_assign_rhs_to_tree (gimple stmt)
*** 101,108 ****

    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;
  }
--- 100,105 ----
*************** expand_gimple_cond (basic_block bb, gimp
*** 1804,1811 ****
    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));

    /* These flags have no purpose in RTL land.  */
    true_edge->flags &= ~EDGE_TRUE_VALUE;
--- 1801,1807 ----
    last2 = last = get_last_insn ();

    extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
!   set_curr_insn_location (gimple_location (stmt));

    /* These flags have no purpose in RTL land.  */
    true_edge->flags &= ~EDGE_TRUE_VALUE;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1818,1830 ****
        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;
        false_edge->flags |= EDGE_FALLTHRU;
        maybe_cleanup_end_of_block (false_edge, last);
        return NULL;
--- 1814,1821 ----
        jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
  		true_edge->probability);
        maybe_dump_rtl_for_gimple_stmt (stmt, last);
!       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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1834,1846 ****
        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;
        true_edge->flags |= EDGE_FALLTHRU;
        maybe_cleanup_end_of_block (true_edge, last);
        return NULL;
--- 1825,1832 ----
        jumpifnot_1 (code, op0, op1, label_rtx_for_bb (false_edge->dest),
  		   false_edge->probability);
        maybe_dump_rtl_for_gimple_stmt (stmt, last);
!       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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1849,1861 ****
    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;
    emit_jump (label_rtx_for_bb (false_edge->dest));

    BB_END (bb) = last;
--- 1835,1842 ----
    jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
  	    true_edge->probability);
    last = get_last_insn ();
!   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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1880,1892 ****

    maybe_dump_rtl_for_gimple_stmt (stmt, last2);

!   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;

    return new_bb;
  }
--- 1861,1871 ----

    maybe_dump_rtl_for_gimple_stmt (stmt, last2);

!   if (!IS_UNKNOWN_LOCATION (true_edge->goto_locus))
      {
!       set_curr_insn_location (true_edge->goto_locus);
!       true_edge->goto_locus = curr_insn_location ();
      }

    return new_bb;
  }
*************** expand_call_stmt (gimple stmt)
*** 1986,1992 ****
      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))
--- 1965,1970 ----
*************** expand_gimple_stmt_1 (gimple stmt)
*** 2021,2028 ****
  {
    tree op0;

!   set_curr_insn_source_location (gimple_location (stmt));
!   set_curr_insn_block (gimple_block (stmt));

    switch (gimple_code (stmt))
      {
--- 1999,2005 ----
  {
    tree op0;

!   set_curr_insn_location (gimple_location (stmt));

    switch (gimple_code (stmt))
      {
*************** expand_gimple_basic_block (basic_block b
*** 3766,3773 ****
  	  tree op;
  	  gimple def;

! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();

  	  /* Look for SSA names that have their last use here (TERed
  	     names always have only one real use).  */
--- 3743,3749 ----
  	  tree op;
  	  gimple def;

! 	  location_t sloc = curr_insn_location ();

  	  /* Look for SSA names that have their last use here (TERed
  	     names always have only one real use).  */
*************** expand_gimple_basic_block (basic_block b
*** 3800,3807 ****
  		    rtx val;
  		    enum machine_mode mode;

! 		    set_curr_insn_source_location (gimple_location (def));
! 		    set_curr_insn_block (gimple_block (def));

  		    DECL_ARTIFICIAL (vexpr) = 1;
  		    TREE_TYPE (vexpr) = TREE_TYPE (value);
--- 3776,3782 ----
  		    rtx val;
  		    enum machine_mode mode;

! 		    set_curr_insn_location (gimple_location (def));

  		    DECL_ARTIFICIAL (vexpr) = 1;
  		    TREE_TYPE (vexpr) = TREE_TYPE (value);
*************** expand_gimple_basic_block (basic_block b
*** 3828,3835 ****
  		      }
  		  }
  	      }
! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}

        currently_expanding_gimple_stmt = stmt;
--- 3803,3809 ----
  		      }
  		  }
  	      }
! 	  set_curr_insn_location (sloc);
  	}

        currently_expanding_gimple_stmt = stmt;
*************** expand_gimple_basic_block (basic_block b
*** 3844,3851 ****
  	}
        else if (gimple_debug_bind_p (stmt))
  	{
! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();
  	  gimple_stmt_iterator nsi = gsi;

  	  for (;;)
--- 3818,3824 ----
  	}
        else if (gimple_debug_bind_p (stmt))
  	{
! 	  location_t sloc = curr_insn_location ();
  	  gimple_stmt_iterator nsi = gsi;

  	  for (;;)
*************** expand_gimple_basic_block (basic_block b
*** 3867,3874 ****

  	      last = get_last_insn ();

! 	      set_curr_insn_source_location (gimple_location (stmt));
! 	      set_curr_insn_block (gimple_block (stmt));

  	      if (DECL_P (var))
  		mode = DECL_MODE (var);
--- 3840,3846 ----

  	      last = get_last_insn ();

! 	      set_curr_insn_location (gimple_location (stmt));

  	      if (DECL_P (var))
  		mode = DECL_MODE (var);
*************** expand_gimple_basic_block (basic_block b
*** 3906,3918 ****
  		break;
  	    }

! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}
        else if (gimple_debug_source_bind_p (stmt))
  	{
! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();
  	  tree var = gimple_debug_source_bind_get_var (stmt);
  	  tree value = gimple_debug_source_bind_get_value (stmt);
  	  rtx val;
--- 3878,3888 ----
  		break;
  	    }

! 	  set_curr_insn_location (sloc);
  	}
        else if (gimple_debug_source_bind_p (stmt))
  	{
! 	  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;
*************** expand_gimple_basic_block (basic_block b
*** 3920,3927 ****

  	  last = get_last_insn ();

! 	  set_curr_insn_source_location (gimple_location (stmt));
! 	  set_curr_insn_block (gimple_block (stmt));

  	  mode = DECL_MODE (var);

--- 3890,3896 ----

  	  last = get_last_insn ();

! 	  set_curr_insn_location (gimple_location (stmt));

  	  mode = DECL_MODE (var);

*************** expand_gimple_basic_block (basic_block b
*** 3939,3946 ****
  	      PAT_VAR_LOCATION_LOC (val) = (rtx)value;
  	    }

! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}
        else
  	{
--- 3908,3914 ----
  	      PAT_VAR_LOCATION_LOC (val) = (rtx)value;
  	    }

! 	  set_curr_insn_location (sloc);
  	}
        else
  	{
*************** expand_gimple_basic_block (basic_block b
*** 3981,3993 ****
    /* 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 ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb)
  	{
  	  emit_jump (label_rtx_for_bb (e->dest));
--- 3949,3956 ----
    /* Expand implicit goto and convert goto_locus.  */
    FOR_EACH_EDGE (e, ei, bb->succs)
      {
!       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));
*************** construct_exit_block (void)
*** 4107,4118 ****

    /* 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)
      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 ();

--- 4070,4078 ----

    /* Make sure the locus is set to the end of the function, so that
       epilogue line numbers and warnings are set properly.  */
!   if (!IS_UNKNOWN_LOCATION (cfun->function_end_locus))
      input_location = cfun->function_end_locus;

    /* Generate rtl for function exit.  */
    expand_function_end ();

*************** gimple_expand_cfg (void)
*** 4331,4350 ****

    rtl_profile_for_bb (ENTRY_BLOCK_PTR);

!   insn_locators_alloc ();
    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
           (DECL_SOURCE_LOCATION (current_function_decl));
        else
!        set_curr_insn_source_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 ();

  #ifdef INSN_SCHEDULING
    init_sched_attrs ();
--- 4291,4309 ----

    rtl_profile_for_bb (ENTRY_BLOCK_PTR);

!   insn_locations_init ();
    if (!DECL_IS_BUILTIN (current_function_decl))
      {
        /* Eventually, all FEs should explicitly set function_start_locus.  */
!       if (IS_UNKNOWN_LOCATION (cfun->function_start_locus))
!        set_curr_insn_location
           (DECL_SOURCE_LOCATION (current_function_decl));
        else
!        set_curr_insn_location (cfun->function_start_locus);
      }
    else
!     set_curr_insn_location (UNKNOWN_LOCATION);
!   prologue_location = curr_insn_location ();

  #ifdef INSN_SCHEDULING
    init_sched_attrs ();
*************** gimple_expand_cfg (void)
*** 4514,4521 ****
    free_histograms ();

    construct_exit_block ();
!   set_curr_insn_block (DECL_INITIAL (current_function_decl));
!   insn_locators_finalize ();

    /* Zap the tree EH table.  */
    set_eh_throw_stmt_table (cfun, NULL);
--- 4473,4479 ----
    free_histograms ();

    construct_exit_block ();
!   insn_locations_finalize ();

    /* Zap the tree EH table.  */
    set_eh_throw_stmt_table (cfun, NULL);
Index: gcc/cfgcleanup.c
===================================================================
*** gcc/cfgcleanup.c	(revision 189835)
--- gcc/cfgcleanup.c	(working copy)
*************** try_forward_edges (int mode, basic_block
*** 481,493 ****
  		  int new_locus = single_succ_edge (target)->goto_locus;
  		  int locus = goto_locus;

! 		  if (new_locus && locus && !locator_eq (new_locus, locus))
  		    new_target = NULL;
  		  else
  		    {
  		      rtx last;

! 		      if (new_locus)
  			locus = new_locus;

  		      last = BB_END (target);
--- 481,495 ----
  		  int new_locus = single_succ_edge (target)->goto_locus;
  		  int locus = goto_locus;

! 		  if (!IS_UNKNOWN_LOCATION (new_locus)
! 		      && !IS_UNKNOWN_LOCATION (locus)
! 		      && new_locus != locus)
  		    new_target = NULL;
  		  else
  		    {
  		      rtx last;

! 		      if (!IS_UNKNOWN_LOCATION (new_locus))
  			locus = new_locus;

  		      last = BB_END (target);
*************** try_forward_edges (int mode, basic_block
*** 495,507 ****
  			last = prev_nondebug_insn (last);

  		      new_locus = last && INSN_P (last)
! 				  ? INSN_LOCATOR (last) : 0;

! 		      if (new_locus && locus && !locator_eq (new_locus, locus))
  			new_target = NULL;
  		      else
  			{
! 			  if (new_locus)
  			    locus = new_locus;

  			  goto_locus = locus;
--- 497,511 ----
  			last = prev_nondebug_insn (last);

  		      new_locus = last && INSN_P (last)
! 				  ? INSN_LOCATION (last) : 0;

! 		      if (!IS_UNKNOWN_LOCATION (new_locus)
! 			  && !IS_UNKNOWN_LOCATION (locus)
! 			  && new_locus != locus)
  			new_target = NULL;
  		      else
  			{
! 			  if (!IS_UNKNOWN_LOCATION (new_locus))
  			    locus = new_locus;

  			  goto_locus = locus;
Index: gcc/tree-ssa-live.c
===================================================================
*** gcc/tree-ssa-live.c	(revision 189835)
--- gcc/tree-ssa-live.c	(working copy)
*************** remove_unused_scope_block_p (tree scope,
*** 587,593 ****
     else
     /* Verfify that only blocks with source location set
        are entry points to the inlined functions.  */
!      gcc_assert (BLOCK_SOURCE_LOCATION (scope) == UNKNOWN_LOCATION);

     TREE_USED (scope) = !unused;
     return unused;
--- 587,593 ----
     else
     /* Verfify that only blocks with source location set
        are entry points to the inlined functions.  */
!      gcc_assert (IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (scope)));

     TREE_USED (scope) = !unused;
     return unused;
*************** dump_scope_block (FILE *file, int indent
*** 615,621 ****
    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)
      {
        expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (scope));
        fprintf (file, " %s:%i", s.file, s.line);
--- 615,621 ----
    fprintf (file, "\n%*s{ Scope block #%i%s%s",indent, "" ,
BLOCK_NUMBER (scope),
    	   TREE_USED (scope) ? "" : " (unused)",
  	   BLOCK_ABSTRACT (scope) ? " (abstract)": "");
!   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);
*************** remove_unused_locals (void)
*** 765,777 ****
            FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_ALL_USES)
              {
  	      tree arg = USE_FROM_PTR (arg_p);
  	      mark_all_vars_used (&arg, global_unused_vars);
              }
          }

        FOR_EACH_EDGE (e, ei, bb->succs)
  	if (e->goto_locus)
! 	  TREE_USED (e->goto_block) = true;
      }

    /* We do a two-pass approach about the out-of-scope clobbers.  We want
--- 765,782 ----
            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, global_unused_vars);
              }
          }

        FOR_EACH_EDGE (e, ei, bb->succs)
  	if (e->goto_locus)
! 	  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 189835)
--- gcc/lto/lto.c	(working copy)
*************** lto_fixup_prevailing_decls (tree t)
*** 1603,1609 ****
    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));
      }
--- 1603,1608 ----
Index: gcc/tree-streamer-out.c
===================================================================
*** gcc/tree-streamer-out.c	(revision 189835)
--- gcc/tree-streamer-out.c	(working copy)
*************** write_ts_decl_minimal_tree_pointers (str
*** 471,477 ****
  {
    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));
  }


--- 471,477 ----
  {
    stream_write_tree (ob, DECL_NAME (expr), ref_p);
    stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
!   lto_output_location (ob, LOCATION_LOCUS (DECL_SOURCE_LOCATION (expr)));
  }


*************** write_ts_exp_tree_pointers (struct outpu
*** 668,674 ****
    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));
    stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
  }

--- 668,674 ----
    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, LOCATION_LOCUS (EXPR_LOCATION (expr)));
    stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
  }

Index: gcc/rtl.c
===================================================================
*** gcc/rtl.c	(revision 189835)
--- gcc/rtl.c	(working copy)
*************** rtx_equal_p_cb (const_rtx x, const_rtx y
*** 440,446 ****
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && locator_eq (XINT (x, i), XINT (y, i)))
  		break;
  #endif
  	      return 0;
--- 440,446 ----
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && XINT (x, i) == XINT (y, i))
  		break;
  #endif
  	      return 0;
*************** rtx_equal_p (const_rtx x, const_rtx y)
*** 579,585 ****
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && locator_eq (XINT (x, i), XINT (y, i)))
  		break;
  #endif
  	      return 0;
--- 579,585 ----
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && XINT (x, i) == XINT (y, i))
  		break;
  #endif
  	      return 0;
Index: gcc/rtl.h
===================================================================
*** gcc/rtl.h	(revision 189835)
--- gcc/rtl.h	(working copy)
*************** extern void rtl_check_failed_flag (const
*** 739,744 ****
--- 739,745 ----
  #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)
*************** extern void rtl_check_failed_flag (const
*** 802,814 ****
  /* The body of an insn.  */
  #define PATTERN(INSN)	XEXP (INSN, 4)

! #define INSN_LOCATOR(INSN) XINT (INSN, 5)
  /* 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 ()))

  /* Code number of instruction, from when it was recognized.
     -1 means this instruction has not been recognized yet.  */
--- 803,815 ----
  /* The body of an insn.  */
  #define PATTERN(INSN)	XEXP (INSN, 4)

! #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) ? \
! 			 INSN_LOCATION (X) : UNKNOWN_LOCATION)

  /* Code number of instruction, from when it was recognized.
     -1 means this instruction has not been recognized yet.  */
*************** extern rtx prev_cc0_setter (rtx);
*** 1807,1818 ****
  /* 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);

  /* In jump.c */
  extern enum rtx_code reverse_condition (enum rtx_code);
--- 1808,1815 ----
  /* In emit-rtl.c  */
  extern int insn_line (const_rtx);
  extern const char * insn_file (const_rtx);
  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);
*************** extern const struct rtl_hooks general_rt
*** 2648,2661 ****
  /* 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 bool optimize_insn_for_size_p (void);
  extern bool optimize_insn_for_speed_p (void);

--- 2645,2654 ----
  /* Keep this for the nonce.  */
  #define gen_lowpart rtl_hooks.gen_lowpart

! 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 189835)
--- gcc/tree-inline.c	(working copy)
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 852,861 ****
        /* 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);
--- 852,857 ----
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 901,913 ****
  	{
  	  /* 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.  */
  	  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,
--- 897,905 ----
  	{
  	  /* Variable substitution need not be simple.  In particular,
  	     the MEM_REF substitution above.  Make sure that
! 	     TREE_CONSTANT and friends are up-to-date.  */
  	  int invariant = is_gimple_min_invariant (*tp);
  	  walk_tree (&TREE_OPERAND (*tp, 0), remap_gimple_op_r, data, NULL);
  	  recompute_tree_invariant_for_addr_expr (*tp);

  	  /* If this used to be invariant, but is not any longer,
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 919,924 ****
--- 911,932 ----
  	}
      }

+   /* 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;
  }
*************** copy_tree_body_r (tree *tp, int *walk_su
*** 1144,1154 ****
  	      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;
  	}

        if (TREE_CODE (*tp) != OMP_CLAUSE)
--- 1152,1161 ----
  	      tree *n;
  	      n = (tree *) pointer_map_contains (id->decl_map,
  						 TREE_BLOCK (*tp));
  	      if (n)
  		new_block = *n;
  	    }
! 	  TREE_SET_BLOCK (*tp, new_block);
  	}

        if (TREE_CODE (*tp) != OMP_CLAUSE)
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 2020,2025 ****
--- 2027,2033 ----
  	      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
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 2031,2039 ****

  	      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.  */
--- 2039,2045 ----
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 2046,2053 ****
  		  gsi_insert_seq_on_edge (new_edge, stmts);
  		  inserted = true;
  		}
  	      add_phi_arg (new_phi, new_arg, new_edge,
! 			   gimple_phi_arg_location_from_edge (phi, old_edge));
  	    }
  	}
      }
--- 2052,2070 ----
  		  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,
! 			   COMBINE_LOCATION (locus, block));
  	    }
  	}
      }
*************** expand_call_inline (basic_block bb, gimp
*** 3946,3952 ****
    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);

    /* Local declarations will be replaced by their equivalents in this
       map.  */
--- 3963,3970 ----
    id->block = make_node (BLOCK);
    BLOCK_ABSTRACT_ORIGIN (id->block) = fn;
    BLOCK_SOURCE_LOCATION (id->block) = input_location;
!   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 189835)
--- gcc/tree-streamer-in.c	(working copy)
*************** lto_input_ts_exp_tree_pointers (struct l
*** 776,782 ****

    loc = lto_input_location (ib, data_in);
    SET_EXPR_LOCATION (expr, loc);
!   TREE_BLOCK (expr) = stream_read_tree (ib, data_in);
  }


--- 776,782 ----

    loc = lto_input_location (ib, data_in);
    SET_EXPR_LOCATION (expr, loc);
!   TREE_SET_BLOCK (expr, stream_read_tree (ib, data_in));
  }


Index: gcc/combine.c
===================================================================
*** gcc/combine.c	(revision 189835)
--- gcc/combine.c	(working copy)
*************** try_combine (rtx i3, rtx i2, rtx i1, rtx
*** 2896,2902 ****

  	  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);

  	  SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
  	  SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
--- 2896,2902 ----

  	  i1 = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
  			     BLOCK_FOR_INSN (i2), XVECEXP (PATTERN (i2), 0, 1),
! 			     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 189835)
--- gcc/tree-outof-ssa.c	(working copy)
*************** set_location_for_edge (edge e)
*** 108,115 ****
  {
    if (e->goto_locus)
      {
!       set_curr_insn_source_location (e->goto_locus);
!       set_curr_insn_block (e->goto_block);
      }
    else
      {
--- 108,114 ----
  {
    if (e->goto_locus)
      {
!       set_curr_insn_location (e->goto_locus);
      }
    else
      {
*************** set_location_for_edge (edge e)
*** 125,132 ****
  		continue;
  	      if (gimple_has_location (stmt) || gimple_block (stmt))
  		{
! 		  set_curr_insn_source_location (gimple_location (stmt));
! 		  set_curr_insn_block (gimple_block (stmt));
  		  return;
  		}
  	    }
--- 124,130 ----
  		continue;
  	      if (gimple_has_location (stmt) || gimple_block (stmt))
  		{
! 		  set_curr_insn_location (gimple_location (stmt));
  		  return;
  		}
  	    }
*************** insert_partition_copy_on_edge (edge e, i
*** 191,197 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);

    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (SA.partition_to_pseudo[dest],
--- 189,195 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_location (locus);

    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (SA.partition_to_pseudo[dest],
*************** insert_value_copy_on_edge (edge e, int d
*** 228,234 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);

    start_sequence ();

--- 226,232 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_location (locus);

    start_sequence ();

*************** insert_rtx_to_part_on_edge (edge e, int
*** 284,290 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_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
--- 282,288 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (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
*************** insert_part_to_rtx_on_edge (edge e, rtx
*** 320,326 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);

    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (dest,
--- 318,324 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (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 189835)
--- gcc/basic-block.h	(working copy)
*************** struct GTY(()) edge_def {
*** 47,54 ****
    /* Auxiliary info specific to a pass.  */
    PTR GTY ((skip (""))) aux;

!   /* Location of any goto implicit in the edge and associated BLOCK.  */
!   tree goto_block;
    location_t goto_locus;

    /* The index number corresponding to this edge in the edge vector
--- 47,53 ----
    /* Auxiliary info specific to a pass.  */
    PTR GTY ((skip (""))) aux;

!   /* 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 189835)
--- gcc/gimple.h	(working copy)
*************** struct GTY(()) gimple_statement_base {
*** 210,219 ****
       and the prev pointer being the last.  */
    gimple next;
    gimple GTY((skip)) prev;
-
-   /* [ WORD 6 ]
-      Lexical block holding this statement.  */
-   tree block;
  };


--- 210,215 ----
*************** gimple_bb (const_gimple g)
*** 1198,1204 ****
  static inline tree
  gimple_block (const_gimple g)
  {
!   return g->gsbase.block;
  }


--- 1194,1200 ----
  static inline tree
  gimple_block (const_gimple g)
  {
!   return LOCATION_BLOCK (g->gsbase.location);
  }


*************** gimple_block (const_gimple g)
*** 1207,1213 ****
  static inline void
  gimple_set_block (gimple g, tree block)
  {
!   g->gsbase.block = block;
  }


--- 1203,1209 ----
  static inline void
  gimple_set_block (gimple g, tree block)
  {
!   g->gsbase.location = COMBINE_LOCATION (g->gsbase.location, block);
  }


*************** gimple_set_location (gimple g, location_
*** 1242,1248 ****
  static inline bool
  gimple_has_location (const_gimple g)
  {
!   return gimple_location (g) != UNKNOWN_LOCATION;
  }


--- 1238,1244 ----
  static inline bool
  gimple_has_location (const_gimple g)
  {
!   return !IS_UNKNOWN_LOCATION (gimple_location (g));
  }


Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c	(revision 189835)
--- gcc/tree-cfg.c	(working copy)
*************** make_cond_expr_edges (basic_block bb)
*** 808,822 ****
    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.  */
--- 808,818 ----
*************** make_goto_expr_edges (basic_block bb)
*** 1026,1033 ****
        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;
      }
--- 1022,1027 ----
*************** gimple_can_merge_blocks_p (basic_block a
*** 1501,1507 ****

    /* When not optimizing, don't merge if we'd lose goto_locus.  */
    if (!optimize
!       && single_succ_edge (a)->goto_locus != UNKNOWN_LOCATION)
      {
        location_t goto_locus = single_succ_edge (a)->goto_locus;
        gimple_stmt_iterator prev, next;
--- 1495,1501 ----

    /* When not optimizing, don't merge if we'd lose goto_locus.  */
    if (!optimize
!       && single_succ_edge (a)->goto_locus)
      {
        location_t goto_locus = single_succ_edge (a)->goto_locus;
        gimple_stmt_iterator prev, next;
*************** move_stmt_op (tree *tp, int *walk_subtre
*** 5987,5995 ****
    tree t = *tp;

    if (EXPR_P (t))
!     /* We should never have TREE_BLOCK set on non-statements.  */
!     gcc_assert (!TREE_BLOCK (t));
!
    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
      {
        if (TREE_CODE (t) == SSA_NAME)
--- 5981,5987 ----
    tree t = *tp;

    if (EXPR_P (t))
!     ;
    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
      {
        if (TREE_CODE (t) == SSA_NAME)
*************** move_block_to_fn (struct function *dest_
*** 6294,6305 ****
      }

    FOR_EACH_EDGE (e, ei, bb->succs)
!     if (e->goto_locus)
        {
! 	tree block = e->goto_block;
  	if (d->orig_block == NULL_TREE
  	    || block == d->orig_block)
! 	  e->goto_block = d->new_block;
  #ifdef ENABLE_CHECKING
  	else if (block != d->new_block)
  	  {
--- 6286,6297 ----
      }

    FOR_EACH_EDGE (e, ei, bb->succs)
!     if (!IS_UNKNOWN_LOCATION (e->goto_locus))
        {
! 	tree block = LOCATION_BLOCK (e->goto_locus);
  	if (d->orig_block == NULL_TREE
  	    || block == d->orig_block)
! 	  e->goto_locus = COMBINE_LOCATION (e->goto_locus, d->new_block);
  #ifdef ENABLE_CHECKING
  	else if (block != d->new_block)
  	  {
Index: gcc/config/alpha/alpha.c
===================================================================
*** gcc/config/alpha/alpha.c	(revision 189835)
--- gcc/config/alpha/alpha.c	(working copy)
*************** alpha_output_mi_thunk_osf (FILE *file, t
*** 8352,8358 ****
       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);
--- 8352,8357 ----
Index: gcc/config/sparc/sparc.c
===================================================================
*** gcc/config/sparc/sparc.c	(revision 189835)
--- gcc/config/sparc/sparc.c	(working copy)
*************** sparc_output_mi_thunk (FILE *file, tree
*** 10654,10660 ****
       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);
--- 10654,10659 ----
Index: gcc/config/i386/i386.c
===================================================================
*** gcc/config/i386/i386.c	(revision 189835)
--- gcc/config/i386/i386.c	(working copy)
*************** x86_output_mi_thunk (FILE *file,
*** 33063,33069 ****
    /* 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);
--- 33063,33068 ----
Index: gcc/config/tilegx/tilegx.c
===================================================================
*** gcc/config/tilegx/tilegx.c	(revision 189835)
--- gcc/config/tilegx/tilegx.c	(working copy)
*************** tilegx_output_mi_thunk (FILE *file, tree
*** 4804,4810 ****
       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);
--- 4804,4809 ----
Index: gcc/config/sh/sh.c
===================================================================
*** gcc/config/sh/sh.c	(revision 189835)
--- gcc/config/sh/sh.c	(working copy)
*************** sh_output_mi_thunk (FILE *file, tree thu
*** 11979,11985 ****
       the insns emitted.  Note that use_thunk calls
       assemble_start_function and assemble_end_function.  */

-   insn_locators_alloc ();
    insns = get_insns ();

    if (optimize > 0)
--- 11979,11984 ----
Index: gcc/config/ia64/ia64.c
===================================================================
*** gcc/config/ia64/ia64.c	(revision 189835)
--- gcc/config/ia64/ia64.c	(working copy)
*************** ia64_output_mi_thunk (FILE *file, tree t
*** 10848,10854 ****
       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);
--- 10848,10853 ----
Index: gcc/config/rs6000/rs6000.c
===================================================================
*** gcc/config/rs6000/rs6000.c	(revision 189835)
--- gcc/config/rs6000/rs6000.c	(working copy)
*************** rs6000_output_mi_thunk (FILE *file, tree
*** 21664,21670 ****
       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);
--- 21664,21669 ----
Index: gcc/config/score/score.c
===================================================================
*** gcc/config/score/score.c	(revision 189835)
--- gcc/config/score/score.c	(working copy)
*************** score_output_mi_thunk (FILE *file, tree
*** 505,511 ****
    /* 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);
--- 505,510 ----
Index: gcc/config/tilepro/tilepro.c
===================================================================
*** gcc/config/tilepro/tilepro.c	(revision 189835)
--- gcc/config/tilepro/tilepro.c	(working copy)
*************** tilepro_asm_output_mi_thunk (FILE *file,
*** 4407,4413 ****
       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);
--- 4407,4412 ----
Index: gcc/config/mips/mips.c
===================================================================
*** gcc/config/mips/mips.c	(revision 189835)
--- gcc/config/mips/mips.c	(working copy)
*************** mips_output_mi_thunk (FILE *file, tree t
*** 15637,15643 ****
    /* 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 ();
    shorten_branches (insn);
--- 15637,15642 ----
Index: gcc/cfgrtl.c
===================================================================
*** gcc/cfgrtl.c	(revision 189835)
--- gcc/cfgrtl.c	(working copy)
*************** rtl_split_block (basic_block bb, void *i
*** 720,738 ****
  static bool
  unique_locus_on_edge_between_p (basic_block a, basic_block b)
  {
!   const int goto_locus = EDGE_SUCC (a, 0)->goto_locus;
    rtx insn, end;

!   if (!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))
      insn = PREV_INSN (insn);

!   if (insn != end && locator_eq (INSN_LOCATOR (insn), goto_locus))
      return false;

    /* Then scan block B forward.  */
--- 720,738 ----
  static bool
  unique_locus_on_edge_between_p (basic_block a, basic_block b)
  {
!   const location_t goto_locus = EDGE_SUCC (a, 0)->goto_locus;
    rtx insn, end;

!   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_HAS_LOCATION (insn)))
      insn = PREV_INSN (insn);

!   if (insn != end && INSN_LOCATION (insn) == goto_locus)
      return false;

    /* Then scan block B forward.  */
*************** unique_locus_on_edge_between_p (basic_bl
*** 743,750 ****
        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))
  	return false;
      }

--- 743,750 ----
        while (insn != end && !NONDEBUG_INSN_P (insn))
  	insn = NEXT_INSN (insn);

!       if (insn != end && INSN_HAS_LOCATION (insn)
! 	  && INSN_LOCATION (insn) == goto_locus)
  	return false;
      }

*************** emit_nop_for_unique_locus_between (basic
*** 761,767 ****
      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;
  }

  /* Blocks A and B are to be merged into a single block A.  The insns
--- 761,767 ----
      return;

    BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
!   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
*************** force_nonfallthru_and_redirect (edge e,
*** 1478,1484 ****
    else
      jump_block = e->src;

!   if (e->goto_locus && e->goto_block == NULL)
      loc = e->goto_locus;
    else
      loc = 0;
--- 1478,1484 ----
    else
      jump_block = e->src;

!   if (!IS_UNKNOWN_LOCATION (e->goto_locus))
      loc = e->goto_locus;
    else
      loc = 0;
*************** fixup_reorder_chain (void)
*** 3337,3343 ****
          edge_iterator ei;

          FOR_EACH_EDGE (e, ei, bb->succs)
! 	  if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
  	    {
  	      edge e2;
  	      edge_iterator ei2;
--- 3337,3344 ----
          edge_iterator ei;

          FOR_EACH_EDGE (e, ei, bb->succs)
! 	  if (!IS_UNKNOWN_LOCATION (e->goto_locus)
! 	      && !(e->flags & EDGE_ABNORMAL))
  	    {
  	      edge e2;
  	      edge_iterator ei2;
*************** fixup_reorder_chain (void)
*** 3347,3361 ****
  	      insn = BB_END (e->src);
  	      end = PREV_INSN (BB_HEAD (e->src));
  	      while (insn != end
! 		     && (!NONDEBUG_INSN_P (insn) || INSN_LOCATOR (insn) == 0))
  		insn = PREV_INSN (insn);
  	      if (insn != end
! 		  && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
  		continue;
  	      if (simplejump_p (BB_END (e->src))
! 		  && INSN_LOCATOR (BB_END (e->src)) == 0)
  		{
! 		  INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
  		  continue;
  		}
  	      dest = e->dest;
--- 3348,3362 ----
  	      insn = BB_END (e->src);
  	      end = PREV_INSN (BB_HEAD (e->src));
  	      while (insn != end
! 		     && (!NONDEBUG_INSN_P (insn) || !INSN_HAS_LOCATION (insn)))
  		insn = PREV_INSN (insn);
  	      if (insn != end
! 		  && INSN_LOCATION (insn) == e->goto_locus)
  		continue;
  	      if (simplejump_p (BB_END (e->src))
! 		  && !INSN_HAS_LOCATION (BB_END (e->src)))
  		{
! 		  INSN_LOCATION (BB_END (e->src)) = e->goto_locus;
  		  continue;
  		}
  	      dest = e->dest;
*************** fixup_reorder_chain (void)
*** 3371,3394 ****
  		  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))
  		    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;

  	      /* 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
  		    && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
! 		    && locator_eq (e->goto_locus, e2->goto_locus))
  		  redirect_edge_and_branch (e2, nb);
  		else
  		  ei_next (&ei2);
--- 3372,3395 ----
  		  end = NEXT_INSN (BB_END (dest));
  		  while (insn != end && !NONDEBUG_INSN_P (insn))
  		    insn = NEXT_INSN (insn);
! 		  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_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 (!IS_UNKNOWN_LOCATION (e2->goto_locus)
  		    && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
! 		    && e->goto_locus == e2->goto_locus)
  		  redirect_edge_and_branch (e2, nb);
  		else
  		  ei_next (&ei2);
*************** cfg_layout_merge_blocks (basic_block a,
*** 4088,4094 ****
      }

    /* If B was a forwarder block, propagate the locus on the edge.  */
!   if (forwarder_p && !EDGE_SUCC (b, 0)->goto_locus)
      EDGE_SUCC (b, 0)->goto_locus = EDGE_SUCC (a, 0)->goto_locus;

    if (dump_file)
--- 4089,4095 ----
      }

    /* If B was a forwarder block, propagate the locus on the edge.  */
!   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 189835)
--- gcc/stmt.c	(working copy)
*************** emit_case_nodes (rtx index, case_node_pt
*** 2397,2403 ****
  		 then emit the code for one side at a time.  */

  	      tree test_label
! 		= build_decl (CURR_INSN_LOCATION,
  			      LABEL_DECL, NULL_TREE, NULL_TREE);

  	      /* See if the value is on the right.  */
--- 2397,2403 ----
  		 then emit the code for one side at a time.  */

  	      tree test_label
! 		= build_decl (curr_insn_location (),
  			      LABEL_DECL, NULL_TREE, NULL_TREE);

  	      /* See if the value is on the right.  */
*************** emit_case_nodes (rtx index, case_node_pt
*** 2521,2527 ****
  	      /* Right hand node requires testing.
  		 Branch to a label where we will handle it later.  */

! 	      test_label = build_decl (CURR_INSN_LOCATION,
  				       LABEL_DECL, NULL_TREE, NULL_TREE);
  	      emit_cmp_and_jump_insns (index,
  				       convert_modes
--- 2521,2527 ----
  	      /* Right hand node requires testing.
  		 Branch to a label where we will handle it later.  */

! 	      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 189835)
--- libcpp/include/line-map.h	(working copy)
*************** struct GTY(()) line_map_ordinary {
*** 89,95 ****

  /* This is the highest possible source location encoded within an
     ordinary or macro map.  */
! #define MAX_SOURCE_LOCATION 0xFFFFFFFF

  struct cpp_hashnode;

--- 89,95 ----

  /* This is the highest possible source location encoded within an
     ordinary or macro map.  */
! #define MAX_SOURCE_LOCATION 0x7FFFFFFF

  struct cpp_hashnode;

*************** struct GTY(()) line_maps {
*** 408,413 ****
--- 408,423 ----
  #define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
    LINEMAPS_LAST_ALLOCATED_MAP (SET, true)

+ extern void location_block_init (void);
+ extern void location_block_fini (void);
+ extern source_location get_combine_location (source_location, void *);
+ extern void *get_block_from_location (source_location);
+ extern source_location get_locus_from_location (source_location);
+
+ #define COMBINE_LOCATION(LOC, BLOCK) \
+   ((BLOCK) ? get_combine_location ((LOC), (BLOCK)) : (LOC))
+ #define IS_COMBINED_LOCATION(LOC) (((LOC) & MAX_SOURCE_LOCATION) != (LOC))
+
  /* Initialize a line map set.  */
  extern void linemap_init (struct line_maps *);

*************** typedef struct
*** 594,599 ****
--- 604,611 ----

    int column;

+   void *block;
+
    /* In a system header?. */
    bool sysp;
  } expanded_location;
Index: libcpp/line-map.c
===================================================================
*** libcpp/line-map.c	(revision 189835)
--- libcpp/line-map.c	(working copy)
*************** along with this program; see the file CO
*** 25,30 ****
--- 25,31 ----
  #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 *,
*************** static source_location linemap_macro_loc
*** 50,55 ****
--- 51,171 ----
  extern unsigned num_expanded_macros_counter;
  extern unsigned num_macro_tokens_counter;

+ struct location_block {
+   source_location locus;
+   void *block;
+ };
+
+ static htab_t location_block_htab;
+ static source_location curr_combined_location;
+ static struct location_block *location_blocks;
+ static unsigned int allocated_location_blocks;
+
+ /* Hash function for location_block hashtable.  */
+
+ static hashval_t
+ location_block_hash (const void *l)
+ {
+   const struct location_block *lb = (const struct location_block *) l;
+   return (hashval_t) lb->locus + (size_t) &lb->block;
+ }
+
+ /* Compare function for location_block hashtable.  */
+
+ static int
+ location_block_eq (const void *l1, const void *l2)
+ {
+   const struct location_block *lb1 = (const struct location_block *) l1;
+   const struct location_block *lb2 = (const struct location_block *) l2;
+   return lb1->locus == lb2->locus && lb1->block == lb2->block;
+ }
+
+ /* Update the hashtable when location_blocks is reallocated.  */
+
+ static int
+ location_block_update (void **slot, void *data)
+ {
+   *((char **) slot) += ((char *) location_blocks - (char *) data);
+   return 1;
+ }
+
+ /* Combine LOCUS and BLOCK to a combined location.  */
+
+ source_location
+ get_combine_location (source_location locus, void *block)
+ {
+   struct location_block lb;
+   struct location_block **slot;
+
+   linemap_assert (block);
+
+   if (IS_COMBINED_LOCATION (locus))
+     locus = location_blocks[locus & MAX_SOURCE_LOCATION].locus;
+   if (locus == 0 && block == NULL)
+     return 0;
+   lb.locus = locus;
+   lb.block = block;
+   slot = (struct location_block **)
+       htab_find_slot (location_block_htab, &lb, INSERT);
+   if (*slot == NULL)
+     {
+       *slot = location_blocks + curr_combined_location;
+       location_blocks[curr_combined_location] = lb;
+       if (++curr_combined_location >= allocated_location_blocks)
+ 	{
+ 	  char *orig_location_blocks = (char *) location_blocks;
+ 	  allocated_location_blocks *= 2;
+ 	  location_blocks = XRESIZEVEC (struct location_block,
+ 				 	location_blocks,
+ 					allocated_location_blocks);
+ 	  htab_traverse (location_block_htab, location_block_update,
+ 			 orig_location_blocks);
+ 	}
+     }
+   return ((*slot) - location_blocks) | 0x80000000;
+ }
+
+ /* Return the block for LOCATION.  */
+
+ void *
+ get_block_from_location (source_location location)
+ {
+   linemap_assert (IS_COMBINED_LOCATION (location));
+   return location_blocks[location & MAX_SOURCE_LOCATION].block;
+ }
+
+ /* Return the locus for LOCATION.  */
+
+ source_location
+ get_locus_from_location (source_location location)
+ {
+   linemap_assert (IS_COMBINED_LOCATION (location));
+   return location_blocks[location & MAX_SOURCE_LOCATION].locus;
+ }
+
+ /* Initialize the location_block structure.  */
+
+ void
+ location_block_init (void)
+ {
+   location_block_htab = htab_create (100, location_block_hash,
+ 				     location_block_eq, NULL);
+   curr_combined_location = 0;
+   allocated_location_blocks = 100;
+   location_blocks = XNEWVEC (struct location_block,
+ 			     allocated_location_blocks);
+ }
+
+ /* Finalize the location_block structure.  */
+
+ void
+ location_block_fini (void)
+ {
+   allocated_location_blocks = 0;
+   XDELETEVEC (location_blocks);
+   htab_delete (location_block_htab);
+ }
+
  /* Initialize a line map set.  */

  void
*************** linemap_position_for_line_and_column (st
*** 509,514 ****
--- 625,632 ----
  const struct line_map*
  linemap_lookup (struct line_maps *set, source_location line)
  {
+   if (IS_COMBINED_LOCATION (line))
+     line = location_blocks[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);
*************** linemap_ordinary_map_lookup (struct line
*** 525,530 ****
--- 643,651 ----
    unsigned int md, mn, mx;
    const struct line_map *cached, *result;

+   if (IS_COMBINED_LOCATION (line))
+     line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
+
    if (set ==  NULL || line < RESERVED_LOCATION_COUNT)
      return NULL;

*************** linemap_macro_map_lookup (struct line_ma
*** 570,575 ****
--- 691,699 ----
    unsigned int md, mn, mx;
    const struct line_map *cached, *result;

+   if (IS_COMBINED_LOCATION (line))
+     line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));

    if (set ==  NULL)
*************** linemap_macro_map_loc_to_def_point (cons
*** 648,653 ****
--- 772,780 ----
  {
    unsigned token_no;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (linemap_macro_expansion_map_p (map)
  		  && location >= MAP_START_LOCATION (map));
    linemap_assert (location >= RESERVED_LOCATION_COUNT);
*************** linemap_macro_map_loc_unwind_toward_spel
*** 672,677 ****
--- 799,807 ----
  {
    unsigned token_no;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (linemap_macro_expansion_map_p (map)
  		  && location >= MAP_START_LOCATION (map));
    linemap_assert (location >= RESERVED_LOCATION_COUNT);
*************** linemap_get_expansion_line (struct line_
*** 696,701 ****
--- 826,834 ----
  {
    const struct line_map *map = NULL;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    if (location < RESERVED_LOCATION_COUNT)
      return 0;

*************** linemap_get_expansion_filename (struct l
*** 720,725 ****
--- 853,861 ----
  {
    const struct line_map *map = NULL;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    if (location < RESERVED_LOCATION_COUNT)
      return NULL;

*************** linemap_location_in_system_header_p (str
*** 754,759 ****
--- 890,898 ----
  {
    const struct line_map *map = NULL;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    if (location < RESERVED_LOCATION_COUNT)
      return false;

*************** bool
*** 793,798 ****
--- 932,940 ----
  linemap_location_from_macro_expansion_p (struct line_maps *set,
  					 source_location location)
  {
+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (location <= MAX_SOURCE_LOCATION
  		  && (set->highest_location
  		      < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
*************** linemap_macro_loc_to_spelling_point (str
*** 933,938 ****
--- 1075,1083 ----
  {
    struct line_map *map;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (set && location >= RESERVED_LOCATION_COUNT);

    while (true)
*************** linemap_macro_loc_to_def_point (struct l
*** 967,972 ****
--- 1112,1120 ----
  {
    struct line_map *map;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (set && location >= RESERVED_LOCATION_COUNT);

    while (true)
*************** linemap_macro_loc_to_exp_point (struct l
*** 1005,1010 ****
--- 1153,1161 ----
  {
    struct line_map *map;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (set && location >= RESERVED_LOCATION_COUNT);

    while (true)
*************** linemap_resolve_location (struct line_ma
*** 1074,1079 ****
--- 1225,1233 ----
  			  enum location_resolution_kind lrk,
  			  const struct line_map **map)
  {
+   if (IS_COMBINED_LOCATION (loc))
+     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+
    if (loc < RESERVED_LOCATION_COUNT)
      {
        /* A reserved location wasn't encoded in a map.  Let's return a
*************** linemap_unwind_toward_expansion (struct
*** 1121,1126 ****
--- 1275,1283 ----
    source_location resolved_location;
    const struct line_map *resolved_map;

+   if (IS_COMBINED_LOCATION (loc))
+     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+
    resolved_location =
      linemap_macro_map_loc_unwind_toward_spelling (*map, loc);
    resolved_map = linemap_lookup (set, resolved_location);
*************** linemap_unwind_to_first_non_reserved_loc
*** 1157,1162 ****
--- 1314,1322 ----
    source_location resolved_loc;
    const struct line_map *map0 = NULL, *map1 = NULL;

+   if (IS_COMBINED_LOCATION (loc))
+     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+
    map0 = linemap_lookup (set, loc);
    if (!linemap_macro_expansion_map_p (map0))
      return loc;
*************** linemap_expand_location (struct line_map
*** 1198,1203 ****
--- 1358,1368 ----
    expanded_location xloc;

    memset (&xloc, 0, sizeof (xloc));
+   if (IS_COMBINED_LOCATION (loc))
+     {
+       loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+       xloc.block = location_blocks[loc & MAX_SOURCE_LOCATION].block;
+     }

    if (loc < RESERVED_LOCATION_COUNT)
      /* The location for this token wasn't generated from a line map.
*************** linemap_dump_location (struct line_maps
*** 1290,1295 ****
--- 1455,1463 ----
    const char *path = "", *from = "";
    int l = -1, c = -1, s = -1, e = -1;

+   if (IS_COMBINED_LOCATION (loc))
+     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+
    if (loc == 0)
      return;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-06 18:36       ` Dehao Chen
@ 2012-08-07 15:16         ` Richard Guenther
  2012-08-07 15:52           ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-08-07 15:16 UTC (permalink / raw)
  To: Dehao Chen
  Cc: gcc-patches, Dodji Seketeli, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey

On Mon, Aug 6, 2012 at 8:35 PM, Dehao Chen <dehao@google.com> wrote:
> On Thu, Aug 2, 2012 at 6:05 PM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Thu, Aug 2, 2012 at 5:23 AM, Dehao Chen <dehao@google.com> wrote:
>>> On Thu, Aug 2, 2012 at 2:07 AM, Richard Guenther
>>> <richard.guenther@gmail.com> wrote:
>>>> On Wed, Aug 1, 2012 at 7:35 AM, Dehao Chen <dehao@google.com> wrote:
>>>>> Hi,
>>>>>
>>>>> This patch:
>>>>>
>>>>> * Integrates location with block into an integrated index.
>>>>> * Removes gimple->gsbase.block and tree->exp.block fields.
>>>>> * Updates inline/clone as well as tree liveness analysis to ensure the
>>>>> associated blocks are updated correctly.
>>>>>
>>>>> With this patch, the association between source location and its block
>>>>> are greatly enhanced, which produces much better inline stack in the
>>>>> debug info.
>>>>>
>>>>> Bootstrapped and regression tested on x86.
>>>>>
>>>>> OK for trunk?
>>>>
>>>> Nice.  But the LTO changes mean that you simply drop all BLOCK
>>>> associations on the floor ...
>>>
>>> Why? I've invoked TREE_SET_BLOCK in tree-streamer-in.c to read in the
>>> block info. So it should at least provide the same info as the
>>> original impl.
>>>
>>>> they at least look very incomplete.  Did you actually run LTO tests?
>>>
>>> Thanks for the reminder, I've added the following change to this patch:
>>>
>>> Index: gcc/tree-streamer-out.c
>>> ===================================================================
>>> --- gcc/tree-streamer-out.c     (revision 189835)
>>> +++ gcc/tree-streamer-out.c     (working copy)
>>> @@ -471,7 +471,7 @@
>>>  {
>>>    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 @@
>>>    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);
>>>  }
>>
>> That doesn't match up with the change
>>
>> Index: gcc/lto-streamer-out.c
>> ===================================================================
>> --- gcc/lto-streamer-out.c      (revision 189835)
>> +++ gcc/lto-streamer-out.c      (working copy)
>> @@ -155,6 +155,7 @@
>>  {
>>    expanded_location xloc;
>>
>> +  loc = LOCATION_LOCUS (loc);
>>    bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
>>    if (loc == UNKNOWN_LOCATION)
>>      return;
>>
>> (please remember to generate diffs with -p, so the function name is shown
>> in the diff hunk header)
>
> I've attached the new patch with -p output in this mail. Also added
> the change in gimple-stream-out.c
>
>>
>>> I think BLOCK associations works fine for LTO. I've run check-gcc, and
>>> there's no regression on LTO tests. I also manually write some tests,
>>> and the generated final assembly has block info as expected.
>>
>> What about the lto_output_location calls in gimple-streamer-out.c?  As far as I
>> can see they will end up dropping the associated BLOCK on the floor (I cannot
>> see any change on the -input side).
>
> The beauty of this patch is that it does not need to change the input
> side (except that we added tree_set_block instead of using
> "tree_block(t)" as lvalue, more detail in the following illustration.
>
>>
>>>>
>>>> lto/ has its own ChangeLog
>>>
>>> Thanks, I'll update the ChangeLog accordingly.
>>>
>>>> and I wonder why no frontends are affected
>>>> by this patch?
>>>
>>> Which files are you referring to?
>>
>> I was refering to the issue you brought up earlier - all the fold
>> routines losing
>> block associations.  Maybe you can elaborate some more how locator
>> is different from location, thus how you set up the machinery.
>
> This patch defines the following terminology:
> - locus: the original location_t in structures such as
> gimple_location, EXPR_LOCATION, etc.
> - locator: an index to the location_block array, as used in RTL in the
> original implementation.
> - location: an uint32 that represent the new location: if the highest
> bit is 0, it serves as the locus, if the highest bit is 1, the lower
> 31 bits serves as the locator.
>
> The macro LOCATION_LOCUS derives the locus from location.
> The macro LOCATION_BLOCK derives the block from location.
> And the gimple_set_block and tree_set_block are modified to set the
> updated location for gimple/tree.
>
> Because the interface of gimple_set_block/gimple_block does not
> change, we kept frontend change minimal. Also, as we encode the block
> into location, the block info can be passed without need to change the
> fold_.* interface.
>
> The downside of this approach is that we need to explicitly use
> LOCATION_LOCUS when we mean to use the original locus. E.g. when LTO
> streams out location, it actually streams out locus. Fortunately, only
> a small portion of code need to use the locus. Most code just copy the
> location from one place to one another.

Ok, that makes sense.  Would a libccp maintainer please review the libcpp
bits (or say that they should be elsewhere)?

> Thanks,
> Dehao
>
> Updated patch:

Please always post a CHangeLog as well.

Thanks,
Richard.


>
> Index: gcc/gimple-streamer-out.c
> ===================================================================
> *** gcc/gimple-streamer-out.c   (revision 189835)
> --- gcc/gimple-streamer-out.c   (working copy)
> *************** output_gimple_stmt (struct output_block
> *** 74,80 ****
>     streamer_write_bitpack (&bp);
>
>     /* Emit location information for the statement.  */
> !   lto_output_location (ob, gimple_location (stmt));
>
>     /* Emit the lexical block holding STMT.  */
>     stream_write_tree (ob, gimple_block (stmt), true);
> --- 74,80 ----
>     streamer_write_bitpack (&bp);
>
>     /* Emit location information for the statement.  */
> !   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 189835)
> --- gcc/tree.c  (working copy)
> *************** build1_stat (enum tree_code code, tree t
> *** 3765,3771 ****
>     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);
> --- 3765,3770 ----
> *************** walk_tree_without_duplicates_1 (tree *tp
> *** 10867,10883 ****
>   }
>
>
> ! tree *
>   tree_block (tree t)
>   {
>     char const c = TREE_CODE_CLASS (TREE_CODE (t));
>
>     if (IS_EXPR_CODE_CLASS (c))
> !     return &t->exp.block;
>     gcc_unreachable ();
>     return NULL;
>   }
>
>   /* 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.  */
> --- 10866,10893 ----
>   }
>
>
> ! tree
>   tree_block (tree t)
>   {
>     char const c = TREE_CODE_CLASS (TREE_CODE (t));
>
>     if (IS_EXPR_CODE_CLASS (c))
> !     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 (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 189835)
> --- gcc/tree.h  (working copy)
> *************** extern void omp_clause_range_check_faile
> *** 999,1005 ****
>
>   #endif
>
> ! #define TREE_BLOCK(NODE)              *(tree_block (NODE))
>
>   #include "tree-check.h"
>
> --- 999,1006 ----
>
>   #endif
>
> ! #define TREE_BLOCK(NODE)              (tree_block (NODE))
> ! #define TREE_SET_BLOCK(T, B)          (tree_set_block ((T), (B)))
>
>   #include "tree-check.h"
>
> *************** struct GTY(()) tree_constructor {
> *** 1702,1708 ****
>   #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)
>   /* 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)
> --- 1703,1709 ----
>   #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) (!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)
> *************** extern void protected_set_expr_location
> *** 1881,1887 ****
>                                               OMP_CLAUSE_PRIVATE,       \
>                                               OMP_CLAUSE_COPYPRIVATE), 0)
>   #define OMP_CLAUSE_HAS_LOCATION(NODE) \
> !   ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus != UNKNOWN_LOCATION)
>   #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,1888 ----
>                                               OMP_CLAUSE_PRIVATE,       \
>                                               OMP_CLAUSE_COPYPRIVATE), 0)
>   #define OMP_CLAUSE_HAS_LOCATION(NODE) \
> !   (!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.
> *************** enum omp_clause_default_kind
> *** 1972,1978 ****
>   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];
> --- 1973,1978 ----
> *************** function_args_iter_next (function_args_i
> *** 5164,5170 ****
>   static inline bool
>   inlined_function_outer_scope_p (const_tree block)
>   {
> !  return BLOCK_SOURCE_LOCATION (block) != UNKNOWN_LOCATION;
>   }
>
>   /* Loop over all function arguments of FNTYPE.  In each iteration, PTR is set
> --- 5164,5170 ----
>   static inline bool
>   inlined_function_outer_scope_p (const_tree block)
>   {
> !  return !IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (block));
>   }
>
>   /* Loop over all function arguments of FNTYPE.  In each iteration, PTR is set
> *************** extern bool subrange_type_for_debug_p (c
> *** 5539,5545 ****
>   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 location_t *block_nonartificial_location (tree);
>   extern location_t tree_nonartificial_location (tree);
>
> --- 5539,5546 ----
>   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 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 189835)
> --- gcc/final.c (working copy)
> *************** reemit_insn_block_notes (void)
> *** 1605,1611 ****
>                                              insn_scope (XVECEXP (body, 0, i)));
>         }
>         if (! this_block)
> !       continue;
>
>         if (this_block != cur_block)
>         {
> --- 1605,1611 ----
>                                              insn_scope (XVECEXP (body, 0, i)));
>         }
>         if (! this_block)
> !       this_block = DECL_INITIAL (cfun->decl);
>
>         if (this_block != cur_block)
>         {
> *************** final_start_function (rtx first ATTRIBUT
> *** 1640,1647 ****
>
>     this_is_asm_operands = 0;
>
> !   last_filename = locator_file (prologue_locator);
> !   last_linenum = locator_line (prologue_locator);
>     last_discriminator = discriminator = 0;
>
>     high_block_linenum = high_function_linenum = last_linenum;
> --- 1640,1647 ----
>
>     this_is_asm_operands = 0;
>
> !   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 189835)
> --- gcc/input.c (working copy)
> *************** expand_location_1 (source_location loc,
> *** 51,56 ****
> --- 51,63 ----
>     expanded_location xloc;
>     const struct line_map *map;
>     enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
> +   tree block = NULL;
> +
> +   if (IS_COMBINED_LOCATION (loc))
> +     {
> +       block = LOCATION_BLOCK (loc);
> +       loc = LOCATION_LOCUS (loc);
> +     }
>
>     memset (&xloc, 0, sizeof (xloc));
>
> *************** expand_location_1 (source_location loc,
> *** 74,79 ****
> --- 81,87 ----
>         xloc = linemap_expand_location (line_table, map, loc);
>       }
>
> +   xloc.block = block;
>     if (loc <= BUILTINS_LOCATION)
>       xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
>
> Index: gcc/input.h
> ===================================================================
> *** gcc/input.h (revision 189835)
> --- gcc/input.h (working copy)
> *************** extern location_t input_location;
> *** 51,56 ****
> --- 51,64 ----
>   #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_COMBINED_LOCATION(LOC)) ? get_locus_from_location (LOC) : (LOC))
> + #define LOCATION_BLOCK(LOC) \
> +   ((tree) ((IS_COMBINED_LOCATION (LOC)) ? get_block_from_location (LOC) \
> +   : NULL))
> + #define IS_UNKNOWN_LOCATION(LOC) \
> +   ((IS_COMBINED_LOCATION (LOC)) ? get_locus_from_location (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 189835)
> --- gcc/fold-const.c    (working copy)
> *************** static location_t
> *** 145,151 ****
>   expr_location_or (tree t, location_t loc)
>   {
>     location_t tloc = EXPR_LOCATION (t);
> !   return tloc != UNKNOWN_LOCATION ? tloc : loc;
>   }
>
>   /* Similar to protected_set_expr_location, but never modify x in place,
> --- 145,151 ----
>   expr_location_or (tree t, location_t loc)
>   {
>     location_t tloc = EXPR_LOCATION (t);
> !   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 189835)
> --- gcc/toplev.c        (working copy)
> *************** general_init (const char *argv0)
> *** 1140,1145 ****
> --- 1140,1146 ----
>     linemap_init (line_table);
>     line_table->reallocator = realloc_for_line_map;
>     line_table->round_alloc_size = ggc_round_alloc_size;
> +   location_block_init ();
>     init_ttree ();
>
>     /* Initialize register usage now so switches may override.  */
> *************** toplev_main (int argc, char **argv)
> *** 1946,1951 ****
> --- 1947,1953 ----
>     invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
>
>     finalize_plugins ();
> +   location_block_fini ();
>     if (seen_error ())
>       return (FATAL_EXIT_CODE);
>
> Index: gcc/reorg.c
> ===================================================================
> *** gcc/reorg.c (revision 189835)
> --- gcc/reorg.c (working copy)
> *************** emit_delay_sequence (rtx insn, rtx list,
> *** 545,551 ****
>     INSN_DELETED_P (delay_insn) = 0;
>     PREV_INSN (delay_insn) = PREV_INSN (seq_insn);
>
> !   INSN_LOCATOR (seq_insn) = INSN_LOCATOR (delay_insn);
>
>     for (li = list; li; li = XEXP (li, 1), i++)
>       {
> --- 545,551 ----
>     INSN_DELETED_P (delay_insn) = 0;
>     PREV_INSN (delay_insn) = PREV_INSN (seq_insn);
>
> !   INSN_LOCATION (seq_insn) = INSN_LOCATION (delay_insn);
>
>     for (li = list; li; li = XEXP (li, 1), i++)
>       {
> *************** emit_delay_sequence (rtx insn, rtx list,
> *** 561,569 ****
>
>         /* 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;
>
>         for (note = REG_NOTES (tem); note; note = next)
>         {
> --- 561,569 ----
>
>         /* SPARC assembler, for instance, emit warning when debug info is output
>            into the delay slot.  */
> !       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)
>         {
> *************** dbr_schedule (rtx first)
> *** 4087,4093 ****
>       for (link = crtl->epilogue_delay_list;
>            link;
>            link = XEXP (link, 1))
> !       INSN_LOCATOR (XEXP (link, 0)) = 0;
>     }
>
>   #endif
> --- 4087,4093 ----
>       for (link = crtl->epilogue_delay_list;
>            link;
>            link = XEXP (link, 1))
> !       INSN_LOCATION (XEXP (link, 0)) = 0;
>     }
>
>   #endif
> Index: gcc/modulo-sched.c
> ===================================================================
> *** gcc/modulo-sched.c  (revision 189835)
> --- gcc/modulo-sched.c  (working copy)
> *************** loop_single_full_bb_p (struct loop *loop
> *** 1246,1254 ****
>   /* Dump file:line from INSN's location info to dump_file.  */
>
>   static void
> ! dump_insn_locator (rtx insn)
>   {
> !   if (dump_file && INSN_LOCATOR (insn))
>       {
>         const char *file = insn_file (insn);
>         if (file)
> --- 1246,1254 ----
>   /* Dump file:line from INSN's location info to dump_file.  */
>
>   static void
> ! dump_insn_location (rtx insn)
>   {
> !   if (dump_file && INSN_LOCATION (insn))
>       {
>         const char *file = insn_file (insn);
>         if (file)
> *************** loop_canon_p (struct loop *loop)
> *** 1282,1288 ****
>           rtx insn = BB_END (loop->header);
>
>           fprintf (dump_file, "SMS loop many exits");
> !         dump_insn_locator (insn);
>           fprintf (dump_file, "\n");
>         }
>         return false;
> --- 1282,1288 ----
>           rtx insn = BB_END (loop->header);
>
>           fprintf (dump_file, "SMS loop many exits");
> !         dump_insn_location (insn);
>           fprintf (dump_file, "\n");
>         }
>         return false;
> *************** loop_canon_p (struct loop *loop)
> *** 1295,1301 ****
>           rtx insn = BB_END (loop->header);
>
>           fprintf (dump_file, "SMS loop many BBs.");
> !         dump_insn_locator (insn);
>           fprintf (dump_file, "\n");
>         }
>         return false;
> --- 1295,1301 ----
>           rtx insn = BB_END (loop->header);
>
>           fprintf (dump_file, "SMS loop many BBs.");
> !         dump_insn_location (insn);
>           fprintf (dump_file, "\n");
>         }
>         return false;
> *************** sms_schedule (void)
> *** 1421,1427 ****
>           rtx insn = BB_END (loop->header);
>
>           fprintf (dump_file, "SMS loop num: %d", loop->num);
> !         dump_insn_locator (insn);
>           fprintf (dump_file, "\n");
>         }
>
> --- 1421,1427 ----
>           rtx insn = BB_END (loop->header);
>
>           fprintf (dump_file, "SMS loop num: %d", loop->num);
> !         dump_insn_location (insn);
>           fprintf (dump_file, "\n");
>         }
>
> *************** sms_schedule (void)
> *** 1450,1456 ****
>         {
>           if (dump_file)
>             {
> !             dump_insn_locator (tail);
>               fprintf (dump_file, "\nSMS single-bb-loop\n");
>               if (profile_info && flag_branch_probabilities)
>                 {
> --- 1450,1456 ----
>         {
>           if (dump_file)
>             {
> !             dump_insn_location (tail);
>               fprintf (dump_file, "\nSMS single-bb-loop\n");
>               if (profile_info && flag_branch_probabilities)
>                 {
> *************** sms_schedule (void)
> *** 1556,1562 ****
>           rtx insn = BB_END (loop->header);
>
>           fprintf (dump_file, "SMS loop num: %d", loop->num);
> !         dump_insn_locator (insn);
>           fprintf (dump_file, "\n");
>
>           print_ddg (dump_file, g);
> --- 1556,1562 ----
>           rtx insn = BB_END (loop->header);
>
>           fprintf (dump_file, "SMS loop num: %d", loop->num);
> !         dump_insn_location (insn);
>           fprintf (dump_file, "\n");
>
>           print_ddg (dump_file, g);
> *************** sms_schedule (void)
> *** 1571,1577 ****
>
>         if (dump_file)
>         {
> !         dump_insn_locator (tail);
>           fprintf (dump_file, "\nSMS single-bb-loop\n");
>           if (profile_info && flag_branch_probabilities)
>             {
> --- 1571,1577 ----
>
>         if (dump_file)
>         {
> !         dump_insn_location (tail);
>           fprintf (dump_file, "\nSMS single-bb-loop\n");
>           if (profile_info && flag_branch_probabilities)
>             {
> *************** sms_schedule (void)
> *** 1714,1720 ****
>
>             if (dump_file)
>               {
> !             dump_insn_locator (tail);
>               fprintf (dump_file, " SMS succeeded %d %d (with ii, sc)\n",
>                        ps->ii, stage_count);
>               print_partial_schedule (ps, dump_file);
> --- 1714,1720 ----
>
>             if (dump_file)
>               {
> !             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 189835)
> --- gcc/lto-streamer-out.c      (working copy)
> *************** lto_output_location_bitpack (struct bitp
> *** 155,160 ****
> --- 155,161 ----
>   {
>     expanded_location xloc;
>
> +   loc = LOCATION_LOCUS (loc);
>     bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
>     if (loc == UNKNOWN_LOCATION)
>       return;
> Index: gcc/jump.c
> ===================================================================
> *** gcc/jump.c  (revision 189835)
> --- gcc/jump.c  (working copy)
> *************** rtx_renumbered_equal_p (const_rtx x, con
> *** 1818,1825 ****
>           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)))
>                 break;
>               return 0;
>             }
> --- 1818,1824 ----
>           if (XINT (x, i) != XINT (y, i))
>             {
>               if (((code == ASM_OPERANDS && i == 6)
> !                  || (code == ASM_INPUT && i == 1)))
>                 break;
>               return 0;
>             }
> Index: gcc/ifcvt.c
> ===================================================================
> *** gcc/ifcvt.c (revision 189835)
> --- gcc/ifcvt.c (working copy)
> *************** noce_try_move (struct noce_if_info *if_i
> *** 1019,1025 ****
>             return FALSE;
>
>           emit_insn_before_setloc (seq, if_info->jump,
> !                                  INSN_LOCATOR (if_info->insn_a));
>         }
>         return TRUE;
>       }
> --- 1019,1025 ----
>             return FALSE;
>
>           emit_insn_before_setloc (seq, if_info->jump,
> !                                  INSN_LOCATION (if_info->insn_a));
>         }
>         return TRUE;
>       }
> *************** noce_try_store_flag (struct noce_if_info
> *** 1064,1070 ****
>         return FALSE;
>
>         emit_insn_before_setloc (seq, if_info->jump,
> !                              INSN_LOCATOR (if_info->insn_a));
>         return TRUE;
>       }
>     else
> --- 1064,1070 ----
>         return FALSE;
>
>         emit_insn_before_setloc (seq, if_info->jump,
> !                              INSN_LOCATION (if_info->insn_a));
>         return TRUE;
>       }
>     else
> *************** noce_try_store_flag_constants (struct no
> *** 1195,1201 ****
>         return FALSE;
>
>         emit_insn_before_setloc (seq, if_info->jump,
> !                              INSN_LOCATOR (if_info->insn_a));
>         return TRUE;
>       }
>
> --- 1195,1201 ----
>         return FALSE;
>
>         emit_insn_before_setloc (seq, if_info->jump,
> !                              INSN_LOCATION (if_info->insn_a));
>         return TRUE;
>       }
>
> *************** noce_try_addcc (struct noce_if_info *if_
> *** 1243,1249 ****
>                 return FALSE;
>
>               emit_insn_before_setloc (seq, if_info->jump,
> !                                      INSN_LOCATOR (if_info->insn_a));
>               return TRUE;
>             }
>           end_sequence ();
> --- 1243,1249 ----
>                 return FALSE;
>
>               emit_insn_before_setloc (seq, if_info->jump,
> !                                      INSN_LOCATION (if_info->insn_a));
>               return TRUE;
>             }
>           end_sequence ();
> *************** noce_try_addcc (struct noce_if_info *if_
> *** 1283,1289 ****
>                 return FALSE;
>
>               emit_insn_before_setloc (seq, if_info->jump,
> !                                      INSN_LOCATOR (if_info->insn_a));
>               return TRUE;
>             }
>           end_sequence ();
> --- 1283,1289 ----
>                 return FALSE;
>
>               emit_insn_before_setloc (seq, if_info->jump,
> !                                      INSN_LOCATION (if_info->insn_a));
>               return TRUE;
>             }
>           end_sequence ();
> *************** noce_try_store_flag_mask (struct noce_if
> *** 1332,1338 ****
>             return FALSE;
>
>           emit_insn_before_setloc (seq, if_info->jump,
> !                                  INSN_LOCATOR (if_info->insn_a));
>           return TRUE;
>         }
>
> --- 1332,1338 ----
>             return FALSE;
>
>           emit_insn_before_setloc (seq, if_info->jump,
> !                                  INSN_LOCATION (if_info->insn_a));
>           return TRUE;
>         }
>
> *************** noce_try_cmove (struct noce_if_info *if_
> *** 1481,1487 ****
>             return FALSE;
>
>           emit_insn_before_setloc (seq, if_info->jump,
> !                                  INSN_LOCATOR (if_info->insn_a));
>           return TRUE;
>         }
>         else
> --- 1481,1487 ----
>             return FALSE;
>
>           emit_insn_before_setloc (seq, if_info->jump,
> !                                  INSN_LOCATION (if_info->insn_a));
>           return TRUE;
>         }
>         else
> *************** noce_try_cmove_arith (struct noce_if_inf
> *** 1682,1688 ****
>     if (!tmp)
>       return FALSE;
>
> !   emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR
> (if_info->insn_a));
>     return TRUE;
>
>    end_seq_and_fail:
> --- 1682,1688 ----
>     if (!tmp)
>       return FALSE;
>
> !   emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATION
> (if_info->insn_a));
>     return TRUE;
>
>    end_seq_and_fail:
> *************** noce_try_minmax (struct noce_if_info *if
> *** 1929,1935 ****
>     if (!seq)
>       return FALSE;
>
> !   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
> (if_info->insn_a));
>     if_info->cond = cond;
>     if_info->cond_earliest = earliest;
>
> --- 1929,1935 ----
>     if (!seq)
>       return FALSE;
>
> !   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
> (if_info->insn_a));
>     if_info->cond = cond;
>     if_info->cond_earliest = earliest;
>
> *************** noce_try_abs (struct noce_if_info *if_in
> *** 2076,2082 ****
>     if (!seq)
>       return FALSE;
>
> !   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
> (if_info->insn_a));
>     if_info->cond = cond;
>     if_info->cond_earliest = earliest;
>
> --- 2076,2082 ----
>     if (!seq)
>       return FALSE;
>
> !   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
> (if_info->insn_a));
>     if_info->cond = cond;
>     if_info->cond_earliest = earliest;
>
> *************** noce_try_sign_mask (struct noce_if_info
> *** 2155,2161 ****
>     if (!seq)
>       return FALSE;
>
> !   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
> (if_info->insn_a));
>     return TRUE;
>   }
>
> --- 2155,2161 ----
>     if (!seq)
>       return FALSE;
>
> !   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
> (if_info->insn_a));
>     return TRUE;
>   }
>
> *************** noce_try_bitop (struct noce_if_info *if_
> *** 2255,2261 ****
>         return FALSE;
>
>         emit_insn_before_setloc (seq, if_info->jump,
> !                              INSN_LOCATOR (if_info->insn_a));
>       }
>     return TRUE;
>   }
> --- 2255,2261 ----
>         return FALSE;
>
>         emit_insn_before_setloc (seq, if_info->jump,
> !                              INSN_LOCATION (if_info->insn_a));
>       }
>     return TRUE;
>   }
> *************** noce_process_if_block (struct noce_if_in
> *** 2656,2662 ****
>         unshare_all_rtl_in_chain (seq);
>         end_sequence ();
>
> !       emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATOR (insn_a));
>       }
>
>     /* The original THEN and ELSE blocks may now be removed.  The test block
> --- 2656,2662 ----
>         unshare_all_rtl_in_chain (seq);
>         end_sequence ();
>
> !       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
> *************** cond_move_process_if_block (struct noce_
> *** 2937,2943 ****
>         loc_insn = first_active_insn (else_bb);
>         gcc_assert (loc_insn);
>       }
> !   emit_insn_before_setloc (seq, jump, INSN_LOCATOR (loc_insn));
>
>     if (else_bb)
>       {
> --- 2937,2943 ----
>         loc_insn = first_active_insn (else_bb);
>         gcc_assert (loc_insn);
>       }
> !   emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));
>
>     if (else_bb)
>       {
> *************** find_cond_trap (basic_block test_bb, edg
> *** 3655,3661 ****
>       return FALSE;
>
>     /* Emit the new insns before cond_earliest.  */
> !   emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATOR (trap));
>
>     /* Delete the trap block if possible.  */
>     remove_edge (trap_bb == then_bb ? then_edge : else_edge);
> --- 3655,3661 ----
>       return FALSE;
>
>     /* Emit the new insns before cond_earliest.  */
> !   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/dwarf2out.c
> ===================================================================
> *** gcc/dwarf2out.c     (revision 189835)
> --- gcc/dwarf2out.c     (working copy)
> *************** add_src_coords_attributes (dw_die_ref di
> *** 15506,15512 ****
>   {
>     expanded_location s;
>
> !   if (DECL_SOURCE_LOCATION (decl) == UNKNOWN_LOCATION)
>       return;
>     s = expand_location (DECL_SOURCE_LOCATION (decl));
>     add_AT_file (die, DW_AT_decl_file, lookup_filename (s.file));
> --- 15506,15512 ----
>   {
>     expanded_location s;
>
> !   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 189835)
> --- gcc/expr.c  (working copy)
> *************** expand_expr_real (tree exp, rtx target,
> *** 7802,7820 ****
>     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 ();
>         input_location = EXPR_LOCATION (exp);
> !       set_curr_insn_source_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);
>       }
>     else
>       {
> --- 7802,7815 ----
>     if (cfun && EXPR_HAS_LOCATION (exp))
>       {
>         location_t saved_location = input_location;
> !       location_t saved_curr_loc = curr_insn_location ();
>         input_location = EXPR_LOCATION (exp);
> !       set_curr_insn_location (input_location);
>
>         ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
>
>         input_location = saved_location;
> !       set_curr_insn_location (saved_curr_loc);
>       }
>     else
>       {
> Index: gcc/predict.c
> ===================================================================
> *** gcc/predict.c       (revision 189835)
> --- gcc/predict.c       (working copy)
> *************** tree_estimate_probability_driver (void)
> *** 2177,2183 ****
>   {
>     unsigned nb_loops;
>
> !   loop_optimizer_init (0);
>     if (dump_file && (dump_flags & TDF_DETAILS))
>       flow_loops_dump (dump_file, NULL, 0);
>
> --- 2177,2183 ----
>   {
>     unsigned nb_loops;
>
> !   loop_optimizer_init (LOOPS_NORMAL);
>     if (dump_file && (dump_flags & TDF_DETAILS))
>       flow_loops_dump (dump_file, NULL, 0);
>
> Index: gcc/tree-parloops.c
> ===================================================================
> *** gcc/tree-parloops.c (revision 189835)
> --- gcc/tree-parloops.c (working copy)
> *************** create_loop_fn (location_t loc)
> *** 1415,1420 ****
> --- 1415,1421 ----
>     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 189835)
> --- gcc/recog.c (working copy)
> *************** peep2_attempt (basic_block bb, rtx insn,
> *** 3333,3339 ****
>     /* 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));
>     before_try = PREV_INSN (insn);
>     delete_insn_chain (insn, peep2_insn_data[i].insn, false);
>
> --- 3333,3339 ----
>     /* Replace the old sequence with the new.  */
>     last = emit_insn_after_setloc (attempt,
>                                  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 189835)
> --- gcc/function.c      (working copy)
> *************** static bool contains (const_rtx, htab_t)
> *** 133,139 ****
>   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;
>
>   /* Stack of nested functions.  */
>   /* Keep track of the cfun stack.  */
> --- 133,139 ----
>   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_locations (rtx, int) ATTRIBUTE_UNUSED;
>
>   /* Stack of nested functions.  */
>   /* Keep track of the cfun stack.  */
> *************** free_after_compilation (struct function
> *** 200,206 ****
>     f->cfg = NULL;
>
>     regno_reg_rtx = NULL;
> -   insn_locators_free ();
>   }
>
>   /* Return size needed for stack frame based on slots so far allocated.
> --- 200,205 ----
> *************** expand_function_end (void)
> *** 4979,4985 ****
>               probe_stack_range (STACK_OLD_CHECK_PROTECT, max_frame_size);
>             seq = get_insns ();
>             end_sequence ();
> !           set_insn_locators (seq, prologue_locator);
>             emit_insn_before (seq, stack_check_probe_note);
>             break;
>           }
> --- 4978,4984 ----
>               probe_stack_range (STACK_OLD_CHECK_PROTECT, max_frame_size);
>             seq = get_insns ();
>             end_sequence ();
> !           set_insn_locations (seq, prologue_location);
>             emit_insn_before (seq, stack_check_probe_note);
>             break;
>           }
> *************** expand_function_end (void)
> *** 4994,5000 ****
>
>     /* Output a linenumber for the end of the function.
>        SDB depends on this.  */
> !   set_curr_insn_source_location (input_location);
>
>     /* Before the return label (if any), clobber the return
>        registers so that they are not propagated live to the rest of
> --- 4993,4999 ----
>
>     /* Output a linenumber for the end of the function.
>        SDB depends on this.  */
> !   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
> *************** maybe_copy_prologue_epilogue_insn (rtx i
> *** 5277,5290 ****
>     *slot = copy;
>   }
>
> ! /* Set the locator of the insn chain starting at INSN to LOC.  */
>   static void
> ! set_insn_locators (rtx insn, int loc)
>   {
>     while (insn != NULL_RTX)
>       {
>         if (INSN_P (insn))
> !       INSN_LOCATOR (insn) = loc;
>         insn = NEXT_INSN (insn);
>       }
>   }
> --- 5276,5289 ----
>     *slot = copy;
>   }
>
> ! /* Set the location of the insn chain starting at INSN to LOC.  */
>   static void
> ! set_insn_locations (rtx insn, int loc)
>   {
>     while (insn != NULL_RTX)
>       {
>         if (INSN_P (insn))
> !       INSN_LOCATION (insn) = loc;
>         insn = NEXT_INSN (insn);
>       }
>   }
> *************** thread_prologue_and_epilogue_insns (void
> *** 5893,5899 ****
>         end_sequence ();
>
>         record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
> !       set_insn_locators (split_prologue_seq, prologue_locator);
>   #endif
>       }
>
> --- 5892,5898 ----
>         end_sequence ();
>
>         record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
> !       set_insn_locations (split_prologue_seq, prologue_location);
>   #endif
>       }
>
> *************** thread_prologue_and_epilogue_insns (void
> *** 5922,5928 ****
>
>         prologue_seq = get_insns ();
>         end_sequence ();
> !       set_insn_locators (prologue_seq, prologue_locator);
>       }
>   #endif
>
> --- 5921,5927 ----
>
>         prologue_seq = get_insns ();
>         end_sequence ();
> !       set_insn_locations (prologue_seq, prologue_location);
>       }
>   #endif
>
> *************** thread_prologue_and_epilogue_insns (void
> *** 6418,6424 ****
>
>         /* Retain a map of the epilogue insns.  */
>         record_insns (seq, NULL, &epilogue_insn_hash);
> !       set_insn_locators (seq, epilogue_locator);
>
>         seq = get_insns ();
>         returnjump = get_last_insn ();
> --- 6417,6423 ----
>
>         /* Retain a map of the epilogue insns.  */
>         record_insns (seq, NULL, &epilogue_insn_hash);
> !       set_insn_locations (seq, epilogue_location);
>
>         seq = get_insns ();
>         returnjump = get_last_insn ();
> *************** epilogue_done:
> *** 6608,6614 ****
>              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);
>
>           emit_insn_before (seq, insn);
>         }
> --- 6607,6613 ----
>              avoid getting rid of sibcall epilogue insns.  Do this before we
>              actually emit the sequence.  */
>           record_insns (seq, NULL, &epilogue_insn_hash);
> !         set_insn_locations (seq, epilogue_location);
>
>           emit_insn_before (seq, insn);
>         }
> Index: gcc/print-rtl.c
> ===================================================================
> *** gcc/print-rtl.c     (revision 189835)
> --- gcc/print-rtl.c     (working copy)
> *************** print_rtx (const_rtx in_rtx)
> *** 416,425 ****
>         if (i == 5 && INSN_P (in_rtx))
>           {
>   #ifndef GENERATOR_FILE
> !           /*  Pretty-print insn locators.  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))
>               fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
>   #endif
>           }
> --- 416,425 ----
>         if (i == 5 && INSN_P (in_rtx))
>           {
>   #ifndef GENERATOR_FILE
> !           /*  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_LOCATION (in_rtx) && insn_file (in_rtx))
>               fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
>   #endif
>           }
> *************** print_rtx (const_rtx in_rtx)
> *** 427,442 ****
>           {
>   #ifndef GENERATOR_FILE
>             fprintf (outfile, " %s:%i",
> !                    locator_file (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)),
> !                    locator_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)));
>   #endif
>           }
>         else if (i == 6 && NOTE_P (in_rtx))
> --- 427,442 ----
>           {
>   #ifndef GENERATOR_FILE
>             fprintf (outfile, " %s:%i",
> !                    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",
> !                    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 189835)
> --- gcc/profile.c       (working copy)
> *************** branch_prob (void)
> *** 966,972 ****
>              is not computed twice.  */
>           if (last
>               && gimple_has_location (last)
> !             && e->goto_locus != UNKNOWN_LOCATION
>               && !single_succ_p (bb)
>               && (LOCATION_FILE (e->goto_locus)
>                   != LOCATION_FILE (gimple_location (last))
> --- 966,972 ----
>              is not computed twice.  */
>           if (last
>               && gimple_has_location (last)
> !             && !IS_UNKNOWN_LOCATION (e->goto_locus)
>               && !single_succ_p (bb)
>               && (LOCATION_FILE (e->goto_locus)
>                   != LOCATION_FILE (gimple_location (last))
> *************** branch_prob (void)
> *** 976,982 ****
>               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)
> --- 976,981 ----
> *************** branch_prob (void)
> *** 1188,1194 ****
>
>           /* Notice GOTO expressions eliminated while constructing the CFG.  */
>           if (single_succ_p (bb)
> !             && single_succ_edge (bb)->goto_locus != UNKNOWN_LOCATION)
>             {
>               expanded_location curr_location
>                 = expand_location (single_succ_edge (bb)->goto_locus);
> --- 1187,1193 ----
>
>           /* Notice GOTO expressions eliminated while constructing the CFG.  */
>           if (single_succ_p (bb)
> !             && !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 189835)
> --- gcc/trans-mem.c     (working copy)
> *************** ipa_tm_scan_irr_block (basic_block bb)
> *** 3796,3802 ****
>             {
>               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;
> --- 3796,3801 ----
> Index: gcc/gimplify.c
> ===================================================================
> *** gcc/gimplify.c      (revision 189835)
> --- gcc/gimplify.c      (working copy)
> *************** gimplify_call_expr (tree *expr_p, gimple
> *** 2600,2606 ****
>             = 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;
> --- 2600,2605 ----
> Index: gcc/except.c
> ===================================================================
> *** gcc/except.c        (revision 189835)
> --- gcc/except.c        (working copy)
> *************** duplicate_eh_regions_1 (struct duplicate
> *** 526,532 ****
>         break;
>
>       case ERT_MUST_NOT_THROW:
> !       new_r->u.must_not_throw = old_r->u.must_not_throw;
>         break;
>       }
>
> --- 526,535 ----
>         break;
>
>       case ERT_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 189835)
> --- gcc/emit-rtl.c      (working copy)
> *************** try_split (rtx pat, rtx trial, int last)
> *** 3634,3640 ****
>         }
>       }
>
> !   tem = emit_insn_after_setloc (seq, trial, INSN_LOCATOR (trial));
>
>     delete_insn (trial);
>     if (has_barrier)
> --- 3634,3640 ----
>         }
>       }
>
> !   tem = emit_insn_after_setloc (seq, trial, INSN_LOCATION (trial));
>
>     delete_insn (trial);
>     if (has_barrier)
> *************** make_insn_raw (rtx pattern)
> *** 3670,3676 ****
>     PATTERN (insn) = pattern;
>     INSN_CODE (insn) = -1;
>     REG_NOTES (insn) = NULL;
> !   INSN_LOCATOR (insn) = curr_insn_locator ();
>     BLOCK_FOR_INSN (insn) = NULL;
>
>   #ifdef ENABLE_RTL_CHECKING
> --- 3670,3676 ----
>     PATTERN (insn) = pattern;
>     INSN_CODE (insn) = -1;
>     REG_NOTES (insn) = NULL;
> !   INSN_LOCATION (insn) = curr_insn_location ();
>     BLOCK_FOR_INSN (insn) = NULL;
>
>   #ifdef ENABLE_RTL_CHECKING
> *************** make_debug_insn_raw (rtx pattern)
> *** 3703,3709 ****
>     PATTERN (insn) = pattern;
>     INSN_CODE (insn) = -1;
>     REG_NOTES (insn) = NULL;
> !   INSN_LOCATOR (insn) = curr_insn_locator ();
>     BLOCK_FOR_INSN (insn) = NULL;
>
>     return insn;
> --- 3703,3709 ----
>     PATTERN (insn) = pattern;
>     INSN_CODE (insn) = -1;
>     REG_NOTES (insn) = NULL;
> !   INSN_LOCATION (insn) = curr_insn_location ();
>     BLOCK_FOR_INSN (insn) = NULL;
>
>     return insn;
> *************** make_jump_insn_raw (rtx pattern)
> *** 3723,3729 ****
>     INSN_CODE (insn) = -1;
>     REG_NOTES (insn) = NULL;
>     JUMP_LABEL (insn) = NULL;
> !   INSN_LOCATOR (insn) = curr_insn_locator ();
>     BLOCK_FOR_INSN (insn) = NULL;
>
>     return insn;
> --- 3723,3729 ----
>     INSN_CODE (insn) = -1;
>     REG_NOTES (insn) = NULL;
>     JUMP_LABEL (insn) = NULL;
> !   INSN_LOCATION (insn) = curr_insn_location ();
>     BLOCK_FOR_INSN (insn) = NULL;
>
>     return insn;
> *************** make_call_insn_raw (rtx pattern)
> *** 3743,3749 ****
>     INSN_CODE (insn) = -1;
>     REG_NOTES (insn) = NULL;
>     CALL_INSN_FUNCTION_USAGE (insn) = NULL;
> !   INSN_LOCATOR (insn) = curr_insn_locator ();
>     BLOCK_FOR_INSN (insn) = NULL;
>
>     return insn;
> --- 3743,3749 ----
>     INSN_CODE (insn) = -1;
>     REG_NOTES (insn) = NULL;
>     CALL_INSN_FUNCTION_USAGE (insn) = NULL;
> !   INSN_LOCATION (insn) = curr_insn_location ();
>     BLOCK_FOR_INSN (insn) = NULL;
>
>     return insn;
> *************** emit_pattern_after_setloc (rtx pattern,
> *** 4416,4423 ****
>     after = NEXT_INSN (after);
>     while (1)
>       {
> !       if (active_insn_p (after) && !INSN_LOCATOR (after))
> !       INSN_LOCATOR (after) = loc;
>         if (after == last)
>         break;
>         after = NEXT_INSN (after);
> --- 4416,4423 ----
>     after = NEXT_INSN (after);
>     while (1)
>       {
> !       if (active_insn_p (after) && !INSN_LOCATION (after))
> !       INSN_LOCATION (after) = loc;
>         if (after == last)
>         break;
>         after = NEXT_INSN (after);
> *************** emit_pattern_after (rtx pattern, rtx aft
> *** 4440,4501 ****
>         prev = PREV_INSN (prev);
>
>     if (INSN_P (prev))
> !     return emit_pattern_after_setloc (pattern, after, INSN_LOCATOR (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.  */
>   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.  */
>   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.  */
>   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.  */
>   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.  */
>   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.  */
>   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.  */
>   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.  */
>   rtx
>   emit_debug_insn_after (rtx pattern, rtx after)
>   {
> --- 4440,4501 ----
>         prev = PREV_INSN (prev);
>
>     if (INSN_P (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_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_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_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_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_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_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_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_LOCATION according
> to AFTER.  */
>   rtx
>   emit_debug_insn_after (rtx pattern, rtx after)
>   {
> *************** emit_pattern_before_setloc (rtx pattern,
> *** 4525,4532 ****
>       first = NEXT_INSN (first);
>     while (1)
>       {
> !       if (active_insn_p (first) && !INSN_LOCATOR (first))
> !       INSN_LOCATOR (first) = loc;
>         if (first == last)
>         break;
>         first = NEXT_INSN (first);
> --- 4525,4532 ----
>       first = NEXT_INSN (first);
>     while (1)
>       {
> !       if (active_insn_p (first) && !INSN_LOCATION (first))
> !       INSN_LOCATION (first) = loc;
>         if (first == last)
>         break;
>         first = NEXT_INSN (first);
> *************** emit_pattern_before (rtx pattern, rtx be
> *** 4550,4556 ****
>         next = PREV_INSN (next);
>
>     if (INSN_P (next))
> !     return emit_pattern_before_setloc (pattern, before, INSN_LOCATOR (next),
>                                        insnp, make_raw);
>     else
>       return emit_pattern_before_noloc (pattern, before,
> --- 4550,4556 ----
>         next = PREV_INSN (next);
>
>     if (INSN_P (next))
> !     return emit_pattern_before_setloc (pattern, before, INSN_LOCATION (next),
>                                        insnp, make_raw);
>     else
>       return emit_pattern_before_noloc (pattern, before,
> *************** emit_pattern_before (rtx pattern, rtx be
> *** 4558,4564 ****
>                                         NULL, make_raw);
>   }
>
> ! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
>   rtx
>   emit_insn_before_setloc (rtx pattern, rtx before, int loc)
>   {
> --- 4558,4564 ----
>                                         NULL, make_raw);
>   }
>
> ! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
>   rtx
>   emit_insn_before_setloc (rtx pattern, rtx before, int loc)
>   {
> *************** emit_insn_before_setloc (rtx pattern, rt
> *** 4566,4579 ****
>                                      make_insn_raw);
>   }
>
> ! /* Like emit_insn_before_noloc, but set INSN_LOCATOR 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.  */
>   rtx
>   emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
>   {
> --- 4566,4579 ----
>                                      make_insn_raw);
>   }
>
> ! /* 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_LOCATION according to LOC.  */
>   rtx
>   emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
>   {
> *************** emit_jump_insn_before_setloc (rtx patter
> *** 4581,4587 ****
>                                      make_jump_insn_raw);
>   }
>
> ! /* Like emit_jump_insn_before_noloc, but set INSN_LOCATOR according
> to BEFORE.  */
>   rtx
>   emit_jump_insn_before (rtx pattern, rtx before)
>   {
> --- 4581,4587 ----
>                                      make_jump_insn_raw);
>   }
>
> ! /* Like emit_jump_insn_before_noloc, but set INSN_LOCATION according
> to BEFORE.  */
>   rtx
>   emit_jump_insn_before (rtx pattern, rtx before)
>   {
> *************** emit_jump_insn_before (rtx pattern, rtx
> *** 4589,4595 ****
>                               make_jump_insn_raw);
>   }
>
> ! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
>   rtx
>   emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
>   {
> --- 4589,4595 ----
>                               make_jump_insn_raw);
>   }
>
> ! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
>   rtx
>   emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
>   {
> *************** emit_call_insn_before_setloc (rtx patter
> *** 4598,4604 ****
>   }
>
>   /* Like emit_call_insn_before_noloc,
> !    but set insn_locator according to BEFORE.  */
>   rtx
>   emit_call_insn_before (rtx pattern, rtx before)
>   {
> --- 4598,4604 ----
>   }
>
>   /* Like emit_call_insn_before_noloc,
> !    but set insn_location according to BEFORE.  */
>   rtx
>   emit_call_insn_before (rtx pattern, rtx before)
>   {
> *************** emit_call_insn_before (rtx pattern, rtx
> *** 4606,4612 ****
>                               make_call_insn_raw);
>   }
>
> ! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
>   rtx
>   emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
>   {
> --- 4606,4612 ----
>                               make_call_insn_raw);
>   }
>
> ! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
>   rtx
>   emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
>   {
> *************** emit_debug_insn_before_setloc (rtx patte
> *** 4615,4621 ****
>   }
>
>   /* Like emit_debug_insn_before_noloc,
> !    but set insn_locator according to BEFORE.  */
>   rtx
>   emit_debug_insn_before (rtx pattern, rtx before)
>   {
> --- 4615,4621 ----
>   }
>
>   /* Like emit_debug_insn_before_noloc,
> !    but set insn_location according to BEFORE.  */
>   rtx
>   emit_debug_insn_before (rtx pattern, rtx before)
>   {
> *************** emit_copy_of_insn_after (rtx insn, rtx a
> *** 5865,5871 ****
>     /* Update LABEL_NUSES.  */
>     mark_jump_label (PATTERN (new_rtx), new_rtx, 0);
>
> !   INSN_LOCATOR (new_rtx) = INSN_LOCATOR (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,
> --- 5865,5871 ----
>     /* Update LABEL_NUSES.  */
>     mark_jump_label (PATTERN (new_rtx), new_rtx, 0);
>
> !   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,
> *************** gen_hard_reg_clobber (enum machine_mode
> *** 5900,6149 ****
>             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_O(location_t);
> ! DEF_VEC_ALLOC_O(location_t,heap);
> ! static VEC(location_t,heap) *locations_locators_vals;
> ! int prologue_locator;
> ! int epilogue_locator;
>
>   /* 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.  */
>   void
> ! insn_locators_alloc (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);
> !
>     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)
> ! {
> !   if (curr_rtl_loc >= 0)
> !     epilogue_locator = curr_insn_locator ();
> !   curr_rtl_loc = -1;
> ! }
> !
> ! /* 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)
>   {
> -   /* 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)
>   {
>     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 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 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 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.  */
> --- 5900,5965 ----
>             gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
>   }
>
> ! 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;
>
> ! /* Allocate insn location datastructure.  */
>   void
> ! insn_locations_init (void)
>   {
> !   prologue_location = epilogue_location = 0;
>     curr_location = UNKNOWN_LOCATION;
>     last_location = UNKNOWN_LOCATION;
>   }
>
>   /* At the end of emit stage, clear current location.  */
>   void
> ! insn_locations_finalize (void)
>   {
> !   epilogue_location = curr_location;
> !   curr_location = UNKNOWN_LOCATION;
>   }
>
>   /* Set current location.  */
>   void
> ! set_curr_insn_location (location_t location)
>   {
>     curr_location = location;
>   }
>
>   /* Get current location.  */
>   location_t
> ! curr_insn_location (void)
>   {
>     return curr_location;
>   }
>
>   /* Return lexical scope block insn belongs to.  */
>   tree
>   insn_scope (const_rtx insn)
>   {
> !   return LOCATION_BLOCK (INSN_LOCATION (insn));
>   }
>
>   /* Return line number of the statement that produced this insn.  */
>   int
>   insn_line (const_rtx insn)
>   {
> !   return LOCATION_LINE (INSN_LOCATION (insn));
>   }
>
>   /* Return source file of the statement that produced this insn.  */
>   const char *
>   insn_file (const_rtx insn)
>   {
> !   return LOCATION_FILE (INSN_LOCATION (insn));
>   }
>
>   /* 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 189835)
> --- gcc/cfgexpand.c     (working copy)
> *************** gimple_assign_rhs_to_tree (gimple stmt)
> *** 92,99 ****
>            && gimple_location (stmt) != EXPR_LOCATION (t))
>           || (gimple_block (stmt)
>               && currently_expanding_to_rtl
> !             && EXPR_P (t)
> !             && gimple_block (stmt) != TREE_BLOCK (t)))
>         t = copy_node (t);
>       }
>     else
> --- 92,98 ----
>            && gimple_location (stmt) != EXPR_LOCATION (t))
>           || (gimple_block (stmt)
>               && currently_expanding_to_rtl
> !             && EXPR_P (t)))
>         t = copy_node (t);
>       }
>     else
> *************** gimple_assign_rhs_to_tree (gimple stmt)
> *** 101,108 ****
>
>     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;
>   }
> --- 100,105 ----
> *************** expand_gimple_cond (basic_block bb, gimp
> *** 1804,1811 ****
>     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));
>
>     /* These flags have no purpose in RTL land.  */
>     true_edge->flags &= ~EDGE_TRUE_VALUE;
> --- 1801,1807 ----
>     last2 = last = get_last_insn ();
>
>     extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
> !   set_curr_insn_location (gimple_location (stmt));
>
>     /* These flags have no purpose in RTL land.  */
>     true_edge->flags &= ~EDGE_TRUE_VALUE;
> *************** expand_gimple_cond (basic_block bb, gimp
> *** 1818,1830 ****
>         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;
>         false_edge->flags |= EDGE_FALLTHRU;
>         maybe_cleanup_end_of_block (false_edge, last);
>         return NULL;
> --- 1814,1821 ----
>         jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
>                 true_edge->probability);
>         maybe_dump_rtl_for_gimple_stmt (stmt, last);
> !       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;
> *************** expand_gimple_cond (basic_block bb, gimp
> *** 1834,1846 ****
>         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;
>         true_edge->flags |= EDGE_FALLTHRU;
>         maybe_cleanup_end_of_block (true_edge, last);
>         return NULL;
> --- 1825,1832 ----
>         jumpifnot_1 (code, op0, op1, label_rtx_for_bb (false_edge->dest),
>                    false_edge->probability);
>         maybe_dump_rtl_for_gimple_stmt (stmt, last);
> !       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;
> *************** expand_gimple_cond (basic_block bb, gimp
> *** 1849,1861 ****
>     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;
>     emit_jump (label_rtx_for_bb (false_edge->dest));
>
>     BB_END (bb) = last;
> --- 1835,1842 ----
>     jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
>             true_edge->probability);
>     last = get_last_insn ();
> !   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;
> *************** expand_gimple_cond (basic_block bb, gimp
> *** 1880,1892 ****
>
>     maybe_dump_rtl_for_gimple_stmt (stmt, last2);
>
> !   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;
>
>     return new_bb;
>   }
> --- 1861,1871 ----
>
>     maybe_dump_rtl_for_gimple_stmt (stmt, last2);
>
> !   if (!IS_UNKNOWN_LOCATION (true_edge->goto_locus))
>       {
> !       set_curr_insn_location (true_edge->goto_locus);
> !       true_edge->goto_locus = curr_insn_location ();
>       }
>
>     return new_bb;
>   }
> *************** expand_call_stmt (gimple stmt)
> *** 1986,1992 ****
>       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))
> --- 1965,1970 ----
> *************** expand_gimple_stmt_1 (gimple stmt)
> *** 2021,2028 ****
>   {
>     tree op0;
>
> !   set_curr_insn_source_location (gimple_location (stmt));
> !   set_curr_insn_block (gimple_block (stmt));
>
>     switch (gimple_code (stmt))
>       {
> --- 1999,2005 ----
>   {
>     tree op0;
>
> !   set_curr_insn_location (gimple_location (stmt));
>
>     switch (gimple_code (stmt))
>       {
> *************** expand_gimple_basic_block (basic_block b
> *** 3766,3773 ****
>           tree op;
>           gimple def;
>
> !         location_t sloc = get_curr_insn_source_location ();
> !         tree sblock = get_curr_insn_block ();
>
>           /* Look for SSA names that have their last use here (TERed
>              names always have only one real use).  */
> --- 3743,3749 ----
>           tree op;
>           gimple def;
>
> !         location_t sloc = curr_insn_location ();
>
>           /* Look for SSA names that have their last use here (TERed
>              names always have only one real use).  */
> *************** expand_gimple_basic_block (basic_block b
> *** 3800,3807 ****
>                     rtx val;
>                     enum machine_mode mode;
>
> !                   set_curr_insn_source_location (gimple_location (def));
> !                   set_curr_insn_block (gimple_block (def));
>
>                     DECL_ARTIFICIAL (vexpr) = 1;
>                     TREE_TYPE (vexpr) = TREE_TYPE (value);
> --- 3776,3782 ----
>                     rtx val;
>                     enum machine_mode mode;
>
> !                   set_curr_insn_location (gimple_location (def));
>
>                     DECL_ARTIFICIAL (vexpr) = 1;
>                     TREE_TYPE (vexpr) = TREE_TYPE (value);
> *************** expand_gimple_basic_block (basic_block b
> *** 3828,3835 ****
>                       }
>                   }
>               }
> !         set_curr_insn_source_location (sloc);
> !         set_curr_insn_block (sblock);
>         }
>
>         currently_expanding_gimple_stmt = stmt;
> --- 3803,3809 ----
>                       }
>                   }
>               }
> !         set_curr_insn_location (sloc);
>         }
>
>         currently_expanding_gimple_stmt = stmt;
> *************** expand_gimple_basic_block (basic_block b
> *** 3844,3851 ****
>         }
>         else if (gimple_debug_bind_p (stmt))
>         {
> !         location_t sloc = get_curr_insn_source_location ();
> !         tree sblock = get_curr_insn_block ();
>           gimple_stmt_iterator nsi = gsi;
>
>           for (;;)
> --- 3818,3824 ----
>         }
>         else if (gimple_debug_bind_p (stmt))
>         {
> !         location_t sloc = curr_insn_location ();
>           gimple_stmt_iterator nsi = gsi;
>
>           for (;;)
> *************** expand_gimple_basic_block (basic_block b
> *** 3867,3874 ****
>
>               last = get_last_insn ();
>
> !             set_curr_insn_source_location (gimple_location (stmt));
> !             set_curr_insn_block (gimple_block (stmt));
>
>               if (DECL_P (var))
>                 mode = DECL_MODE (var);
> --- 3840,3846 ----
>
>               last = get_last_insn ();
>
> !             set_curr_insn_location (gimple_location (stmt));
>
>               if (DECL_P (var))
>                 mode = DECL_MODE (var);
> *************** expand_gimple_basic_block (basic_block b
> *** 3906,3918 ****
>                 break;
>             }
>
> !         set_curr_insn_source_location (sloc);
> !         set_curr_insn_block (sblock);
>         }
>         else if (gimple_debug_source_bind_p (stmt))
>         {
> !         location_t sloc = get_curr_insn_source_location ();
> !         tree sblock = get_curr_insn_block ();
>           tree var = gimple_debug_source_bind_get_var (stmt);
>           tree value = gimple_debug_source_bind_get_value (stmt);
>           rtx val;
> --- 3878,3888 ----
>                 break;
>             }
>
> !         set_curr_insn_location (sloc);
>         }
>         else if (gimple_debug_source_bind_p (stmt))
>         {
> !         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;
> *************** expand_gimple_basic_block (basic_block b
> *** 3920,3927 ****
>
>           last = get_last_insn ();
>
> !         set_curr_insn_source_location (gimple_location (stmt));
> !         set_curr_insn_block (gimple_block (stmt));
>
>           mode = DECL_MODE (var);
>
> --- 3890,3896 ----
>
>           last = get_last_insn ();
>
> !         set_curr_insn_location (gimple_location (stmt));
>
>           mode = DECL_MODE (var);
>
> *************** expand_gimple_basic_block (basic_block b
> *** 3939,3946 ****
>               PAT_VAR_LOCATION_LOC (val) = (rtx)value;
>             }
>
> !         set_curr_insn_source_location (sloc);
> !         set_curr_insn_block (sblock);
>         }
>         else
>         {
> --- 3908,3914 ----
>               PAT_VAR_LOCATION_LOC (val) = (rtx)value;
>             }
>
> !         set_curr_insn_location (sloc);
>         }
>         else
>         {
> *************** expand_gimple_basic_block (basic_block b
> *** 3981,3993 ****
>     /* 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 ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb)
>         {
>           emit_jump (label_rtx_for_bb (e->dest));
> --- 3949,3956 ----
>     /* Expand implicit goto and convert goto_locus.  */
>     FOR_EACH_EDGE (e, ei, bb->succs)
>       {
> !       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));
> *************** construct_exit_block (void)
> *** 4107,4118 ****
>
>     /* 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)
>       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 ();
>
> --- 4070,4078 ----
>
>     /* Make sure the locus is set to the end of the function, so that
>        epilogue line numbers and warnings are set properly.  */
> !   if (!IS_UNKNOWN_LOCATION (cfun->function_end_locus))
>       input_location = cfun->function_end_locus;
>
>     /* Generate rtl for function exit.  */
>     expand_function_end ();
>
> *************** gimple_expand_cfg (void)
> *** 4331,4350 ****
>
>     rtl_profile_for_bb (ENTRY_BLOCK_PTR);
>
> !   insn_locators_alloc ();
>     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
>            (DECL_SOURCE_LOCATION (current_function_decl));
>         else
> !        set_curr_insn_source_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 ();
>
>   #ifdef INSN_SCHEDULING
>     init_sched_attrs ();
> --- 4291,4309 ----
>
>     rtl_profile_for_bb (ENTRY_BLOCK_PTR);
>
> !   insn_locations_init ();
>     if (!DECL_IS_BUILTIN (current_function_decl))
>       {
>         /* Eventually, all FEs should explicitly set function_start_locus.  */
> !       if (IS_UNKNOWN_LOCATION (cfun->function_start_locus))
> !        set_curr_insn_location
>            (DECL_SOURCE_LOCATION (current_function_decl));
>         else
> !        set_curr_insn_location (cfun->function_start_locus);
>       }
>     else
> !     set_curr_insn_location (UNKNOWN_LOCATION);
> !   prologue_location = curr_insn_location ();
>
>   #ifdef INSN_SCHEDULING
>     init_sched_attrs ();
> *************** gimple_expand_cfg (void)
> *** 4514,4521 ****
>     free_histograms ();
>
>     construct_exit_block ();
> !   set_curr_insn_block (DECL_INITIAL (current_function_decl));
> !   insn_locators_finalize ();
>
>     /* Zap the tree EH table.  */
>     set_eh_throw_stmt_table (cfun, NULL);
> --- 4473,4479 ----
>     free_histograms ();
>
>     construct_exit_block ();
> !   insn_locations_finalize ();
>
>     /* Zap the tree EH table.  */
>     set_eh_throw_stmt_table (cfun, NULL);
> Index: gcc/cfgcleanup.c
> ===================================================================
> *** gcc/cfgcleanup.c    (revision 189835)
> --- gcc/cfgcleanup.c    (working copy)
> *************** try_forward_edges (int mode, basic_block
> *** 481,493 ****
>                   int new_locus = single_succ_edge (target)->goto_locus;
>                   int locus = goto_locus;
>
> !                 if (new_locus && locus && !locator_eq (new_locus, locus))
>                     new_target = NULL;
>                   else
>                     {
>                       rtx last;
>
> !                     if (new_locus)
>                         locus = new_locus;
>
>                       last = BB_END (target);
> --- 481,495 ----
>                   int new_locus = single_succ_edge (target)->goto_locus;
>                   int locus = goto_locus;
>
> !                 if (!IS_UNKNOWN_LOCATION (new_locus)
> !                     && !IS_UNKNOWN_LOCATION (locus)
> !                     && new_locus != locus)
>                     new_target = NULL;
>                   else
>                     {
>                       rtx last;
>
> !                     if (!IS_UNKNOWN_LOCATION (new_locus))
>                         locus = new_locus;
>
>                       last = BB_END (target);
> *************** try_forward_edges (int mode, basic_block
> *** 495,507 ****
>                         last = prev_nondebug_insn (last);
>
>                       new_locus = last && INSN_P (last)
> !                                 ? INSN_LOCATOR (last) : 0;
>
> !                     if (new_locus && locus && !locator_eq (new_locus, locus))
>                         new_target = NULL;
>                       else
>                         {
> !                         if (new_locus)
>                             locus = new_locus;
>
>                           goto_locus = locus;
> --- 497,511 ----
>                         last = prev_nondebug_insn (last);
>
>                       new_locus = last && INSN_P (last)
> !                                 ? INSN_LOCATION (last) : 0;
>
> !                     if (!IS_UNKNOWN_LOCATION (new_locus)
> !                         && !IS_UNKNOWN_LOCATION (locus)
> !                         && new_locus != locus)
>                         new_target = NULL;
>                       else
>                         {
> !                         if (!IS_UNKNOWN_LOCATION (new_locus))
>                             locus = new_locus;
>
>                           goto_locus = locus;
> Index: gcc/tree-ssa-live.c
> ===================================================================
> *** gcc/tree-ssa-live.c (revision 189835)
> --- gcc/tree-ssa-live.c (working copy)
> *************** remove_unused_scope_block_p (tree scope,
> *** 587,593 ****
>      else
>      /* Verfify that only blocks with source location set
>         are entry points to the inlined functions.  */
> !      gcc_assert (BLOCK_SOURCE_LOCATION (scope) == UNKNOWN_LOCATION);
>
>      TREE_USED (scope) = !unused;
>      return unused;
> --- 587,593 ----
>      else
>      /* Verfify that only blocks with source location set
>         are entry points to the inlined functions.  */
> !      gcc_assert (IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (scope)));
>
>      TREE_USED (scope) = !unused;
>      return unused;
> *************** dump_scope_block (FILE *file, int indent
> *** 615,621 ****
>     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)
>       {
>         expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (scope));
>         fprintf (file, " %s:%i", s.file, s.line);
> --- 615,621 ----
>     fprintf (file, "\n%*s{ Scope block #%i%s%s",indent, "" ,
> BLOCK_NUMBER (scope),
>            TREE_USED (scope) ? "" : " (unused)",
>            BLOCK_ABSTRACT (scope) ? " (abstract)": "");
> !   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);
> *************** remove_unused_locals (void)
> *** 765,777 ****
>             FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_ALL_USES)
>               {
>               tree arg = USE_FROM_PTR (arg_p);
>               mark_all_vars_used (&arg, global_unused_vars);
>               }
>           }
>
>         FOR_EACH_EDGE (e, ei, bb->succs)
>         if (e->goto_locus)
> !         TREE_USED (e->goto_block) = true;
>       }
>
>     /* We do a two-pass approach about the out-of-scope clobbers.  We want
> --- 765,782 ----
>             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, global_unused_vars);
>               }
>           }
>
>         FOR_EACH_EDGE (e, ei, bb->succs)
>         if (e->goto_locus)
> !         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 189835)
> --- gcc/lto/lto.c       (working copy)
> *************** lto_fixup_prevailing_decls (tree t)
> *** 1603,1609 ****
>     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));
>       }
> --- 1603,1608 ----
> Index: gcc/tree-streamer-out.c
> ===================================================================
> *** gcc/tree-streamer-out.c     (revision 189835)
> --- gcc/tree-streamer-out.c     (working copy)
> *************** write_ts_decl_minimal_tree_pointers (str
> *** 471,477 ****
>   {
>     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));
>   }
>
>
> --- 471,477 ----
>   {
>     stream_write_tree (ob, DECL_NAME (expr), ref_p);
>     stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
> !   lto_output_location (ob, LOCATION_LOCUS (DECL_SOURCE_LOCATION (expr)));
>   }
>
>
> *************** write_ts_exp_tree_pointers (struct outpu
> *** 668,674 ****
>     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));
>     stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
>   }
>
> --- 668,674 ----
>     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, LOCATION_LOCUS (EXPR_LOCATION (expr)));
>     stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
>   }
>
> Index: gcc/rtl.c
> ===================================================================
> *** gcc/rtl.c   (revision 189835)
> --- gcc/rtl.c   (working copy)
> *************** rtx_equal_p_cb (const_rtx x, const_rtx y
> *** 440,446 ****
>   #ifndef GENERATOR_FILE
>               if (((code == ASM_OPERANDS && i == 6)
>                    || (code == ASM_INPUT && i == 1))
> !                 && locator_eq (XINT (x, i), XINT (y, i)))
>                 break;
>   #endif
>               return 0;
> --- 440,446 ----
>   #ifndef GENERATOR_FILE
>               if (((code == ASM_OPERANDS && i == 6)
>                    || (code == ASM_INPUT && i == 1))
> !                 && XINT (x, i) == XINT (y, i))
>                 break;
>   #endif
>               return 0;
> *************** rtx_equal_p (const_rtx x, const_rtx y)
> *** 579,585 ****
>   #ifndef GENERATOR_FILE
>               if (((code == ASM_OPERANDS && i == 6)
>                    || (code == ASM_INPUT && i == 1))
> !                 && locator_eq (XINT (x, i), XINT (y, i)))
>                 break;
>   #endif
>               return 0;
> --- 579,585 ----
>   #ifndef GENERATOR_FILE
>               if (((code == ASM_OPERANDS && i == 6)
>                    || (code == ASM_INPUT && i == 1))
> !                 && XINT (x, i) == XINT (y, i))
>                 break;
>   #endif
>               return 0;
> Index: gcc/rtl.h
> ===================================================================
> *** gcc/rtl.h   (revision 189835)
> --- gcc/rtl.h   (working copy)
> *************** extern void rtl_check_failed_flag (const
> *** 739,744 ****
> --- 739,745 ----
>   #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)
> *************** extern void rtl_check_failed_flag (const
> *** 802,814 ****
>   /* The body of an insn.  */
>   #define PATTERN(INSN) XEXP (INSN, 4)
>
> ! #define INSN_LOCATOR(INSN) XINT (INSN, 5)
>   /* 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 ()))
>
>   /* Code number of instruction, from when it was recognized.
>      -1 means this instruction has not been recognized yet.  */
> --- 803,815 ----
>   /* The body of an insn.  */
>   #define PATTERN(INSN) XEXP (INSN, 4)
>
> ! #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) ? \
> !                        INSN_LOCATION (X) : UNKNOWN_LOCATION)
>
>   /* Code number of instruction, from when it was recognized.
>      -1 means this instruction has not been recognized yet.  */
> *************** extern rtx prev_cc0_setter (rtx);
> *** 1807,1818 ****
>   /* 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);
>
>   /* In jump.c */
>   extern enum rtx_code reverse_condition (enum rtx_code);
> --- 1808,1815 ----
>   /* In emit-rtl.c  */
>   extern int insn_line (const_rtx);
>   extern const char * insn_file (const_rtx);
>   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);
> *************** extern const struct rtl_hooks general_rt
> *** 2648,2661 ****
>   /* 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 bool optimize_insn_for_size_p (void);
>   extern bool optimize_insn_for_speed_p (void);
>
> --- 2645,2654 ----
>   /* Keep this for the nonce.  */
>   #define gen_lowpart rtl_hooks.gen_lowpart
>
> ! 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 189835)
> --- gcc/tree-inline.c   (working copy)
> *************** remap_gimple_op_r (tree *tp, int *walk_s
> *** 852,861 ****
>         /* 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);
> --- 852,857 ----
> *************** remap_gimple_op_r (tree *tp, int *walk_s
> *** 901,913 ****
>         {
>           /* 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.  */
>           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,
> --- 897,905 ----
>         {
>           /* Variable substitution need not be simple.  In particular,
>              the MEM_REF substitution above.  Make sure that
> !            TREE_CONSTANT and friends are up-to-date.  */
>           int invariant = is_gimple_min_invariant (*tp);
>           walk_tree (&TREE_OPERAND (*tp, 0), remap_gimple_op_r, data, NULL);
>           recompute_tree_invariant_for_addr_expr (*tp);
>
>           /* If this used to be invariant, but is not any longer,
> *************** remap_gimple_op_r (tree *tp, int *walk_s
> *** 919,924 ****
> --- 911,932 ----
>         }
>       }
>
> +   /* 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;
>   }
> *************** copy_tree_body_r (tree *tp, int *walk_su
> *** 1144,1154 ****
>               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;
>         }
>
>         if (TREE_CODE (*tp) != OMP_CLAUSE)
> --- 1152,1161 ----
>               tree *n;
>               n = (tree *) pointer_map_contains (id->decl_map,
>                                                  TREE_BLOCK (*tp));
>               if (n)
>                 new_block = *n;
>             }
> !         TREE_SET_BLOCK (*tp, new_block);
>         }
>
>         if (TREE_CODE (*tp) != OMP_CLAUSE)
> *************** copy_phis_for_bb (basic_block bb, copy_b
> *** 2020,2025 ****
> --- 2027,2033 ----
>               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
> *************** copy_phis_for_bb (basic_block bb, copy_b
> *** 2031,2039 ****
>
>               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.  */
> --- 2039,2045 ----
> *************** copy_phis_for_bb (basic_block bb, copy_b
> *** 2046,2053 ****
>                   gsi_insert_seq_on_edge (new_edge, stmts);
>                   inserted = true;
>                 }
>               add_phi_arg (new_phi, new_arg, new_edge,
> !                          gimple_phi_arg_location_from_edge (phi, old_edge));
>             }
>         }
>       }
> --- 2052,2070 ----
>                   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,
> !                          COMBINE_LOCATION (locus, block));
>             }
>         }
>       }
> *************** expand_call_inline (basic_block bb, gimp
> *** 3946,3952 ****
>     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);
>
>     /* Local declarations will be replaced by their equivalents in this
>        map.  */
> --- 3963,3970 ----
>     id->block = make_node (BLOCK);
>     BLOCK_ABSTRACT_ORIGIN (id->block) = fn;
>     BLOCK_SOURCE_LOCATION (id->block) = input_location;
> !   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 189835)
> --- gcc/tree-streamer-in.c      (working copy)
> *************** lto_input_ts_exp_tree_pointers (struct l
> *** 776,782 ****
>
>     loc = lto_input_location (ib, data_in);
>     SET_EXPR_LOCATION (expr, loc);
> !   TREE_BLOCK (expr) = stream_read_tree (ib, data_in);
>   }
>
>
> --- 776,782 ----
>
>     loc = lto_input_location (ib, data_in);
>     SET_EXPR_LOCATION (expr, loc);
> !   TREE_SET_BLOCK (expr, stream_read_tree (ib, data_in));
>   }
>
>
> Index: gcc/combine.c
> ===================================================================
> *** gcc/combine.c       (revision 189835)
> --- gcc/combine.c       (working copy)
> *************** try_combine (rtx i3, rtx i2, rtx i1, rtx
> *** 2896,2902 ****
>
>           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);
>
>           SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
>           SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
> --- 2896,2902 ----
>
>           i1 = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
>                              BLOCK_FOR_INSN (i2), XVECEXP (PATTERN (i2), 0, 1),
> !                            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 189835)
> --- gcc/tree-outof-ssa.c        (working copy)
> *************** set_location_for_edge (edge e)
> *** 108,115 ****
>   {
>     if (e->goto_locus)
>       {
> !       set_curr_insn_source_location (e->goto_locus);
> !       set_curr_insn_block (e->goto_block);
>       }
>     else
>       {
> --- 108,114 ----
>   {
>     if (e->goto_locus)
>       {
> !       set_curr_insn_location (e->goto_locus);
>       }
>     else
>       {
> *************** set_location_for_edge (edge e)
> *** 125,132 ****
>                 continue;
>               if (gimple_has_location (stmt) || gimple_block (stmt))
>                 {
> !                 set_curr_insn_source_location (gimple_location (stmt));
> !                 set_curr_insn_block (gimple_block (stmt));
>                   return;
>                 }
>             }
> --- 124,130 ----
>                 continue;
>               if (gimple_has_location (stmt) || gimple_block (stmt))
>                 {
> !                 set_curr_insn_location (gimple_location (stmt));
>                   return;
>                 }
>             }
> *************** insert_partition_copy_on_edge (edge e, i
> *** 191,197 ****
>     set_location_for_edge (e);
>     /* If a locus is provided, override the default.  */
>     if (locus)
> !     set_curr_insn_source_location (locus);
>
>     var = partition_to_var (SA.map, src);
>     seq = emit_partition_copy (SA.partition_to_pseudo[dest],
> --- 189,195 ----
>     set_location_for_edge (e);
>     /* If a locus is provided, override the default.  */
>     if (locus)
> !     set_curr_insn_location (locus);
>
>     var = partition_to_var (SA.map, src);
>     seq = emit_partition_copy (SA.partition_to_pseudo[dest],
> *************** insert_value_copy_on_edge (edge e, int d
> *** 228,234 ****
>     set_location_for_edge (e);
>     /* If a locus is provided, override the default.  */
>     if (locus)
> !     set_curr_insn_source_location (locus);
>
>     start_sequence ();
>
> --- 226,232 ----
>     set_location_for_edge (e);
>     /* If a locus is provided, override the default.  */
>     if (locus)
> !     set_curr_insn_location (locus);
>
>     start_sequence ();
>
> *************** insert_rtx_to_part_on_edge (edge e, int
> *** 284,290 ****
>     set_location_for_edge (e);
>     /* If a locus is provided, override the default.  */
>     if (locus)
> !     set_curr_insn_source_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
> --- 282,288 ----
>     set_location_for_edge (e);
>     /* If a locus is provided, override the default.  */
>     if (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
> *************** insert_part_to_rtx_on_edge (edge e, rtx
> *** 320,326 ****
>     set_location_for_edge (e);
>     /* If a locus is provided, override the default.  */
>     if (locus)
> !     set_curr_insn_source_location (locus);
>
>     var = partition_to_var (SA.map, src);
>     seq = emit_partition_copy (dest,
> --- 318,324 ----
>     set_location_for_edge (e);
>     /* If a locus is provided, override the default.  */
>     if (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 189835)
> --- gcc/basic-block.h   (working copy)
> *************** struct GTY(()) edge_def {
> *** 47,54 ****
>     /* Auxiliary info specific to a pass.  */
>     PTR GTY ((skip (""))) aux;
>
> !   /* Location of any goto implicit in the edge and associated BLOCK.  */
> !   tree goto_block;
>     location_t goto_locus;
>
>     /* The index number corresponding to this edge in the edge vector
> --- 47,53 ----
>     /* Auxiliary info specific to a pass.  */
>     PTR GTY ((skip (""))) aux;
>
> !   /* 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 189835)
> --- gcc/gimple.h        (working copy)
> *************** struct GTY(()) gimple_statement_base {
> *** 210,219 ****
>        and the prev pointer being the last.  */
>     gimple next;
>     gimple GTY((skip)) prev;
> -
> -   /* [ WORD 6 ]
> -      Lexical block holding this statement.  */
> -   tree block;
>   };
>
>
> --- 210,215 ----
> *************** gimple_bb (const_gimple g)
> *** 1198,1204 ****
>   static inline tree
>   gimple_block (const_gimple g)
>   {
> !   return g->gsbase.block;
>   }
>
>
> --- 1194,1200 ----
>   static inline tree
>   gimple_block (const_gimple g)
>   {
> !   return LOCATION_BLOCK (g->gsbase.location);
>   }
>
>
> *************** gimple_block (const_gimple g)
> *** 1207,1213 ****
>   static inline void
>   gimple_set_block (gimple g, tree block)
>   {
> !   g->gsbase.block = block;
>   }
>
>
> --- 1203,1209 ----
>   static inline void
>   gimple_set_block (gimple g, tree block)
>   {
> !   g->gsbase.location = COMBINE_LOCATION (g->gsbase.location, block);
>   }
>
>
> *************** gimple_set_location (gimple g, location_
> *** 1242,1248 ****
>   static inline bool
>   gimple_has_location (const_gimple g)
>   {
> !   return gimple_location (g) != UNKNOWN_LOCATION;
>   }
>
>
> --- 1238,1244 ----
>   static inline bool
>   gimple_has_location (const_gimple g)
>   {
> !   return !IS_UNKNOWN_LOCATION (gimple_location (g));
>   }
>
>
> Index: gcc/tree-cfg.c
> ===================================================================
> *** gcc/tree-cfg.c      (revision 189835)
> --- gcc/tree-cfg.c      (working copy)
> *************** make_cond_expr_edges (basic_block bb)
> *** 808,822 ****
>     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.  */
> --- 808,818 ----
> *************** make_goto_expr_edges (basic_block bb)
> *** 1026,1033 ****
>         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;
>       }
> --- 1022,1027 ----
> *************** gimple_can_merge_blocks_p (basic_block a
> *** 1501,1507 ****
>
>     /* When not optimizing, don't merge if we'd lose goto_locus.  */
>     if (!optimize
> !       && single_succ_edge (a)->goto_locus != UNKNOWN_LOCATION)
>       {
>         location_t goto_locus = single_succ_edge (a)->goto_locus;
>         gimple_stmt_iterator prev, next;
> --- 1495,1501 ----
>
>     /* When not optimizing, don't merge if we'd lose goto_locus.  */
>     if (!optimize
> !       && single_succ_edge (a)->goto_locus)
>       {
>         location_t goto_locus = single_succ_edge (a)->goto_locus;
>         gimple_stmt_iterator prev, next;
> *************** move_stmt_op (tree *tp, int *walk_subtre
> *** 5987,5995 ****
>     tree t = *tp;
>
>     if (EXPR_P (t))
> !     /* We should never have TREE_BLOCK set on non-statements.  */
> !     gcc_assert (!TREE_BLOCK (t));
> !
>     else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
>       {
>         if (TREE_CODE (t) == SSA_NAME)
> --- 5981,5987 ----
>     tree t = *tp;
>
>     if (EXPR_P (t))
> !     ;
>     else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
>       {
>         if (TREE_CODE (t) == SSA_NAME)
> *************** move_block_to_fn (struct function *dest_
> *** 6294,6305 ****
>       }
>
>     FOR_EACH_EDGE (e, ei, bb->succs)
> !     if (e->goto_locus)
>         {
> !       tree block = e->goto_block;
>         if (d->orig_block == NULL_TREE
>             || block == d->orig_block)
> !         e->goto_block = d->new_block;
>   #ifdef ENABLE_CHECKING
>         else if (block != d->new_block)
>           {
> --- 6286,6297 ----
>       }
>
>     FOR_EACH_EDGE (e, ei, bb->succs)
> !     if (!IS_UNKNOWN_LOCATION (e->goto_locus))
>         {
> !       tree block = LOCATION_BLOCK (e->goto_locus);
>         if (d->orig_block == NULL_TREE
>             || block == d->orig_block)
> !         e->goto_locus = COMBINE_LOCATION (e->goto_locus, d->new_block);
>   #ifdef ENABLE_CHECKING
>         else if (block != d->new_block)
>           {
> Index: gcc/config/alpha/alpha.c
> ===================================================================
> *** gcc/config/alpha/alpha.c    (revision 189835)
> --- gcc/config/alpha/alpha.c    (working copy)
> *************** alpha_output_mi_thunk_osf (FILE *file, t
> *** 8352,8358 ****
>        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);
> --- 8352,8357 ----
> Index: gcc/config/sparc/sparc.c
> ===================================================================
> *** gcc/config/sparc/sparc.c    (revision 189835)
> --- gcc/config/sparc/sparc.c    (working copy)
> *************** sparc_output_mi_thunk (FILE *file, tree
> *** 10654,10660 ****
>        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);
> --- 10654,10659 ----
> Index: gcc/config/i386/i386.c
> ===================================================================
> *** gcc/config/i386/i386.c      (revision 189835)
> --- gcc/config/i386/i386.c      (working copy)
> *************** x86_output_mi_thunk (FILE *file,
> *** 33063,33069 ****
>     /* 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);
> --- 33063,33068 ----
> Index: gcc/config/tilegx/tilegx.c
> ===================================================================
> *** gcc/config/tilegx/tilegx.c  (revision 189835)
> --- gcc/config/tilegx/tilegx.c  (working copy)
> *************** tilegx_output_mi_thunk (FILE *file, tree
> *** 4804,4810 ****
>        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);
> --- 4804,4809 ----
> Index: gcc/config/sh/sh.c
> ===================================================================
> *** gcc/config/sh/sh.c  (revision 189835)
> --- gcc/config/sh/sh.c  (working copy)
> *************** sh_output_mi_thunk (FILE *file, tree thu
> *** 11979,11985 ****
>        the insns emitted.  Note that use_thunk calls
>        assemble_start_function and assemble_end_function.  */
>
> -   insn_locators_alloc ();
>     insns = get_insns ();
>
>     if (optimize > 0)
> --- 11979,11984 ----
> Index: gcc/config/ia64/ia64.c
> ===================================================================
> *** gcc/config/ia64/ia64.c      (revision 189835)
> --- gcc/config/ia64/ia64.c      (working copy)
> *************** ia64_output_mi_thunk (FILE *file, tree t
> *** 10848,10854 ****
>        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);
> --- 10848,10853 ----
> Index: gcc/config/rs6000/rs6000.c
> ===================================================================
> *** gcc/config/rs6000/rs6000.c  (revision 189835)
> --- gcc/config/rs6000/rs6000.c  (working copy)
> *************** rs6000_output_mi_thunk (FILE *file, tree
> *** 21664,21670 ****
>        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);
> --- 21664,21669 ----
> Index: gcc/config/score/score.c
> ===================================================================
> *** gcc/config/score/score.c    (revision 189835)
> --- gcc/config/score/score.c    (working copy)
> *************** score_output_mi_thunk (FILE *file, tree
> *** 505,511 ****
>     /* 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);
> --- 505,510 ----
> Index: gcc/config/tilepro/tilepro.c
> ===================================================================
> *** gcc/config/tilepro/tilepro.c        (revision 189835)
> --- gcc/config/tilepro/tilepro.c        (working copy)
> *************** tilepro_asm_output_mi_thunk (FILE *file,
> *** 4407,4413 ****
>        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);
> --- 4407,4412 ----
> Index: gcc/config/mips/mips.c
> ===================================================================
> *** gcc/config/mips/mips.c      (revision 189835)
> --- gcc/config/mips/mips.c      (working copy)
> *************** mips_output_mi_thunk (FILE *file, tree t
> *** 15637,15643 ****
>     /* 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 ();
>     shorten_branches (insn);
> --- 15637,15642 ----
> Index: gcc/cfgrtl.c
> ===================================================================
> *** gcc/cfgrtl.c        (revision 189835)
> --- gcc/cfgrtl.c        (working copy)
> *************** rtl_split_block (basic_block bb, void *i
> *** 720,738 ****
>   static bool
>   unique_locus_on_edge_between_p (basic_block a, basic_block b)
>   {
> !   const int goto_locus = EDGE_SUCC (a, 0)->goto_locus;
>     rtx insn, end;
>
> !   if (!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))
>       insn = PREV_INSN (insn);
>
> !   if (insn != end && locator_eq (INSN_LOCATOR (insn), goto_locus))
>       return false;
>
>     /* Then scan block B forward.  */
> --- 720,738 ----
>   static bool
>   unique_locus_on_edge_between_p (basic_block a, basic_block b)
>   {
> !   const location_t goto_locus = EDGE_SUCC (a, 0)->goto_locus;
>     rtx insn, end;
>
> !   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_HAS_LOCATION (insn)))
>       insn = PREV_INSN (insn);
>
> !   if (insn != end && INSN_LOCATION (insn) == goto_locus)
>       return false;
>
>     /* Then scan block B forward.  */
> *************** unique_locus_on_edge_between_p (basic_bl
> *** 743,750 ****
>         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))
>         return false;
>       }
>
> --- 743,750 ----
>         while (insn != end && !NONDEBUG_INSN_P (insn))
>         insn = NEXT_INSN (insn);
>
> !       if (insn != end && INSN_HAS_LOCATION (insn)
> !         && INSN_LOCATION (insn) == goto_locus)
>         return false;
>       }
>
> *************** emit_nop_for_unique_locus_between (basic
> *** 761,767 ****
>       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;
>   }
>
>   /* Blocks A and B are to be merged into a single block A.  The insns
> --- 761,767 ----
>       return;
>
>     BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
> !   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
> *************** force_nonfallthru_and_redirect (edge e,
> *** 1478,1484 ****
>     else
>       jump_block = e->src;
>
> !   if (e->goto_locus && e->goto_block == NULL)
>       loc = e->goto_locus;
>     else
>       loc = 0;
> --- 1478,1484 ----
>     else
>       jump_block = e->src;
>
> !   if (!IS_UNKNOWN_LOCATION (e->goto_locus))
>       loc = e->goto_locus;
>     else
>       loc = 0;
> *************** fixup_reorder_chain (void)
> *** 3337,3343 ****
>           edge_iterator ei;
>
>           FOR_EACH_EDGE (e, ei, bb->succs)
> !         if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
>             {
>               edge e2;
>               edge_iterator ei2;
> --- 3337,3344 ----
>           edge_iterator ei;
>
>           FOR_EACH_EDGE (e, ei, bb->succs)
> !         if (!IS_UNKNOWN_LOCATION (e->goto_locus)
> !             && !(e->flags & EDGE_ABNORMAL))
>             {
>               edge e2;
>               edge_iterator ei2;
> *************** fixup_reorder_chain (void)
> *** 3347,3361 ****
>               insn = BB_END (e->src);
>               end = PREV_INSN (BB_HEAD (e->src));
>               while (insn != end
> !                    && (!NONDEBUG_INSN_P (insn) || INSN_LOCATOR (insn) == 0))
>                 insn = PREV_INSN (insn);
>               if (insn != end
> !                 && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
>                 continue;
>               if (simplejump_p (BB_END (e->src))
> !                 && INSN_LOCATOR (BB_END (e->src)) == 0)
>                 {
> !                 INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
>                   continue;
>                 }
>               dest = e->dest;
> --- 3348,3362 ----
>               insn = BB_END (e->src);
>               end = PREV_INSN (BB_HEAD (e->src));
>               while (insn != end
> !                    && (!NONDEBUG_INSN_P (insn) || !INSN_HAS_LOCATION (insn)))
>                 insn = PREV_INSN (insn);
>               if (insn != end
> !                 && INSN_LOCATION (insn) == e->goto_locus)
>                 continue;
>               if (simplejump_p (BB_END (e->src))
> !                 && !INSN_HAS_LOCATION (BB_END (e->src)))
>                 {
> !                 INSN_LOCATION (BB_END (e->src)) = e->goto_locus;
>                   continue;
>                 }
>               dest = e->dest;
> *************** fixup_reorder_chain (void)
> *** 3371,3394 ****
>                   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))
>                     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;
>
>               /* 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
>                     && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
> !                   && locator_eq (e->goto_locus, e2->goto_locus))
>                   redirect_edge_and_branch (e2, nb);
>                 else
>                   ei_next (&ei2);
> --- 3372,3395 ----
>                   end = NEXT_INSN (BB_END (dest));
>                   while (insn != end && !NONDEBUG_INSN_P (insn))
>                     insn = NEXT_INSN (insn);
> !                 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_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 (!IS_UNKNOWN_LOCATION (e2->goto_locus)
>                     && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
> !                   && e->goto_locus == e2->goto_locus)
>                   redirect_edge_and_branch (e2, nb);
>                 else
>                   ei_next (&ei2);
> *************** cfg_layout_merge_blocks (basic_block a,
> *** 4088,4094 ****
>       }
>
>     /* If B was a forwarder block, propagate the locus on the edge.  */
> !   if (forwarder_p && !EDGE_SUCC (b, 0)->goto_locus)
>       EDGE_SUCC (b, 0)->goto_locus = EDGE_SUCC (a, 0)->goto_locus;
>
>     if (dump_file)
> --- 4089,4095 ----
>       }
>
>     /* If B was a forwarder block, propagate the locus on the edge.  */
> !   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 189835)
> --- gcc/stmt.c  (working copy)
> *************** emit_case_nodes (rtx index, case_node_pt
> *** 2397,2403 ****
>                  then emit the code for one side at a time.  */
>
>               tree test_label
> !               = build_decl (CURR_INSN_LOCATION,
>                               LABEL_DECL, NULL_TREE, NULL_TREE);
>
>               /* See if the value is on the right.  */
> --- 2397,2403 ----
>                  then emit the code for one side at a time.  */
>
>               tree test_label
> !               = build_decl (curr_insn_location (),
>                               LABEL_DECL, NULL_TREE, NULL_TREE);
>
>               /* See if the value is on the right.  */
> *************** emit_case_nodes (rtx index, case_node_pt
> *** 2521,2527 ****
>               /* Right hand node requires testing.
>                  Branch to a label where we will handle it later.  */
>
> !             test_label = build_decl (CURR_INSN_LOCATION,
>                                        LABEL_DECL, NULL_TREE, NULL_TREE);
>               emit_cmp_and_jump_insns (index,
>                                        convert_modes
> --- 2521,2527 ----
>               /* Right hand node requires testing.
>                  Branch to a label where we will handle it later.  */
>
> !             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 189835)
> --- libcpp/include/line-map.h   (working copy)
> *************** struct GTY(()) line_map_ordinary {
> *** 89,95 ****
>
>   /* This is the highest possible source location encoded within an
>      ordinary or macro map.  */
> ! #define MAX_SOURCE_LOCATION 0xFFFFFFFF
>
>   struct cpp_hashnode;
>
> --- 89,95 ----
>
>   /* This is the highest possible source location encoded within an
>      ordinary or macro map.  */
> ! #define MAX_SOURCE_LOCATION 0x7FFFFFFF
>
>   struct cpp_hashnode;
>
> *************** struct GTY(()) line_maps {
> *** 408,413 ****
> --- 408,423 ----
>   #define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
>     LINEMAPS_LAST_ALLOCATED_MAP (SET, true)
>
> + extern void location_block_init (void);
> + extern void location_block_fini (void);
> + extern source_location get_combine_location (source_location, void *);
> + extern void *get_block_from_location (source_location);
> + extern source_location get_locus_from_location (source_location);
> +
> + #define COMBINE_LOCATION(LOC, BLOCK) \
> +   ((BLOCK) ? get_combine_location ((LOC), (BLOCK)) : (LOC))
> + #define IS_COMBINED_LOCATION(LOC) (((LOC) & MAX_SOURCE_LOCATION) != (LOC))
> +
>   /* Initialize a line map set.  */
>   extern void linemap_init (struct line_maps *);
>
> *************** typedef struct
> *** 594,599 ****
> --- 604,611 ----
>
>     int column;
>
> +   void *block;
> +
>     /* In a system header?. */
>     bool sysp;
>   } expanded_location;
> Index: libcpp/line-map.c
> ===================================================================
> *** libcpp/line-map.c   (revision 189835)
> --- libcpp/line-map.c   (working copy)
> *************** along with this program; see the file CO
> *** 25,30 ****
> --- 25,31 ----
>   #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 *,
> *************** static source_location linemap_macro_loc
> *** 50,55 ****
> --- 51,171 ----
>   extern unsigned num_expanded_macros_counter;
>   extern unsigned num_macro_tokens_counter;
>
> + struct location_block {
> +   source_location locus;
> +   void *block;
> + };
> +
> + static htab_t location_block_htab;
> + static source_location curr_combined_location;
> + static struct location_block *location_blocks;
> + static unsigned int allocated_location_blocks;
> +
> + /* Hash function for location_block hashtable.  */
> +
> + static hashval_t
> + location_block_hash (const void *l)
> + {
> +   const struct location_block *lb = (const struct location_block *) l;
> +   return (hashval_t) lb->locus + (size_t) &lb->block;
> + }
> +
> + /* Compare function for location_block hashtable.  */
> +
> + static int
> + location_block_eq (const void *l1, const void *l2)
> + {
> +   const struct location_block *lb1 = (const struct location_block *) l1;
> +   const struct location_block *lb2 = (const struct location_block *) l2;
> +   return lb1->locus == lb2->locus && lb1->block == lb2->block;
> + }
> +
> + /* Update the hashtable when location_blocks is reallocated.  */
> +
> + static int
> + location_block_update (void **slot, void *data)
> + {
> +   *((char **) slot) += ((char *) location_blocks - (char *) data);
> +   return 1;
> + }
> +
> + /* Combine LOCUS and BLOCK to a combined location.  */
> +
> + source_location
> + get_combine_location (source_location locus, void *block)
> + {
> +   struct location_block lb;
> +   struct location_block **slot;
> +
> +   linemap_assert (block);
> +
> +   if (IS_COMBINED_LOCATION (locus))
> +     locus = location_blocks[locus & MAX_SOURCE_LOCATION].locus;
> +   if (locus == 0 && block == NULL)
> +     return 0;
> +   lb.locus = locus;
> +   lb.block = block;
> +   slot = (struct location_block **)
> +       htab_find_slot (location_block_htab, &lb, INSERT);
> +   if (*slot == NULL)
> +     {
> +       *slot = location_blocks + curr_combined_location;
> +       location_blocks[curr_combined_location] = lb;
> +       if (++curr_combined_location >= allocated_location_blocks)
> +       {
> +         char *orig_location_blocks = (char *) location_blocks;
> +         allocated_location_blocks *= 2;
> +         location_blocks = XRESIZEVEC (struct location_block,
> +                                       location_blocks,
> +                                       allocated_location_blocks);
> +         htab_traverse (location_block_htab, location_block_update,
> +                        orig_location_blocks);
> +       }
> +     }
> +   return ((*slot) - location_blocks) | 0x80000000;
> + }
> +
> + /* Return the block for LOCATION.  */
> +
> + void *
> + get_block_from_location (source_location location)
> + {
> +   linemap_assert (IS_COMBINED_LOCATION (location));
> +   return location_blocks[location & MAX_SOURCE_LOCATION].block;
> + }
> +
> + /* Return the locus for LOCATION.  */
> +
> + source_location
> + get_locus_from_location (source_location location)
> + {
> +   linemap_assert (IS_COMBINED_LOCATION (location));
> +   return location_blocks[location & MAX_SOURCE_LOCATION].locus;
> + }
> +
> + /* Initialize the location_block structure.  */
> +
> + void
> + location_block_init (void)
> + {
> +   location_block_htab = htab_create (100, location_block_hash,
> +                                    location_block_eq, NULL);
> +   curr_combined_location = 0;
> +   allocated_location_blocks = 100;
> +   location_blocks = XNEWVEC (struct location_block,
> +                            allocated_location_blocks);
> + }
> +
> + /* Finalize the location_block structure.  */
> +
> + void
> + location_block_fini (void)
> + {
> +   allocated_location_blocks = 0;
> +   XDELETEVEC (location_blocks);
> +   htab_delete (location_block_htab);
> + }
> +
>   /* Initialize a line map set.  */
>
>   void
> *************** linemap_position_for_line_and_column (st
> *** 509,514 ****
> --- 625,632 ----
>   const struct line_map*
>   linemap_lookup (struct line_maps *set, source_location line)
>   {
> +   if (IS_COMBINED_LOCATION (line))
> +     line = location_blocks[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);
> *************** linemap_ordinary_map_lookup (struct line
> *** 525,530 ****
> --- 643,651 ----
>     unsigned int md, mn, mx;
>     const struct line_map *cached, *result;
>
> +   if (IS_COMBINED_LOCATION (line))
> +     line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
> +
>     if (set ==  NULL || line < RESERVED_LOCATION_COUNT)
>       return NULL;
>
> *************** linemap_macro_map_lookup (struct line_ma
> *** 570,575 ****
> --- 691,699 ----
>     unsigned int md, mn, mx;
>     const struct line_map *cached, *result;
>
> +   if (IS_COMBINED_LOCATION (line))
> +     line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
> +
>     linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
>
>     if (set ==  NULL)
> *************** linemap_macro_map_loc_to_def_point (cons
> *** 648,653 ****
> --- 772,780 ----
>   {
>     unsigned token_no;
>
> +   if (IS_COMBINED_LOCATION (location))
> +     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>     linemap_assert (linemap_macro_expansion_map_p (map)
>                   && location >= MAP_START_LOCATION (map));
>     linemap_assert (location >= RESERVED_LOCATION_COUNT);
> *************** linemap_macro_map_loc_unwind_toward_spel
> *** 672,677 ****
> --- 799,807 ----
>   {
>     unsigned token_no;
>
> +   if (IS_COMBINED_LOCATION (location))
> +     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>     linemap_assert (linemap_macro_expansion_map_p (map)
>                   && location >= MAP_START_LOCATION (map));
>     linemap_assert (location >= RESERVED_LOCATION_COUNT);
> *************** linemap_get_expansion_line (struct line_
> *** 696,701 ****
> --- 826,834 ----
>   {
>     const struct line_map *map = NULL;
>
> +   if (IS_COMBINED_LOCATION (location))
> +     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>     if (location < RESERVED_LOCATION_COUNT)
>       return 0;
>
> *************** linemap_get_expansion_filename (struct l
> *** 720,725 ****
> --- 853,861 ----
>   {
>     const struct line_map *map = NULL;
>
> +   if (IS_COMBINED_LOCATION (location))
> +     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>     if (location < RESERVED_LOCATION_COUNT)
>       return NULL;
>
> *************** linemap_location_in_system_header_p (str
> *** 754,759 ****
> --- 890,898 ----
>   {
>     const struct line_map *map = NULL;
>
> +   if (IS_COMBINED_LOCATION (location))
> +     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>     if (location < RESERVED_LOCATION_COUNT)
>       return false;
>
> *************** bool
> *** 793,798 ****
> --- 932,940 ----
>   linemap_location_from_macro_expansion_p (struct line_maps *set,
>                                          source_location location)
>   {
> +   if (IS_COMBINED_LOCATION (location))
> +     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>     linemap_assert (location <= MAX_SOURCE_LOCATION
>                   && (set->highest_location
>                       < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
> *************** linemap_macro_loc_to_spelling_point (str
> *** 933,938 ****
> --- 1075,1083 ----
>   {
>     struct line_map *map;
>
> +   if (IS_COMBINED_LOCATION (location))
> +     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>     linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
>
>     while (true)
> *************** linemap_macro_loc_to_def_point (struct l
> *** 967,972 ****
> --- 1112,1120 ----
>   {
>     struct line_map *map;
>
> +   if (IS_COMBINED_LOCATION (location))
> +     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>     linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
>
>     while (true)
> *************** linemap_macro_loc_to_exp_point (struct l
> *** 1005,1010 ****
> --- 1153,1161 ----
>   {
>     struct line_map *map;
>
> +   if (IS_COMBINED_LOCATION (location))
> +     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
> +
>     linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
>
>     while (true)
> *************** linemap_resolve_location (struct line_ma
> *** 1074,1079 ****
> --- 1225,1233 ----
>                           enum location_resolution_kind lrk,
>                           const struct line_map **map)
>   {
> +   if (IS_COMBINED_LOCATION (loc))
> +     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
> +
>     if (loc < RESERVED_LOCATION_COUNT)
>       {
>         /* A reserved location wasn't encoded in a map.  Let's return a
> *************** linemap_unwind_toward_expansion (struct
> *** 1121,1126 ****
> --- 1275,1283 ----
>     source_location resolved_location;
>     const struct line_map *resolved_map;
>
> +   if (IS_COMBINED_LOCATION (loc))
> +     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
> +
>     resolved_location =
>       linemap_macro_map_loc_unwind_toward_spelling (*map, loc);
>     resolved_map = linemap_lookup (set, resolved_location);
> *************** linemap_unwind_to_first_non_reserved_loc
> *** 1157,1162 ****
> --- 1314,1322 ----
>     source_location resolved_loc;
>     const struct line_map *map0 = NULL, *map1 = NULL;
>
> +   if (IS_COMBINED_LOCATION (loc))
> +     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
> +
>     map0 = linemap_lookup (set, loc);
>     if (!linemap_macro_expansion_map_p (map0))
>       return loc;
> *************** linemap_expand_location (struct line_map
> *** 1198,1203 ****
> --- 1358,1368 ----
>     expanded_location xloc;
>
>     memset (&xloc, 0, sizeof (xloc));
> +   if (IS_COMBINED_LOCATION (loc))
> +     {
> +       loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
> +       xloc.block = location_blocks[loc & MAX_SOURCE_LOCATION].block;
> +     }
>
>     if (loc < RESERVED_LOCATION_COUNT)
>       /* The location for this token wasn't generated from a line map.
> *************** linemap_dump_location (struct line_maps
> *** 1290,1295 ****
> --- 1455,1463 ----
>     const char *path = "", *from = "";
>     int l = -1, c = -1, s = -1, e = -1;
>
> +   if (IS_COMBINED_LOCATION (loc))
> +     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
> +
>     if (loc == 0)
>       return;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-07 15:16         ` Richard Guenther
@ 2012-08-07 15:52           ` Dehao Chen
  2012-08-13 18:35             ` Dodji Seketeli
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-08-07 15:52 UTC (permalink / raw)
  To: Richard Guenther
  Cc: gcc-patches, Dodji Seketeli, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey

Reattaching the ChangeLog with the patch.

Bootstrapped and passed regression tests on x86_64

gcc/ChangeLog:

2012-08-01  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.
	* dewarf2out.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 (): 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-08-01  Dehao Chen  <dehao@google.com>

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

libcpp/ChangeLog

2012-08-01  Dehao Chen  <dehao@google.com>

	* include/line-map.h (MAX_SOURCE_LOCATION): New value.
	(location_block_init): New.
	(location_block_fini): New.
	(get_combine_location): New.
	(get_block_from_location): New.
	(get_locus_from_location): New.
	(COMBINE_LOCATION): New.
	(IS_COMBINED_LOCATION): New.
	(expanded_location): New field.
	* line-map.c (location_block): New.
	(location_block_htab): New.
	(curr_combined_location): New.
	(location_blocks): New.
	(allocated_location_blocks): New.
	(location_block_hash): New.
	(location_block_eq): New.
	(location_block_update): New.
	(get_combine_location): New.
	(get_block_from_location): New.
	(get_locus_from_location): New.
	(location_block_init): New.
	(location_block_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 189835)
--- gcc/gimple-streamer-out.c	(working copy)
*************** output_gimple_stmt (struct output_block
*** 74,80 ****
    streamer_write_bitpack (&bp);

    /* Emit location information for the statement.  */
!   lto_output_location (ob, gimple_location (stmt));

    /* Emit the lexical block holding STMT.  */
    stream_write_tree (ob, gimple_block (stmt), true);
--- 74,80 ----
    streamer_write_bitpack (&bp);

    /* Emit location information for the statement.  */
!   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 189835)
--- gcc/tree.c	(working copy)
*************** build1_stat (enum tree_code code, tree t
*** 3765,3771 ****
    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);
--- 3765,3770 ----
*************** walk_tree_without_duplicates_1 (tree *tp
*** 10867,10883 ****
  }


! tree *
  tree_block (tree t)
  {
    char const c = TREE_CODE_CLASS (TREE_CODE (t));

    if (IS_EXPR_CODE_CLASS (c))
!     return &t->exp.block;
    gcc_unreachable ();
    return NULL;
  }

  /* 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.  */
--- 10866,10893 ----
  }


! tree
  tree_block (tree t)
  {
    char const c = TREE_CODE_CLASS (TREE_CODE (t));

    if (IS_EXPR_CODE_CLASS (c))
!     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 (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 189835)
--- gcc/tree.h	(working copy)
*************** extern void omp_clause_range_check_faile
*** 999,1005 ****

  #endif

! #define TREE_BLOCK(NODE)		*(tree_block (NODE))

  #include "tree-check.h"

--- 999,1006 ----

  #endif

! #define TREE_BLOCK(NODE)		(tree_block (NODE))
! #define TREE_SET_BLOCK(T, B)		(tree_set_block ((T), (B)))

  #include "tree-check.h"

*************** struct GTY(()) tree_constructor {
*** 1702,1708 ****
  #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)
  /* 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)
--- 1703,1709 ----
  #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) (!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)
*************** extern void protected_set_expr_location
*** 1881,1887 ****
  					      OMP_CLAUSE_PRIVATE,	\
  	                                      OMP_CLAUSE_COPYPRIVATE), 0)
  #define OMP_CLAUSE_HAS_LOCATION(NODE) \
!   ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus != UNKNOWN_LOCATION)
  #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,1888 ----
  					      OMP_CLAUSE_PRIVATE,	\
  	                                      OMP_CLAUSE_COPYPRIVATE), 0)
  #define OMP_CLAUSE_HAS_LOCATION(NODE) \
!   (!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.
*************** enum omp_clause_default_kind
*** 1972,1978 ****
  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];
--- 1973,1978 ----
*************** function_args_iter_next (function_args_i
*** 5164,5170 ****
  static inline bool
  inlined_function_outer_scope_p (const_tree block)
  {
!  return BLOCK_SOURCE_LOCATION (block) != UNKNOWN_LOCATION;
  }

  /* Loop over all function arguments of FNTYPE.  In each iteration, PTR is set
--- 5164,5170 ----
  static inline bool
  inlined_function_outer_scope_p (const_tree block)
  {
!  return !IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (block));
  }

  /* Loop over all function arguments of FNTYPE.  In each iteration, PTR is set
*************** extern bool subrange_type_for_debug_p (c
*** 5539,5545 ****
  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 location_t *block_nonartificial_location (tree);
  extern location_t tree_nonartificial_location (tree);

--- 5539,5546 ----
  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 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 189835)
--- gcc/final.c	(working copy)
*************** reemit_insn_block_notes (void)
*** 1605,1611 ****
  					     insn_scope (XVECEXP (body, 0, i)));
  	}
        if (! this_block)
! 	continue;

        if (this_block != cur_block)
  	{
--- 1605,1611 ----
  					     insn_scope (XVECEXP (body, 0, i)));
  	}
        if (! this_block)
! 	this_block = DECL_INITIAL (cfun->decl);

        if (this_block != cur_block)
  	{
*************** final_start_function (rtx first ATTRIBUT
*** 1640,1647 ****

    this_is_asm_operands = 0;

!   last_filename = locator_file (prologue_locator);
!   last_linenum = locator_line (prologue_locator);
    last_discriminator = discriminator = 0;

    high_block_linenum = high_function_linenum = last_linenum;
--- 1640,1647 ----

    this_is_asm_operands = 0;

!   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 189835)
--- gcc/input.c	(working copy)
*************** expand_location_1 (source_location loc,
*** 51,56 ****
--- 51,63 ----
    expanded_location xloc;
    const struct line_map *map;
    enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
+   tree block = NULL;
+
+   if (IS_COMBINED_LOCATION (loc))
+     {
+       block = LOCATION_BLOCK (loc);
+       loc = LOCATION_LOCUS (loc);
+     }

    memset (&xloc, 0, sizeof (xloc));

*************** expand_location_1 (source_location loc,
*** 74,79 ****
--- 81,87 ----
        xloc = linemap_expand_location (line_table, map, loc);
      }

+   xloc.block = block;
    if (loc <= BUILTINS_LOCATION)
      xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");

Index: gcc/input.h
===================================================================
*** gcc/input.h	(revision 189835)
--- gcc/input.h	(working copy)
*************** extern location_t input_location;
*** 51,56 ****
--- 51,64 ----
  #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_COMBINED_LOCATION(LOC)) ? get_locus_from_location (LOC) : (LOC))
+ #define LOCATION_BLOCK(LOC) \
+   ((tree) ((IS_COMBINED_LOCATION (LOC)) ? get_block_from_location (LOC) \
+   : NULL))
+ #define IS_UNKNOWN_LOCATION(LOC) \
+   ((IS_COMBINED_LOCATION (LOC)) ? get_locus_from_location (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 189835)
--- gcc/fold-const.c	(working copy)
*************** static location_t
*** 145,151 ****
  expr_location_or (tree t, location_t loc)
  {
    location_t tloc = EXPR_LOCATION (t);
!   return tloc != UNKNOWN_LOCATION ? tloc : loc;
  }

  /* Similar to protected_set_expr_location, but never modify x in place,
--- 145,151 ----
  expr_location_or (tree t, location_t loc)
  {
    location_t tloc = EXPR_LOCATION (t);
!   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 189835)
--- gcc/toplev.c	(working copy)
*************** general_init (const char *argv0)
*** 1140,1145 ****
--- 1140,1146 ----
    linemap_init (line_table);
    line_table->reallocator = realloc_for_line_map;
    line_table->round_alloc_size = ggc_round_alloc_size;
+   location_block_init ();
    init_ttree ();

    /* Initialize register usage now so switches may override.  */
*************** toplev_main (int argc, char **argv)
*** 1946,1951 ****
--- 1947,1953 ----
    invoke_plugin_callbacks (PLUGIN_FINISH, NULL);

    finalize_plugins ();
+   location_block_fini ();
    if (seen_error ())
      return (FATAL_EXIT_CODE);

Index: gcc/reorg.c
===================================================================
*** gcc/reorg.c	(revision 189835)
--- gcc/reorg.c	(working copy)
*************** emit_delay_sequence (rtx insn, rtx list,
*** 545,551 ****
    INSN_DELETED_P (delay_insn) = 0;
    PREV_INSN (delay_insn) = PREV_INSN (seq_insn);

!   INSN_LOCATOR (seq_insn) = INSN_LOCATOR (delay_insn);

    for (li = list; li; li = XEXP (li, 1), i++)
      {
--- 545,551 ----
    INSN_DELETED_P (delay_insn) = 0;
    PREV_INSN (delay_insn) = PREV_INSN (seq_insn);

!   INSN_LOCATION (seq_insn) = INSN_LOCATION (delay_insn);

    for (li = list; li; li = XEXP (li, 1), i++)
      {
*************** emit_delay_sequence (rtx insn, rtx list,
*** 561,569 ****

        /* 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;

        for (note = REG_NOTES (tem); note; note = next)
  	{
--- 561,569 ----

        /* SPARC assembler, for instance, emit warning when debug info is output
           into the delay slot.  */
!       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)
  	{
*************** dbr_schedule (rtx first)
*** 4087,4093 ****
      for (link = crtl->epilogue_delay_list;
           link;
           link = XEXP (link, 1))
!       INSN_LOCATOR (XEXP (link, 0)) = 0;
    }

  #endif
--- 4087,4093 ----
      for (link = crtl->epilogue_delay_list;
           link;
           link = XEXP (link, 1))
!       INSN_LOCATION (XEXP (link, 0)) = 0;
    }

  #endif
Index: gcc/modulo-sched.c
===================================================================
*** gcc/modulo-sched.c	(revision 189835)
--- gcc/modulo-sched.c	(working copy)
*************** loop_single_full_bb_p (struct loop *loop
*** 1246,1254 ****
  /* Dump file:line from INSN's location info to dump_file.  */

  static void
! dump_insn_locator (rtx insn)
  {
!   if (dump_file && INSN_LOCATOR (insn))
      {
        const char *file = insn_file (insn);
        if (file)
--- 1246,1254 ----
  /* Dump file:line from INSN's location info to dump_file.  */

  static void
! dump_insn_location (rtx insn)
  {
!   if (dump_file && INSN_LOCATION (insn))
      {
        const char *file = insn_file (insn);
        if (file)
*************** loop_canon_p (struct loop *loop)
*** 1282,1288 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many exits");
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
--- 1282,1288 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many exits");
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
*************** loop_canon_p (struct loop *loop)
*** 1295,1301 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many BBs.");
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
--- 1295,1301 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many BBs.");
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
*************** sms_schedule (void)
*** 1421,1427 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}

--- 1421,1427 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}

*************** sms_schedule (void)
*** 1450,1456 ****
  	{
  	  if (dump_file)
  	    {
! 	      dump_insn_locator (tail);
  	      fprintf (dump_file, "\nSMS single-bb-loop\n");
  	      if (profile_info && flag_branch_probabilities)
  	    	{
--- 1450,1456 ----
  	{
  	  if (dump_file)
  	    {
! 	      dump_insn_location (tail);
  	      fprintf (dump_file, "\nSMS single-bb-loop\n");
  	      if (profile_info && flag_branch_probabilities)
  	    	{
*************** sms_schedule (void)
*** 1556,1562 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");

  	  print_ddg (dump_file, g);
--- 1556,1562 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");

  	  print_ddg (dump_file, g);
*************** sms_schedule (void)
*** 1571,1577 ****

        if (dump_file)
  	{
! 	  dump_insn_locator (tail);
  	  fprintf (dump_file, "\nSMS single-bb-loop\n");
  	  if (profile_info && flag_branch_probabilities)
  	    {
--- 1571,1577 ----

        if (dump_file)
  	{
! 	  dump_insn_location (tail);
  	  fprintf (dump_file, "\nSMS single-bb-loop\n");
  	  if (profile_info && flag_branch_probabilities)
  	    {
*************** sms_schedule (void)
*** 1714,1720 ****

            if (dump_file)
              {
! 	      dump_insn_locator (tail);
  	      fprintf (dump_file, " SMS succeeded %d %d (with ii, sc)\n",
  		       ps->ii, stage_count);
  	      print_partial_schedule (ps, dump_file);
--- 1714,1720 ----

            if (dump_file)
              {
! 	      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 189835)
--- gcc/lto-streamer-out.c	(working copy)
*************** lto_output_location_bitpack (struct bitp
*** 155,160 ****
--- 155,161 ----
  {
    expanded_location xloc;

+   loc = LOCATION_LOCUS (loc);
    bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
    if (loc == UNKNOWN_LOCATION)
      return;
Index: gcc/jump.c
===================================================================
*** gcc/jump.c	(revision 189835)
--- gcc/jump.c	(working copy)
*************** rtx_renumbered_equal_p (const_rtx x, con
*** 1818,1825 ****
  	  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)))
  		break;
  	      return 0;
  	    }
--- 1818,1824 ----
  	  if (XINT (x, i) != XINT (y, i))
  	    {
  	      if (((code == ASM_OPERANDS && i == 6)
! 		   || (code == ASM_INPUT && i == 1)))
  		break;
  	      return 0;
  	    }
Index: gcc/ifcvt.c
===================================================================
*** gcc/ifcvt.c	(revision 189835)
--- gcc/ifcvt.c	(working copy)
*************** noce_try_move (struct noce_if_info *if_i
*** 1019,1025 ****
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	}
        return TRUE;
      }
--- 1019,1025 ----
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	}
        return TRUE;
      }
*************** noce_try_store_flag (struct noce_if_info
*** 1064,1070 ****
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
        return TRUE;
      }
    else
--- 1064,1070 ----
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
        return TRUE;
      }
    else
*************** noce_try_store_flag_constants (struct no
*** 1195,1201 ****
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
        return TRUE;
      }

--- 1195,1201 ----
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
        return TRUE;
      }

*************** noce_try_addcc (struct noce_if_info *if_
*** 1243,1249 ****
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATOR (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
--- 1243,1249 ----
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATION (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
*************** noce_try_addcc (struct noce_if_info *if_
*** 1283,1289 ****
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATOR (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
--- 1283,1289 ----
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATION (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
*************** noce_try_store_flag_mask (struct noce_if
*** 1332,1338 ****
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	  return TRUE;
  	}

--- 1332,1338 ----
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	  return TRUE;
  	}

*************** noce_try_cmove (struct noce_if_info *if_
*** 1481,1487 ****
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	  return TRUE;
  	}
        else
--- 1481,1487 ----
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	  return TRUE;
  	}
        else
*************** noce_try_cmove_arith (struct noce_if_inf
*** 1682,1688 ****
    if (!tmp)
      return FALSE;

!   emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    return TRUE;

   end_seq_and_fail:
--- 1682,1688 ----
    if (!tmp)
      return FALSE;

!   emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    return TRUE;

   end_seq_and_fail:
*************** noce_try_minmax (struct noce_if_info *if
*** 1929,1935 ****
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

--- 1929,1935 ----
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

*************** noce_try_abs (struct noce_if_info *if_in
*** 2076,2082 ****
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

--- 2076,2082 ----
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

*************** noce_try_sign_mask (struct noce_if_info
*** 2155,2161 ****
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    return TRUE;
  }

--- 2155,2161 ----
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    return TRUE;
  }

*************** noce_try_bitop (struct noce_if_info *if_
*** 2255,2261 ****
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
      }
    return TRUE;
  }
--- 2255,2261 ----
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
      }
    return TRUE;
  }
*************** noce_process_if_block (struct noce_if_in
*** 2656,2662 ****
        unshare_all_rtl_in_chain (seq);
        end_sequence ();

!       emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATOR (insn_a));
      }

    /* The original THEN and ELSE blocks may now be removed.  The test block
--- 2656,2662 ----
        unshare_all_rtl_in_chain (seq);
        end_sequence ();

!       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
*************** cond_move_process_if_block (struct noce_
*** 2937,2943 ****
        loc_insn = first_active_insn (else_bb);
        gcc_assert (loc_insn);
      }
!   emit_insn_before_setloc (seq, jump, INSN_LOCATOR (loc_insn));

    if (else_bb)
      {
--- 2937,2943 ----
        loc_insn = first_active_insn (else_bb);
        gcc_assert (loc_insn);
      }
!   emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));

    if (else_bb)
      {
*************** find_cond_trap (basic_block test_bb, edg
*** 3655,3661 ****
      return FALSE;

    /* Emit the new insns before cond_earliest.  */
!   emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATOR (trap));

    /* Delete the trap block if possible.  */
    remove_edge (trap_bb == then_bb ? then_edge : else_edge);
--- 3655,3661 ----
      return FALSE;

    /* Emit the new insns before cond_earliest.  */
!   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/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c	(revision 189835)
--- gcc/dwarf2out.c	(working copy)
*************** add_src_coords_attributes (dw_die_ref di
*** 15506,15512 ****
  {
    expanded_location s;

!   if (DECL_SOURCE_LOCATION (decl) == UNKNOWN_LOCATION)
      return;
    s = expand_location (DECL_SOURCE_LOCATION (decl));
    add_AT_file (die, DW_AT_decl_file, lookup_filename (s.file));
--- 15506,15512 ----
  {
    expanded_location s;

!   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 189835)
--- gcc/expr.c	(working copy)
*************** expand_expr_real (tree exp, rtx target,
*** 7802,7820 ****
    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 ();
        input_location = EXPR_LOCATION (exp);
!       set_curr_insn_source_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);
      }
    else
      {
--- 7802,7815 ----
    if (cfun && EXPR_HAS_LOCATION (exp))
      {
        location_t saved_location = input_location;
!       location_t saved_curr_loc = curr_insn_location ();
        input_location = EXPR_LOCATION (exp);
!       set_curr_insn_location (input_location);

        ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);

        input_location = saved_location;
!       set_curr_insn_location (saved_curr_loc);
      }
    else
      {
Index: gcc/predict.c
===================================================================
*** gcc/predict.c	(revision 189835)
--- gcc/predict.c	(working copy)
*************** tree_estimate_probability_driver (void)
*** 2177,2183 ****
  {
    unsigned nb_loops;

!   loop_optimizer_init (0);
    if (dump_file && (dump_flags & TDF_DETAILS))
      flow_loops_dump (dump_file, NULL, 0);

--- 2177,2183 ----
  {
    unsigned nb_loops;

!   loop_optimizer_init (LOOPS_NORMAL);
    if (dump_file && (dump_flags & TDF_DETAILS))
      flow_loops_dump (dump_file, NULL, 0);

Index: gcc/tree-parloops.c
===================================================================
*** gcc/tree-parloops.c	(revision 189835)
--- gcc/tree-parloops.c	(working copy)
*************** create_loop_fn (location_t loc)
*** 1415,1420 ****
--- 1415,1421 ----
    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 189835)
--- gcc/recog.c	(working copy)
*************** peep2_attempt (basic_block bb, rtx insn,
*** 3333,3339 ****
    /* 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));
    before_try = PREV_INSN (insn);
    delete_insn_chain (insn, peep2_insn_data[i].insn, false);

--- 3333,3339 ----
    /* Replace the old sequence with the new.  */
    last = emit_insn_after_setloc (attempt,
  				 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 189835)
--- gcc/function.c	(working copy)
*************** static bool contains (const_rtx, htab_t)
*** 133,139 ****
  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;
  \f
  /* Stack of nested functions.  */
  /* Keep track of the cfun stack.  */
--- 133,139 ----
  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_locations (rtx, int) ATTRIBUTE_UNUSED;
  \f
  /* Stack of nested functions.  */
  /* Keep track of the cfun stack.  */
*************** free_after_compilation (struct function
*** 200,206 ****
    f->cfg = NULL;

    regno_reg_rtx = NULL;
-   insn_locators_free ();
  }
  \f
  /* Return size needed for stack frame based on slots so far allocated.
--- 200,205 ----
*************** expand_function_end (void)
*** 4979,4985 ****
  	      probe_stack_range (STACK_OLD_CHECK_PROTECT, max_frame_size);
  	    seq = get_insns ();
  	    end_sequence ();
! 	    set_insn_locators (seq, prologue_locator);
  	    emit_insn_before (seq, stack_check_probe_note);
  	    break;
  	  }
--- 4978,4984 ----
  	      probe_stack_range (STACK_OLD_CHECK_PROTECT, max_frame_size);
  	    seq = get_insns ();
  	    end_sequence ();
! 	    set_insn_locations (seq, prologue_location);
  	    emit_insn_before (seq, stack_check_probe_note);
  	    break;
  	  }
*************** expand_function_end (void)
*** 4994,5000 ****

    /* Output a linenumber for the end of the function.
       SDB depends on this.  */
!   set_curr_insn_source_location (input_location);

    /* Before the return label (if any), clobber the return
       registers so that they are not propagated live to the rest of
--- 4993,4999 ----

    /* Output a linenumber for the end of the function.
       SDB depends on this.  */
!   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
*************** maybe_copy_prologue_epilogue_insn (rtx i
*** 5277,5290 ****
    *slot = copy;
  }

! /* Set the locator of the insn chain starting at INSN to LOC.  */
  static void
! set_insn_locators (rtx insn, int loc)
  {
    while (insn != NULL_RTX)
      {
        if (INSN_P (insn))
! 	INSN_LOCATOR (insn) = loc;
        insn = NEXT_INSN (insn);
      }
  }
--- 5276,5289 ----
    *slot = copy;
  }

! /* Set the location of the insn chain starting at INSN to LOC.  */
  static void
! set_insn_locations (rtx insn, int loc)
  {
    while (insn != NULL_RTX)
      {
        if (INSN_P (insn))
! 	INSN_LOCATION (insn) = loc;
        insn = NEXT_INSN (insn);
      }
  }
*************** thread_prologue_and_epilogue_insns (void
*** 5893,5899 ****
        end_sequence ();

        record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
!       set_insn_locators (split_prologue_seq, prologue_locator);
  #endif
      }

--- 5892,5898 ----
        end_sequence ();

        record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
!       set_insn_locations (split_prologue_seq, prologue_location);
  #endif
      }

*************** thread_prologue_and_epilogue_insns (void
*** 5922,5928 ****

        prologue_seq = get_insns ();
        end_sequence ();
!       set_insn_locators (prologue_seq, prologue_locator);
      }
  #endif

--- 5921,5927 ----

        prologue_seq = get_insns ();
        end_sequence ();
!       set_insn_locations (prologue_seq, prologue_location);
      }
  #endif

*************** thread_prologue_and_epilogue_insns (void
*** 6418,6424 ****

        /* Retain a map of the epilogue insns.  */
        record_insns (seq, NULL, &epilogue_insn_hash);
!       set_insn_locators (seq, epilogue_locator);

        seq = get_insns ();
        returnjump = get_last_insn ();
--- 6417,6423 ----

        /* Retain a map of the epilogue insns.  */
        record_insns (seq, NULL, &epilogue_insn_hash);
!       set_insn_locations (seq, epilogue_location);

        seq = get_insns ();
        returnjump = get_last_insn ();
*************** epilogue_done:
*** 6608,6614 ****
  	     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);

  	  emit_insn_before (seq, insn);
  	}
--- 6607,6613 ----
  	     avoid getting rid of sibcall epilogue insns.  Do this before we
  	     actually emit the sequence.  */
  	  record_insns (seq, NULL, &epilogue_insn_hash);
! 	  set_insn_locations (seq, epilogue_location);

  	  emit_insn_before (seq, insn);
  	}
Index: gcc/print-rtl.c
===================================================================
*** gcc/print-rtl.c	(revision 189835)
--- gcc/print-rtl.c	(working copy)
*************** print_rtx (const_rtx in_rtx)
*** 416,425 ****
  	if (i == 5 && INSN_P (in_rtx))
  	  {
  #ifndef GENERATOR_FILE
! 	    /*  Pretty-print insn locators.  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))
  	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
  #endif
  	  }
--- 416,425 ----
  	if (i == 5 && INSN_P (in_rtx))
  	  {
  #ifndef GENERATOR_FILE
! 	    /*  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_LOCATION (in_rtx) && insn_file (in_rtx))
  	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
  #endif
  	  }
*************** print_rtx (const_rtx in_rtx)
*** 427,442 ****
  	  {
  #ifndef GENERATOR_FILE
  	    fprintf (outfile, " %s:%i",
! 		     locator_file (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)),
! 		     locator_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)));
  #endif
  	  }
  	else if (i == 6 && NOTE_P (in_rtx))
--- 427,442 ----
  	  {
  #ifndef GENERATOR_FILE
  	    fprintf (outfile, " %s:%i",
! 		     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",
! 		     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 189835)
--- gcc/profile.c	(working copy)
*************** branch_prob (void)
*** 966,972 ****
  	     is not computed twice.  */
  	  if (last
  	      && gimple_has_location (last)
! 	      && e->goto_locus != UNKNOWN_LOCATION
  	      && !single_succ_p (bb)
  	      && (LOCATION_FILE (e->goto_locus)
  	          != LOCATION_FILE (gimple_location (last))
--- 966,972 ----
  	     is not computed twice.  */
  	  if (last
  	      && gimple_has_location (last)
! 	      && !IS_UNKNOWN_LOCATION (e->goto_locus)
  	      && !single_succ_p (bb)
  	      && (LOCATION_FILE (e->goto_locus)
  	          != LOCATION_FILE (gimple_location (last))
*************** branch_prob (void)
*** 976,982 ****
  	      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)
--- 976,981 ----
*************** branch_prob (void)
*** 1188,1194 ****

  	  /* Notice GOTO expressions eliminated while constructing the CFG.  */
  	  if (single_succ_p (bb)
! 	      && single_succ_edge (bb)->goto_locus != UNKNOWN_LOCATION)
  	    {
  	      expanded_location curr_location
  		= expand_location (single_succ_edge (bb)->goto_locus);
--- 1187,1193 ----

  	  /* Notice GOTO expressions eliminated while constructing the CFG.  */
  	  if (single_succ_p (bb)
! 	      && !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 189835)
--- gcc/trans-mem.c	(working copy)
*************** ipa_tm_scan_irr_block (basic_block bb)
*** 3796,3802 ****
  	    {
  	      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;
--- 3796,3801 ----
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c	(revision 189835)
--- gcc/gimplify.c	(working copy)
*************** gimplify_call_expr (tree *expr_p, gimple
*** 2600,2606 ****
  	    = 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;
--- 2600,2605 ----
Index: gcc/except.c
===================================================================
*** gcc/except.c	(revision 189835)
--- gcc/except.c	(working copy)
*************** duplicate_eh_regions_1 (struct duplicate
*** 526,532 ****
        break;

      case ERT_MUST_NOT_THROW:
!       new_r->u.must_not_throw = old_r->u.must_not_throw;
        break;
      }

--- 526,535 ----
        break;

      case ERT_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 189835)
--- gcc/emit-rtl.c	(working copy)
*************** try_split (rtx pat, rtx trial, int last)
*** 3634,3640 ****
  	}
      }

!   tem = emit_insn_after_setloc (seq, trial, INSN_LOCATOR (trial));

    delete_insn (trial);
    if (has_barrier)
--- 3634,3640 ----
  	}
      }

!   tem = emit_insn_after_setloc (seq, trial, INSN_LOCATION (trial));

    delete_insn (trial);
    if (has_barrier)
*************** make_insn_raw (rtx pattern)
*** 3670,3676 ****
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

  #ifdef ENABLE_RTL_CHECKING
--- 3670,3676 ----
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

  #ifdef ENABLE_RTL_CHECKING
*************** make_debug_insn_raw (rtx pattern)
*** 3703,3709 ****
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
--- 3703,3709 ----
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
*************** make_jump_insn_raw (rtx pattern)
*** 3723,3729 ****
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    JUMP_LABEL (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
--- 3723,3729 ----
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    JUMP_LABEL (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
*************** make_call_insn_raw (rtx pattern)
*** 3743,3749 ****
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    CALL_INSN_FUNCTION_USAGE (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
--- 3743,3749 ----
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    CALL_INSN_FUNCTION_USAGE (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
*************** emit_pattern_after_setloc (rtx pattern,
*** 4416,4423 ****
    after = NEXT_INSN (after);
    while (1)
      {
!       if (active_insn_p (after) && !INSN_LOCATOR (after))
! 	INSN_LOCATOR (after) = loc;
        if (after == last)
  	break;
        after = NEXT_INSN (after);
--- 4416,4423 ----
    after = NEXT_INSN (after);
    while (1)
      {
!       if (active_insn_p (after) && !INSN_LOCATION (after))
! 	INSN_LOCATION (after) = loc;
        if (after == last)
  	break;
        after = NEXT_INSN (after);
*************** emit_pattern_after (rtx pattern, rtx aft
*** 4440,4501 ****
        prev = PREV_INSN (prev);

    if (INSN_P (prev))
!     return emit_pattern_after_setloc (pattern, after, INSN_LOCATOR (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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  rtx
  emit_debug_insn_after (rtx pattern, rtx after)
  {
--- 4440,4501 ----
        prev = PREV_INSN (prev);

    if (INSN_P (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_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_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_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_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_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_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_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_LOCATION according
to AFTER.  */
  rtx
  emit_debug_insn_after (rtx pattern, rtx after)
  {
*************** emit_pattern_before_setloc (rtx pattern,
*** 4525,4532 ****
      first = NEXT_INSN (first);
    while (1)
      {
!       if (active_insn_p (first) && !INSN_LOCATOR (first))
! 	INSN_LOCATOR (first) = loc;
        if (first == last)
  	break;
        first = NEXT_INSN (first);
--- 4525,4532 ----
      first = NEXT_INSN (first);
    while (1)
      {
!       if (active_insn_p (first) && !INSN_LOCATION (first))
! 	INSN_LOCATION (first) = loc;
        if (first == last)
  	break;
        first = NEXT_INSN (first);
*************** emit_pattern_before (rtx pattern, rtx be
*** 4550,4556 ****
        next = PREV_INSN (next);

    if (INSN_P (next))
!     return emit_pattern_before_setloc (pattern, before, INSN_LOCATOR (next),
  				       insnp, make_raw);
    else
      return emit_pattern_before_noloc (pattern, before,
--- 4550,4556 ----
        next = PREV_INSN (next);

    if (INSN_P (next))
!     return emit_pattern_before_setloc (pattern, before, INSN_LOCATION (next),
  				       insnp, make_raw);
    else
      return emit_pattern_before_noloc (pattern, before,
*************** emit_pattern_before (rtx pattern, rtx be
*** 4558,4564 ****
                                        NULL, make_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4558,4564 ----
                                        NULL, make_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_insn_before_setloc (rtx pattern, rt
*** 4566,4579 ****
  				     make_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR 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.  */
  rtx
  emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4566,4579 ----
  				     make_insn_raw);
  }

! /* 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_LOCATION according to LOC.  */
  rtx
  emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_jump_insn_before_setloc (rtx patter
*** 4581,4587 ****
  				     make_jump_insn_raw);
  }

! /* Like emit_jump_insn_before_noloc, but set INSN_LOCATOR according
to BEFORE.  */
  rtx
  emit_jump_insn_before (rtx pattern, rtx before)
  {
--- 4581,4587 ----
  				     make_jump_insn_raw);
  }

! /* Like emit_jump_insn_before_noloc, but set INSN_LOCATION according
to BEFORE.  */
  rtx
  emit_jump_insn_before (rtx pattern, rtx before)
  {
*************** emit_jump_insn_before (rtx pattern, rtx
*** 4589,4595 ****
  			      make_jump_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4589,4595 ----
  			      make_jump_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_call_insn_before_setloc (rtx patter
*** 4598,4604 ****
  }

  /* Like emit_call_insn_before_noloc,
!    but set insn_locator according to BEFORE.  */
  rtx
  emit_call_insn_before (rtx pattern, rtx before)
  {
--- 4598,4604 ----
  }

  /* Like emit_call_insn_before_noloc,
!    but set insn_location according to BEFORE.  */
  rtx
  emit_call_insn_before (rtx pattern, rtx before)
  {
*************** emit_call_insn_before (rtx pattern, rtx
*** 4606,4612 ****
  			      make_call_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4606,4612 ----
  			      make_call_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_debug_insn_before_setloc (rtx patte
*** 4615,4621 ****
  }

  /* Like emit_debug_insn_before_noloc,
!    but set insn_locator according to BEFORE.  */
  rtx
  emit_debug_insn_before (rtx pattern, rtx before)
  {
--- 4615,4621 ----
  }

  /* Like emit_debug_insn_before_noloc,
!    but set insn_location according to BEFORE.  */
  rtx
  emit_debug_insn_before (rtx pattern, rtx before)
  {
*************** emit_copy_of_insn_after (rtx insn, rtx a
*** 5865,5871 ****
    /* Update LABEL_NUSES.  */
    mark_jump_label (PATTERN (new_rtx), new_rtx, 0);

!   INSN_LOCATOR (new_rtx) = INSN_LOCATOR (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,
--- 5865,5871 ----
    /* Update LABEL_NUSES.  */
    mark_jump_label (PATTERN (new_rtx), new_rtx, 0);

!   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,
*************** gen_hard_reg_clobber (enum machine_mode
*** 5900,6149 ****
  	    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_O(location_t);
! DEF_VEC_ALLOC_O(location_t,heap);
! static VEC(location_t,heap) *locations_locators_vals;
! int prologue_locator;
! int epilogue_locator;

  /* 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.  */
  void
! insn_locators_alloc (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);
!
    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)
! {
!   if (curr_rtl_loc >= 0)
!     epilogue_locator = curr_insn_locator ();
!   curr_rtl_loc = -1;
! }
!
! /* 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)
  {
-   /* 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)
  {
    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;
- }
- \f
-
- /* 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 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 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 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);
- }
- \f
-
  /* 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.  */
--- 5900,5965 ----
  	    gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
  }

! 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;

! /* Allocate insn location datastructure.  */
  void
! insn_locations_init (void)
  {
!   prologue_location = epilogue_location = 0;
    curr_location = UNKNOWN_LOCATION;
    last_location = UNKNOWN_LOCATION;
  }

  /* At the end of emit stage, clear current location.  */
  void
! insn_locations_finalize (void)
  {
!   epilogue_location = curr_location;
!   curr_location = UNKNOWN_LOCATION;
  }

  /* Set current location.  */
  void
! set_curr_insn_location (location_t location)
  {
    curr_location = location;
  }

  /* Get current location.  */
  location_t
! curr_insn_location (void)
  {
    return curr_location;
  }

  /* Return lexical scope block insn belongs to.  */
  tree
  insn_scope (const_rtx insn)
  {
!   return LOCATION_BLOCK (INSN_LOCATION (insn));
  }

  /* Return line number of the statement that produced this insn.  */
  int
  insn_line (const_rtx insn)
  {
!   return LOCATION_LINE (INSN_LOCATION (insn));
  }

  /* Return source file of the statement that produced this insn.  */
  const char *
  insn_file (const_rtx insn)
  {
!   return LOCATION_FILE (INSN_LOCATION (insn));
  }

  /* 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 189835)
--- gcc/cfgexpand.c	(working copy)
*************** gimple_assign_rhs_to_tree (gimple stmt)
*** 92,99 ****
  	   && gimple_location (stmt) != EXPR_LOCATION (t))
  	  || (gimple_block (stmt)
  	      && currently_expanding_to_rtl
! 	      && EXPR_P (t)
! 	      && gimple_block (stmt) != TREE_BLOCK (t)))
  	t = copy_node (t);
      }
    else
--- 92,98 ----
  	   && gimple_location (stmt) != EXPR_LOCATION (t))
  	  || (gimple_block (stmt)
  	      && currently_expanding_to_rtl
! 	      && EXPR_P (t)))
  	t = copy_node (t);
      }
    else
*************** gimple_assign_rhs_to_tree (gimple stmt)
*** 101,108 ****

    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;
  }
--- 100,105 ----
*************** expand_gimple_cond (basic_block bb, gimp
*** 1804,1811 ****
    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));

    /* These flags have no purpose in RTL land.  */
    true_edge->flags &= ~EDGE_TRUE_VALUE;
--- 1801,1807 ----
    last2 = last = get_last_insn ();

    extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
!   set_curr_insn_location (gimple_location (stmt));

    /* These flags have no purpose in RTL land.  */
    true_edge->flags &= ~EDGE_TRUE_VALUE;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1818,1830 ****
        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;
        false_edge->flags |= EDGE_FALLTHRU;
        maybe_cleanup_end_of_block (false_edge, last);
        return NULL;
--- 1814,1821 ----
        jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
  		true_edge->probability);
        maybe_dump_rtl_for_gimple_stmt (stmt, last);
!       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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1834,1846 ****
        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;
        true_edge->flags |= EDGE_FALLTHRU;
        maybe_cleanup_end_of_block (true_edge, last);
        return NULL;
--- 1825,1832 ----
        jumpifnot_1 (code, op0, op1, label_rtx_for_bb (false_edge->dest),
  		   false_edge->probability);
        maybe_dump_rtl_for_gimple_stmt (stmt, last);
!       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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1849,1861 ****
    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;
    emit_jump (label_rtx_for_bb (false_edge->dest));

    BB_END (bb) = last;
--- 1835,1842 ----
    jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
  	    true_edge->probability);
    last = get_last_insn ();
!   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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1880,1892 ****

    maybe_dump_rtl_for_gimple_stmt (stmt, last2);

!   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;

    return new_bb;
  }
--- 1861,1871 ----

    maybe_dump_rtl_for_gimple_stmt (stmt, last2);

!   if (!IS_UNKNOWN_LOCATION (true_edge->goto_locus))
      {
!       set_curr_insn_location (true_edge->goto_locus);
!       true_edge->goto_locus = curr_insn_location ();
      }

    return new_bb;
  }
*************** expand_call_stmt (gimple stmt)
*** 1986,1992 ****
      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))
--- 1965,1970 ----
*************** expand_gimple_stmt_1 (gimple stmt)
*** 2021,2028 ****
  {
    tree op0;

!   set_curr_insn_source_location (gimple_location (stmt));
!   set_curr_insn_block (gimple_block (stmt));

    switch (gimple_code (stmt))
      {
--- 1999,2005 ----
  {
    tree op0;

!   set_curr_insn_location (gimple_location (stmt));

    switch (gimple_code (stmt))
      {
*************** expand_gimple_basic_block (basic_block b
*** 3766,3773 ****
  	  tree op;
  	  gimple def;

! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();

  	  /* Look for SSA names that have their last use here (TERed
  	     names always have only one real use).  */
--- 3743,3749 ----
  	  tree op;
  	  gimple def;

! 	  location_t sloc = curr_insn_location ();

  	  /* Look for SSA names that have their last use here (TERed
  	     names always have only one real use).  */
*************** expand_gimple_basic_block (basic_block b
*** 3800,3807 ****
  		    rtx val;
  		    enum machine_mode mode;

! 		    set_curr_insn_source_location (gimple_location (def));
! 		    set_curr_insn_block (gimple_block (def));

  		    DECL_ARTIFICIAL (vexpr) = 1;
  		    TREE_TYPE (vexpr) = TREE_TYPE (value);
--- 3776,3782 ----
  		    rtx val;
  		    enum machine_mode mode;

! 		    set_curr_insn_location (gimple_location (def));

  		    DECL_ARTIFICIAL (vexpr) = 1;
  		    TREE_TYPE (vexpr) = TREE_TYPE (value);
*************** expand_gimple_basic_block (basic_block b
*** 3828,3835 ****
  		      }
  		  }
  	      }
! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}

        currently_expanding_gimple_stmt = stmt;
--- 3803,3809 ----
  		      }
  		  }
  	      }
! 	  set_curr_insn_location (sloc);
  	}

        currently_expanding_gimple_stmt = stmt;
*************** expand_gimple_basic_block (basic_block b
*** 3844,3851 ****
  	}
        else if (gimple_debug_bind_p (stmt))
  	{
! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();
  	  gimple_stmt_iterator nsi = gsi;

  	  for (;;)
--- 3818,3824 ----
  	}
        else if (gimple_debug_bind_p (stmt))
  	{
! 	  location_t sloc = curr_insn_location ();
  	  gimple_stmt_iterator nsi = gsi;

  	  for (;;)
*************** expand_gimple_basic_block (basic_block b
*** 3867,3874 ****

  	      last = get_last_insn ();

! 	      set_curr_insn_source_location (gimple_location (stmt));
! 	      set_curr_insn_block (gimple_block (stmt));

  	      if (DECL_P (var))
  		mode = DECL_MODE (var);
--- 3840,3846 ----

  	      last = get_last_insn ();

! 	      set_curr_insn_location (gimple_location (stmt));

  	      if (DECL_P (var))
  		mode = DECL_MODE (var);
*************** expand_gimple_basic_block (basic_block b
*** 3906,3918 ****
  		break;
  	    }

! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}
        else if (gimple_debug_source_bind_p (stmt))
  	{
! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();
  	  tree var = gimple_debug_source_bind_get_var (stmt);
  	  tree value = gimple_debug_source_bind_get_value (stmt);
  	  rtx val;
--- 3878,3888 ----
  		break;
  	    }

! 	  set_curr_insn_location (sloc);
  	}
        else if (gimple_debug_source_bind_p (stmt))
  	{
! 	  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;
*************** expand_gimple_basic_block (basic_block b
*** 3920,3927 ****

  	  last = get_last_insn ();

! 	  set_curr_insn_source_location (gimple_location (stmt));
! 	  set_curr_insn_block (gimple_block (stmt));

  	  mode = DECL_MODE (var);

--- 3890,3896 ----

  	  last = get_last_insn ();

! 	  set_curr_insn_location (gimple_location (stmt));

  	  mode = DECL_MODE (var);

*************** expand_gimple_basic_block (basic_block b
*** 3939,3946 ****
  	      PAT_VAR_LOCATION_LOC (val) = (rtx)value;
  	    }

! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}
        else
  	{
--- 3908,3914 ----
  	      PAT_VAR_LOCATION_LOC (val) = (rtx)value;
  	    }

! 	  set_curr_insn_location (sloc);
  	}
        else
  	{
*************** expand_gimple_basic_block (basic_block b
*** 3981,3993 ****
    /* 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 ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb)
  	{
  	  emit_jump (label_rtx_for_bb (e->dest));
--- 3949,3956 ----
    /* Expand implicit goto and convert goto_locus.  */
    FOR_EACH_EDGE (e, ei, bb->succs)
      {
!       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));
*************** construct_exit_block (void)
*** 4107,4118 ****

    /* 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)
      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 ();

--- 4070,4078 ----

    /* Make sure the locus is set to the end of the function, so that
       epilogue line numbers and warnings are set properly.  */
!   if (!IS_UNKNOWN_LOCATION (cfun->function_end_locus))
      input_location = cfun->function_end_locus;

    /* Generate rtl for function exit.  */
    expand_function_end ();

*************** gimple_expand_cfg (void)
*** 4331,4350 ****

    rtl_profile_for_bb (ENTRY_BLOCK_PTR);

!   insn_locators_alloc ();
    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
           (DECL_SOURCE_LOCATION (current_function_decl));
        else
!        set_curr_insn_source_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 ();

  #ifdef INSN_SCHEDULING
    init_sched_attrs ();
--- 4291,4309 ----

    rtl_profile_for_bb (ENTRY_BLOCK_PTR);

!   insn_locations_init ();
    if (!DECL_IS_BUILTIN (current_function_decl))
      {
        /* Eventually, all FEs should explicitly set function_start_locus.  */
!       if (IS_UNKNOWN_LOCATION (cfun->function_start_locus))
!        set_curr_insn_location
           (DECL_SOURCE_LOCATION (current_function_decl));
        else
!        set_curr_insn_location (cfun->function_start_locus);
      }
    else
!     set_curr_insn_location (UNKNOWN_LOCATION);
!   prologue_location = curr_insn_location ();

  #ifdef INSN_SCHEDULING
    init_sched_attrs ();
*************** gimple_expand_cfg (void)
*** 4514,4521 ****
    free_histograms ();

    construct_exit_block ();
!   set_curr_insn_block (DECL_INITIAL (current_function_decl));
!   insn_locators_finalize ();

    /* Zap the tree EH table.  */
    set_eh_throw_stmt_table (cfun, NULL);
--- 4473,4479 ----
    free_histograms ();

    construct_exit_block ();
!   insn_locations_finalize ();

    /* Zap the tree EH table.  */
    set_eh_throw_stmt_table (cfun, NULL);
Index: gcc/cfgcleanup.c
===================================================================
*** gcc/cfgcleanup.c	(revision 189835)
--- gcc/cfgcleanup.c	(working copy)
*************** try_forward_edges (int mode, basic_block
*** 481,493 ****
  		  int new_locus = single_succ_edge (target)->goto_locus;
  		  int locus = goto_locus;

! 		  if (new_locus && locus && !locator_eq (new_locus, locus))
  		    new_target = NULL;
  		  else
  		    {
  		      rtx last;

! 		      if (new_locus)
  			locus = new_locus;

  		      last = BB_END (target);
--- 481,495 ----
  		  int new_locus = single_succ_edge (target)->goto_locus;
  		  int locus = goto_locus;

! 		  if (!IS_UNKNOWN_LOCATION (new_locus)
! 		      && !IS_UNKNOWN_LOCATION (locus)
! 		      && new_locus != locus)
  		    new_target = NULL;
  		  else
  		    {
  		      rtx last;

! 		      if (!IS_UNKNOWN_LOCATION (new_locus))
  			locus = new_locus;

  		      last = BB_END (target);
*************** try_forward_edges (int mode, basic_block
*** 495,507 ****
  			last = prev_nondebug_insn (last);

  		      new_locus = last && INSN_P (last)
! 				  ? INSN_LOCATOR (last) : 0;

! 		      if (new_locus && locus && !locator_eq (new_locus, locus))
  			new_target = NULL;
  		      else
  			{
! 			  if (new_locus)
  			    locus = new_locus;

  			  goto_locus = locus;
--- 497,511 ----
  			last = prev_nondebug_insn (last);

  		      new_locus = last && INSN_P (last)
! 				  ? INSN_LOCATION (last) : 0;

! 		      if (!IS_UNKNOWN_LOCATION (new_locus)
! 			  && !IS_UNKNOWN_LOCATION (locus)
! 			  && new_locus != locus)
  			new_target = NULL;
  		      else
  			{
! 			  if (!IS_UNKNOWN_LOCATION (new_locus))
  			    locus = new_locus;

  			  goto_locus = locus;
Index: gcc/tree-ssa-live.c
===================================================================
*** gcc/tree-ssa-live.c	(revision 189835)
--- gcc/tree-ssa-live.c	(working copy)
*************** remove_unused_scope_block_p (tree scope,
*** 587,593 ****
     else
     /* Verfify that only blocks with source location set
        are entry points to the inlined functions.  */
!      gcc_assert (BLOCK_SOURCE_LOCATION (scope) == UNKNOWN_LOCATION);

     TREE_USED (scope) = !unused;
     return unused;
--- 587,593 ----
     else
     /* Verfify that only blocks with source location set
        are entry points to the inlined functions.  */
!      gcc_assert (IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (scope)));

     TREE_USED (scope) = !unused;
     return unused;
*************** dump_scope_block (FILE *file, int indent
*** 615,621 ****
    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)
      {
        expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (scope));
        fprintf (file, " %s:%i", s.file, s.line);
--- 615,621 ----
    fprintf (file, "\n%*s{ Scope block #%i%s%s",indent, "" ,
BLOCK_NUMBER (scope),
    	   TREE_USED (scope) ? "" : " (unused)",
  	   BLOCK_ABSTRACT (scope) ? " (abstract)": "");
!   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);
*************** remove_unused_locals (void)
*** 765,777 ****
            FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_ALL_USES)
              {
  	      tree arg = USE_FROM_PTR (arg_p);
  	      mark_all_vars_used (&arg, global_unused_vars);
              }
          }

        FOR_EACH_EDGE (e, ei, bb->succs)
  	if (e->goto_locus)
! 	  TREE_USED (e->goto_block) = true;
      }

    /* We do a two-pass approach about the out-of-scope clobbers.  We want
--- 765,782 ----
            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, global_unused_vars);
              }
          }

        FOR_EACH_EDGE (e, ei, bb->succs)
  	if (e->goto_locus)
! 	  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 189835)
--- gcc/lto/lto.c	(working copy)
*************** lto_fixup_prevailing_decls (tree t)
*** 1603,1609 ****
    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));
      }
--- 1603,1608 ----
Index: gcc/tree-streamer-out.c
===================================================================
*** gcc/tree-streamer-out.c	(revision 189835)
--- gcc/tree-streamer-out.c	(working copy)
*************** write_ts_decl_minimal_tree_pointers (str
*** 471,477 ****
  {
    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));
  }


--- 471,477 ----
  {
    stream_write_tree (ob, DECL_NAME (expr), ref_p);
    stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
!   lto_output_location (ob, LOCATION_LOCUS (DECL_SOURCE_LOCATION (expr)));
  }


*************** write_ts_exp_tree_pointers (struct outpu
*** 668,674 ****
    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));
    stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
  }

--- 668,674 ----
    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, LOCATION_LOCUS (EXPR_LOCATION (expr)));
    stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
  }

Index: gcc/rtl.c
===================================================================
*** gcc/rtl.c	(revision 189835)
--- gcc/rtl.c	(working copy)
*************** rtx_equal_p_cb (const_rtx x, const_rtx y
*** 440,446 ****
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && locator_eq (XINT (x, i), XINT (y, i)))
  		break;
  #endif
  	      return 0;
--- 440,446 ----
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && XINT (x, i) == XINT (y, i))
  		break;
  #endif
  	      return 0;
*************** rtx_equal_p (const_rtx x, const_rtx y)
*** 579,585 ****
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && locator_eq (XINT (x, i), XINT (y, i)))
  		break;
  #endif
  	      return 0;
--- 579,585 ----
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && XINT (x, i) == XINT (y, i))
  		break;
  #endif
  	      return 0;
Index: gcc/rtl.h
===================================================================
*** gcc/rtl.h	(revision 189835)
--- gcc/rtl.h	(working copy)
*************** extern void rtl_check_failed_flag (const
*** 739,744 ****
--- 739,745 ----
  #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)
*************** extern void rtl_check_failed_flag (const
*** 802,814 ****
  /* The body of an insn.  */
  #define PATTERN(INSN)	XEXP (INSN, 4)

! #define INSN_LOCATOR(INSN) XINT (INSN, 5)
  /* 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 ()))

  /* Code number of instruction, from when it was recognized.
     -1 means this instruction has not been recognized yet.  */
--- 803,815 ----
  /* The body of an insn.  */
  #define PATTERN(INSN)	XEXP (INSN, 4)

! #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) ? \
! 			 INSN_LOCATION (X) : UNKNOWN_LOCATION)

  /* Code number of instruction, from when it was recognized.
     -1 means this instruction has not been recognized yet.  */
*************** extern rtx prev_cc0_setter (rtx);
*** 1807,1818 ****
  /* 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);

  /* In jump.c */
  extern enum rtx_code reverse_condition (enum rtx_code);
--- 1808,1815 ----
  /* In emit-rtl.c  */
  extern int insn_line (const_rtx);
  extern const char * insn_file (const_rtx);
  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);
*************** extern const struct rtl_hooks general_rt
*** 2648,2661 ****
  /* 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 bool optimize_insn_for_size_p (void);
  extern bool optimize_insn_for_speed_p (void);

--- 2645,2654 ----
  /* Keep this for the nonce.  */
  #define gen_lowpart rtl_hooks.gen_lowpart

! 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 189835)
--- gcc/tree-inline.c	(working copy)
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 852,861 ****
        /* 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);
--- 852,857 ----
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 901,913 ****
  	{
  	  /* 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.  */
  	  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,
--- 897,905 ----
  	{
  	  /* Variable substitution need not be simple.  In particular,
  	     the MEM_REF substitution above.  Make sure that
! 	     TREE_CONSTANT and friends are up-to-date.  */
  	  int invariant = is_gimple_min_invariant (*tp);
  	  walk_tree (&TREE_OPERAND (*tp, 0), remap_gimple_op_r, data, NULL);
  	  recompute_tree_invariant_for_addr_expr (*tp);

  	  /* If this used to be invariant, but is not any longer,
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 919,924 ****
--- 911,932 ----
  	}
      }

+   /* 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;
  }
*************** copy_tree_body_r (tree *tp, int *walk_su
*** 1144,1154 ****
  	      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;
  	}

        if (TREE_CODE (*tp) != OMP_CLAUSE)
--- 1152,1161 ----
  	      tree *n;
  	      n = (tree *) pointer_map_contains (id->decl_map,
  						 TREE_BLOCK (*tp));
  	      if (n)
  		new_block = *n;
  	    }
! 	  TREE_SET_BLOCK (*tp, new_block);
  	}

        if (TREE_CODE (*tp) != OMP_CLAUSE)
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 2020,2025 ****
--- 2027,2033 ----
  	      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
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 2031,2039 ****

  	      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.  */
--- 2039,2045 ----
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 2046,2053 ****
  		  gsi_insert_seq_on_edge (new_edge, stmts);
  		  inserted = true;
  		}
  	      add_phi_arg (new_phi, new_arg, new_edge,
! 			   gimple_phi_arg_location_from_edge (phi, old_edge));
  	    }
  	}
      }
--- 2052,2070 ----
  		  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,
! 			   COMBINE_LOCATION (locus, block));
  	    }
  	}
      }
*************** expand_call_inline (basic_block bb, gimp
*** 3946,3952 ****
    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);

    /* Local declarations will be replaced by their equivalents in this
       map.  */
--- 3963,3970 ----
    id->block = make_node (BLOCK);
    BLOCK_ABSTRACT_ORIGIN (id->block) = fn;
    BLOCK_SOURCE_LOCATION (id->block) = input_location;
!   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 189835)
--- gcc/tree-streamer-in.c	(working copy)
*************** lto_input_ts_exp_tree_pointers (struct l
*** 776,782 ****

    loc = lto_input_location (ib, data_in);
    SET_EXPR_LOCATION (expr, loc);
!   TREE_BLOCK (expr) = stream_read_tree (ib, data_in);
  }


--- 776,782 ----

    loc = lto_input_location (ib, data_in);
    SET_EXPR_LOCATION (expr, loc);
!   TREE_SET_BLOCK (expr, stream_read_tree (ib, data_in));
  }


Index: gcc/combine.c
===================================================================
*** gcc/combine.c	(revision 189835)
--- gcc/combine.c	(working copy)
*************** try_combine (rtx i3, rtx i2, rtx i1, rtx
*** 2896,2902 ****

  	  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);

  	  SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
  	  SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
--- 2896,2902 ----

  	  i1 = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
  			     BLOCK_FOR_INSN (i2), XVECEXP (PATTERN (i2), 0, 1),
! 			     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 189835)
--- gcc/tree-outof-ssa.c	(working copy)
*************** set_location_for_edge (edge e)
*** 108,115 ****
  {
    if (e->goto_locus)
      {
!       set_curr_insn_source_location (e->goto_locus);
!       set_curr_insn_block (e->goto_block);
      }
    else
      {
--- 108,114 ----
  {
    if (e->goto_locus)
      {
!       set_curr_insn_location (e->goto_locus);
      }
    else
      {
*************** set_location_for_edge (edge e)
*** 125,132 ****
  		continue;
  	      if (gimple_has_location (stmt) || gimple_block (stmt))
  		{
! 		  set_curr_insn_source_location (gimple_location (stmt));
! 		  set_curr_insn_block (gimple_block (stmt));
  		  return;
  		}
  	    }
--- 124,130 ----
  		continue;
  	      if (gimple_has_location (stmt) || gimple_block (stmt))
  		{
! 		  set_curr_insn_location (gimple_location (stmt));
  		  return;
  		}
  	    }
*************** insert_partition_copy_on_edge (edge e, i
*** 191,197 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);

    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (SA.partition_to_pseudo[dest],
--- 189,195 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_location (locus);

    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (SA.partition_to_pseudo[dest],
*************** insert_value_copy_on_edge (edge e, int d
*** 228,234 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);

    start_sequence ();

--- 226,232 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_location (locus);

    start_sequence ();

*************** insert_rtx_to_part_on_edge (edge e, int
*** 284,290 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_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
--- 282,288 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (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
*************** insert_part_to_rtx_on_edge (edge e, rtx
*** 320,326 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);

    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (dest,
--- 318,324 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (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 189835)
--- gcc/basic-block.h	(working copy)
*************** struct GTY(()) edge_def {
*** 47,54 ****
    /* Auxiliary info specific to a pass.  */
    PTR GTY ((skip (""))) aux;

!   /* Location of any goto implicit in the edge and associated BLOCK.  */
!   tree goto_block;
    location_t goto_locus;

    /* The index number corresponding to this edge in the edge vector
--- 47,53 ----
    /* Auxiliary info specific to a pass.  */
    PTR GTY ((skip (""))) aux;

!   /* 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 189835)
--- gcc/gimple.h	(working copy)
*************** struct GTY(()) gimple_statement_base {
*** 210,219 ****
       and the prev pointer being the last.  */
    gimple next;
    gimple GTY((skip)) prev;
-
-   /* [ WORD 6 ]
-      Lexical block holding this statement.  */
-   tree block;
  };


--- 210,215 ----
*************** gimple_bb (const_gimple g)
*** 1198,1204 ****
  static inline tree
  gimple_block (const_gimple g)
  {
!   return g->gsbase.block;
  }


--- 1194,1200 ----
  static inline tree
  gimple_block (const_gimple g)
  {
!   return LOCATION_BLOCK (g->gsbase.location);
  }


*************** gimple_block (const_gimple g)
*** 1207,1213 ****
  static inline void
  gimple_set_block (gimple g, tree block)
  {
!   g->gsbase.block = block;
  }


--- 1203,1209 ----
  static inline void
  gimple_set_block (gimple g, tree block)
  {
!   g->gsbase.location = COMBINE_LOCATION (g->gsbase.location, block);
  }


*************** gimple_set_location (gimple g, location_
*** 1242,1248 ****
  static inline bool
  gimple_has_location (const_gimple g)
  {
!   return gimple_location (g) != UNKNOWN_LOCATION;
  }


--- 1238,1244 ----
  static inline bool
  gimple_has_location (const_gimple g)
  {
!   return !IS_UNKNOWN_LOCATION (gimple_location (g));
  }


Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c	(revision 189835)
--- gcc/tree-cfg.c	(working copy)
*************** make_cond_expr_edges (basic_block bb)
*** 808,822 ****
    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.  */
--- 808,818 ----
*************** make_goto_expr_edges (basic_block bb)
*** 1026,1033 ****
        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;
      }
--- 1022,1027 ----
*************** gimple_can_merge_blocks_p (basic_block a
*** 1501,1507 ****

    /* When not optimizing, don't merge if we'd lose goto_locus.  */
    if (!optimize
!       && single_succ_edge (a)->goto_locus != UNKNOWN_LOCATION)
      {
        location_t goto_locus = single_succ_edge (a)->goto_locus;
        gimple_stmt_iterator prev, next;
--- 1495,1501 ----

    /* When not optimizing, don't merge if we'd lose goto_locus.  */
    if (!optimize
!       && single_succ_edge (a)->goto_locus)
      {
        location_t goto_locus = single_succ_edge (a)->goto_locus;
        gimple_stmt_iterator prev, next;
*************** move_stmt_op (tree *tp, int *walk_subtre
*** 5987,5995 ****
    tree t = *tp;

    if (EXPR_P (t))
!     /* We should never have TREE_BLOCK set on non-statements.  */
!     gcc_assert (!TREE_BLOCK (t));
!
    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
      {
        if (TREE_CODE (t) == SSA_NAME)
--- 5981,5987 ----
    tree t = *tp;

    if (EXPR_P (t))
!     ;
    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
      {
        if (TREE_CODE (t) == SSA_NAME)
*************** move_block_to_fn (struct function *dest_
*** 6294,6305 ****
      }

    FOR_EACH_EDGE (e, ei, bb->succs)
!     if (e->goto_locus)
        {
! 	tree block = e->goto_block;
  	if (d->orig_block == NULL_TREE
  	    || block == d->orig_block)
! 	  e->goto_block = d->new_block;
  #ifdef ENABLE_CHECKING
  	else if (block != d->new_block)
  	  {
--- 6286,6297 ----
      }

    FOR_EACH_EDGE (e, ei, bb->succs)
!     if (!IS_UNKNOWN_LOCATION (e->goto_locus))
        {
! 	tree block = LOCATION_BLOCK (e->goto_locus);
  	if (d->orig_block == NULL_TREE
  	    || block == d->orig_block)
! 	  e->goto_locus = COMBINE_LOCATION (e->goto_locus, d->new_block);
  #ifdef ENABLE_CHECKING
  	else if (block != d->new_block)
  	  {
Index: gcc/config/alpha/alpha.c
===================================================================
*** gcc/config/alpha/alpha.c	(revision 189835)
--- gcc/config/alpha/alpha.c	(working copy)
*************** alpha_output_mi_thunk_osf (FILE *file, t
*** 8352,8358 ****
       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);
--- 8352,8357 ----
Index: gcc/config/sparc/sparc.c
===================================================================
*** gcc/config/sparc/sparc.c	(revision 189835)
--- gcc/config/sparc/sparc.c	(working copy)
*************** sparc_output_mi_thunk (FILE *file, tree
*** 10654,10660 ****
       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);
--- 10654,10659 ----
Index: gcc/config/i386/i386.c
===================================================================
*** gcc/config/i386/i386.c	(revision 189835)
--- gcc/config/i386/i386.c	(working copy)
*************** x86_output_mi_thunk (FILE *file,
*** 33063,33069 ****
    /* 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);
--- 33063,33068 ----
Index: gcc/config/tilegx/tilegx.c
===================================================================
*** gcc/config/tilegx/tilegx.c	(revision 189835)
--- gcc/config/tilegx/tilegx.c	(working copy)
*************** tilegx_output_mi_thunk (FILE *file, tree
*** 4804,4810 ****
       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);
--- 4804,4809 ----
Index: gcc/config/sh/sh.c
===================================================================
*** gcc/config/sh/sh.c	(revision 189835)
--- gcc/config/sh/sh.c	(working copy)
*************** sh_output_mi_thunk (FILE *file, tree thu
*** 11979,11985 ****
       the insns emitted.  Note that use_thunk calls
       assemble_start_function and assemble_end_function.  */

-   insn_locators_alloc ();
    insns = get_insns ();

    if (optimize > 0)
--- 11979,11984 ----
Index: gcc/config/ia64/ia64.c
===================================================================
*** gcc/config/ia64/ia64.c	(revision 189835)
--- gcc/config/ia64/ia64.c	(working copy)
*************** ia64_output_mi_thunk (FILE *file, tree t
*** 10848,10854 ****
       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);
--- 10848,10853 ----
Index: gcc/config/rs6000/rs6000.c
===================================================================
*** gcc/config/rs6000/rs6000.c	(revision 189835)
--- gcc/config/rs6000/rs6000.c	(working copy)
*************** rs6000_output_mi_thunk (FILE *file, tree
*** 21664,21670 ****
       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);
--- 21664,21669 ----
Index: gcc/config/score/score.c
===================================================================
*** gcc/config/score/score.c	(revision 189835)
--- gcc/config/score/score.c	(working copy)
*************** score_output_mi_thunk (FILE *file, tree
*** 505,511 ****
    /* 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);
--- 505,510 ----
Index: gcc/config/tilepro/tilepro.c
===================================================================
*** gcc/config/tilepro/tilepro.c	(revision 189835)
--- gcc/config/tilepro/tilepro.c	(working copy)
*************** tilepro_asm_output_mi_thunk (FILE *file,
*** 4407,4413 ****
       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);
--- 4407,4412 ----
Index: gcc/config/mips/mips.c
===================================================================
*** gcc/config/mips/mips.c	(revision 189835)
--- gcc/config/mips/mips.c	(working copy)
*************** mips_output_mi_thunk (FILE *file, tree t
*** 15637,15643 ****
    /* 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 ();
    shorten_branches (insn);
--- 15637,15642 ----
Index: gcc/cfgrtl.c
===================================================================
*** gcc/cfgrtl.c	(revision 189835)
--- gcc/cfgrtl.c	(working copy)
*************** rtl_split_block (basic_block bb, void *i
*** 720,738 ****
  static bool
  unique_locus_on_edge_between_p (basic_block a, basic_block b)
  {
!   const int goto_locus = EDGE_SUCC (a, 0)->goto_locus;
    rtx insn, end;

!   if (!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))
      insn = PREV_INSN (insn);

!   if (insn != end && locator_eq (INSN_LOCATOR (insn), goto_locus))
      return false;

    /* Then scan block B forward.  */
--- 720,738 ----
  static bool
  unique_locus_on_edge_between_p (basic_block a, basic_block b)
  {
!   const location_t goto_locus = EDGE_SUCC (a, 0)->goto_locus;
    rtx insn, end;

!   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_HAS_LOCATION (insn)))
      insn = PREV_INSN (insn);

!   if (insn != end && INSN_LOCATION (insn) == goto_locus)
      return false;

    /* Then scan block B forward.  */
*************** unique_locus_on_edge_between_p (basic_bl
*** 743,750 ****
        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))
  	return false;
      }

--- 743,750 ----
        while (insn != end && !NONDEBUG_INSN_P (insn))
  	insn = NEXT_INSN (insn);

!       if (insn != end && INSN_HAS_LOCATION (insn)
! 	  && INSN_LOCATION (insn) == goto_locus)
  	return false;
      }

*************** emit_nop_for_unique_locus_between (basic
*** 761,767 ****
      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;
  }

  /* Blocks A and B are to be merged into a single block A.  The insns
--- 761,767 ----
      return;

    BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
!   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
*************** force_nonfallthru_and_redirect (edge e,
*** 1478,1484 ****
    else
      jump_block = e->src;

!   if (e->goto_locus && e->goto_block == NULL)
      loc = e->goto_locus;
    else
      loc = 0;
--- 1478,1484 ----
    else
      jump_block = e->src;

!   if (!IS_UNKNOWN_LOCATION (e->goto_locus))
      loc = e->goto_locus;
    else
      loc = 0;
*************** fixup_reorder_chain (void)
*** 3337,3343 ****
          edge_iterator ei;

          FOR_EACH_EDGE (e, ei, bb->succs)
! 	  if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
  	    {
  	      edge e2;
  	      edge_iterator ei2;
--- 3337,3344 ----
          edge_iterator ei;

          FOR_EACH_EDGE (e, ei, bb->succs)
! 	  if (!IS_UNKNOWN_LOCATION (e->goto_locus)
! 	      && !(e->flags & EDGE_ABNORMAL))
  	    {
  	      edge e2;
  	      edge_iterator ei2;
*************** fixup_reorder_chain (void)
*** 3347,3361 ****
  	      insn = BB_END (e->src);
  	      end = PREV_INSN (BB_HEAD (e->src));
  	      while (insn != end
! 		     && (!NONDEBUG_INSN_P (insn) || INSN_LOCATOR (insn) == 0))
  		insn = PREV_INSN (insn);
  	      if (insn != end
! 		  && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
  		continue;
  	      if (simplejump_p (BB_END (e->src))
! 		  && INSN_LOCATOR (BB_END (e->src)) == 0)
  		{
! 		  INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
  		  continue;
  		}
  	      dest = e->dest;
--- 3348,3362 ----
  	      insn = BB_END (e->src);
  	      end = PREV_INSN (BB_HEAD (e->src));
  	      while (insn != end
! 		     && (!NONDEBUG_INSN_P (insn) || !INSN_HAS_LOCATION (insn)))
  		insn = PREV_INSN (insn);
  	      if (insn != end
! 		  && INSN_LOCATION (insn) == e->goto_locus)
  		continue;
  	      if (simplejump_p (BB_END (e->src))
! 		  && !INSN_HAS_LOCATION (BB_END (e->src)))
  		{
! 		  INSN_LOCATION (BB_END (e->src)) = e->goto_locus;
  		  continue;
  		}
  	      dest = e->dest;
*************** fixup_reorder_chain (void)
*** 3371,3394 ****
  		  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))
  		    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;

  	      /* 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
  		    && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
! 		    && locator_eq (e->goto_locus, e2->goto_locus))
  		  redirect_edge_and_branch (e2, nb);
  		else
  		  ei_next (&ei2);
--- 3372,3395 ----
  		  end = NEXT_INSN (BB_END (dest));
  		  while (insn != end && !NONDEBUG_INSN_P (insn))
  		    insn = NEXT_INSN (insn);
! 		  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_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 (!IS_UNKNOWN_LOCATION (e2->goto_locus)
  		    && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
! 		    && e->goto_locus == e2->goto_locus)
  		  redirect_edge_and_branch (e2, nb);
  		else
  		  ei_next (&ei2);
*************** cfg_layout_merge_blocks (basic_block a,
*** 4088,4094 ****
      }

    /* If B was a forwarder block, propagate the locus on the edge.  */
!   if (forwarder_p && !EDGE_SUCC (b, 0)->goto_locus)
      EDGE_SUCC (b, 0)->goto_locus = EDGE_SUCC (a, 0)->goto_locus;

    if (dump_file)
--- 4089,4095 ----
      }

    /* If B was a forwarder block, propagate the locus on the edge.  */
!   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 189835)
--- gcc/stmt.c	(working copy)
*************** emit_case_nodes (rtx index, case_node_pt
*** 2397,2403 ****
  		 then emit the code for one side at a time.  */

  	      tree test_label
! 		= build_decl (CURR_INSN_LOCATION,
  			      LABEL_DECL, NULL_TREE, NULL_TREE);

  	      /* See if the value is on the right.  */
--- 2397,2403 ----
  		 then emit the code for one side at a time.  */

  	      tree test_label
! 		= build_decl (curr_insn_location (),
  			      LABEL_DECL, NULL_TREE, NULL_TREE);

  	      /* See if the value is on the right.  */
*************** emit_case_nodes (rtx index, case_node_pt
*** 2521,2527 ****
  	      /* Right hand node requires testing.
  		 Branch to a label where we will handle it later.  */

! 	      test_label = build_decl (CURR_INSN_LOCATION,
  				       LABEL_DECL, NULL_TREE, NULL_TREE);
  	      emit_cmp_and_jump_insns (index,
  				       convert_modes
--- 2521,2527 ----
  	      /* Right hand node requires testing.
  		 Branch to a label where we will handle it later.  */

! 	      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 189835)
--- libcpp/include/line-map.h	(working copy)
*************** struct GTY(()) line_map_ordinary {
*** 89,95 ****

  /* This is the highest possible source location encoded within an
     ordinary or macro map.  */
! #define MAX_SOURCE_LOCATION 0xFFFFFFFF

  struct cpp_hashnode;

--- 89,95 ----

  /* This is the highest possible source location encoded within an
     ordinary or macro map.  */
! #define MAX_SOURCE_LOCATION 0x7FFFFFFF

  struct cpp_hashnode;

*************** struct GTY(()) line_maps {
*** 408,413 ****
--- 408,423 ----
  #define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
    LINEMAPS_LAST_ALLOCATED_MAP (SET, true)

+ extern void location_block_init (void);
+ extern void location_block_fini (void);
+ extern source_location get_combine_location (source_location, void *);
+ extern void *get_block_from_location (source_location);
+ extern source_location get_locus_from_location (source_location);
+
+ #define COMBINE_LOCATION(LOC, BLOCK) \
+   ((BLOCK) ? get_combine_location ((LOC), (BLOCK)) : (LOC))
+ #define IS_COMBINED_LOCATION(LOC) (((LOC) & MAX_SOURCE_LOCATION) != (LOC))
+
  /* Initialize a line map set.  */
  extern void linemap_init (struct line_maps *);

*************** typedef struct
*** 594,599 ****
--- 604,611 ----

    int column;

+   void *block;
+
    /* In a system header?. */
    bool sysp;
  } expanded_location;
Index: libcpp/line-map.c
===================================================================
*** libcpp/line-map.c	(revision 189835)
--- libcpp/line-map.c	(working copy)
*************** along with this program; see the file CO
*** 25,30 ****
--- 25,31 ----
  #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 *,
*************** static source_location linemap_macro_loc
*** 50,55 ****
--- 51,171 ----
  extern unsigned num_expanded_macros_counter;
  extern unsigned num_macro_tokens_counter;

+ struct location_block {
+   source_location locus;
+   void *block;
+ };
+
+ static htab_t location_block_htab;
+ static source_location curr_combined_location;
+ static struct location_block *location_blocks;
+ static unsigned int allocated_location_blocks;
+
+ /* Hash function for location_block hashtable.  */
+
+ static hashval_t
+ location_block_hash (const void *l)
+ {
+   const struct location_block *lb = (const struct location_block *) l;
+   return (hashval_t) lb->locus + (size_t) &lb->block;
+ }
+
+ /* Compare function for location_block hashtable.  */
+
+ static int
+ location_block_eq (const void *l1, const void *l2)
+ {
+   const struct location_block *lb1 = (const struct location_block *) l1;
+   const struct location_block *lb2 = (const struct location_block *) l2;
+   return lb1->locus == lb2->locus && lb1->block == lb2->block;
+ }
+
+ /* Update the hashtable when location_blocks is reallocated.  */
+
+ static int
+ location_block_update (void **slot, void *data)
+ {
+   *((char **) slot) += ((char *) location_blocks - (char *) data);
+   return 1;
+ }
+
+ /* Combine LOCUS and BLOCK to a combined location.  */
+
+ source_location
+ get_combine_location (source_location locus, void *block)
+ {
+   struct location_block lb;
+   struct location_block **slot;
+
+   linemap_assert (block);
+
+   if (IS_COMBINED_LOCATION (locus))
+     locus = location_blocks[locus & MAX_SOURCE_LOCATION].locus;
+   if (locus == 0 && block == NULL)
+     return 0;
+   lb.locus = locus;
+   lb.block = block;
+   slot = (struct location_block **)
+       htab_find_slot (location_block_htab, &lb, INSERT);
+   if (*slot == NULL)
+     {
+       *slot = location_blocks + curr_combined_location;
+       location_blocks[curr_combined_location] = lb;
+       if (++curr_combined_location >= allocated_location_blocks)
+ 	{
+ 	  char *orig_location_blocks = (char *) location_blocks;
+ 	  allocated_location_blocks *= 2;
+ 	  location_blocks = XRESIZEVEC (struct location_block,
+ 				 	location_blocks,
+ 					allocated_location_blocks);
+ 	  htab_traverse (location_block_htab, location_block_update,
+ 			 orig_location_blocks);
+ 	}
+     }
+   return ((*slot) - location_blocks) | 0x80000000;
+ }
+
+ /* Return the block for LOCATION.  */
+
+ void *
+ get_block_from_location (source_location location)
+ {
+   linemap_assert (IS_COMBINED_LOCATION (location));
+   return location_blocks[location & MAX_SOURCE_LOCATION].block;
+ }
+
+ /* Return the locus for LOCATION.  */
+
+ source_location
+ get_locus_from_location (source_location location)
+ {
+   linemap_assert (IS_COMBINED_LOCATION (location));
+   return location_blocks[location & MAX_SOURCE_LOCATION].locus;
+ }
+
+ /* Initialize the location_block structure.  */
+
+ void
+ location_block_init (void)
+ {
+   location_block_htab = htab_create (100, location_block_hash,
+ 				     location_block_eq, NULL);
+   curr_combined_location = 0;
+   allocated_location_blocks = 100;
+   location_blocks = XNEWVEC (struct location_block,
+ 			     allocated_location_blocks);
+ }
+
+ /* Finalize the location_block structure.  */
+
+ void
+ location_block_fini (void)
+ {
+   allocated_location_blocks = 0;
+   XDELETEVEC (location_blocks);
+   htab_delete (location_block_htab);
+ }
+
  /* Initialize a line map set.  */

  void
*************** linemap_position_for_line_and_column (st
*** 509,514 ****
--- 625,632 ----
  const struct line_map*
  linemap_lookup (struct line_maps *set, source_location line)
  {
+   if (IS_COMBINED_LOCATION (line))
+     line = location_blocks[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);
*************** linemap_ordinary_map_lookup (struct line
*** 525,530 ****
--- 643,651 ----
    unsigned int md, mn, mx;
    const struct line_map *cached, *result;

+   if (IS_COMBINED_LOCATION (line))
+     line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
+
    if (set ==  NULL || line < RESERVED_LOCATION_COUNT)
      return NULL;

*************** linemap_macro_map_lookup (struct line_ma
*** 570,575 ****
--- 691,699 ----
    unsigned int md, mn, mx;
    const struct line_map *cached, *result;

+   if (IS_COMBINED_LOCATION (line))
+     line = location_blocks[line & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));

    if (set ==  NULL)
*************** linemap_macro_map_loc_to_def_point (cons
*** 648,653 ****
--- 772,780 ----
  {
    unsigned token_no;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (linemap_macro_expansion_map_p (map)
  		  && location >= MAP_START_LOCATION (map));
    linemap_assert (location >= RESERVED_LOCATION_COUNT);
*************** linemap_macro_map_loc_unwind_toward_spel
*** 672,677 ****
--- 799,807 ----
  {
    unsigned token_no;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (linemap_macro_expansion_map_p (map)
  		  && location >= MAP_START_LOCATION (map));
    linemap_assert (location >= RESERVED_LOCATION_COUNT);
*************** linemap_get_expansion_line (struct line_
*** 696,701 ****
--- 826,834 ----
  {
    const struct line_map *map = NULL;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    if (location < RESERVED_LOCATION_COUNT)
      return 0;

*************** linemap_get_expansion_filename (struct l
*** 720,725 ****
--- 853,861 ----
  {
    const struct line_map *map = NULL;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    if (location < RESERVED_LOCATION_COUNT)
      return NULL;

*************** linemap_location_in_system_header_p (str
*** 754,759 ****
--- 890,898 ----
  {
    const struct line_map *map = NULL;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    if (location < RESERVED_LOCATION_COUNT)
      return false;

*************** bool
*** 793,798 ****
--- 932,940 ----
  linemap_location_from_macro_expansion_p (struct line_maps *set,
  					 source_location location)
  {
+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (location <= MAX_SOURCE_LOCATION
  		  && (set->highest_location
  		      < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
*************** linemap_macro_loc_to_spelling_point (str
*** 933,938 ****
--- 1075,1083 ----
  {
    struct line_map *map;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (set && location >= RESERVED_LOCATION_COUNT);

    while (true)
*************** linemap_macro_loc_to_def_point (struct l
*** 967,972 ****
--- 1112,1120 ----
  {
    struct line_map *map;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (set && location >= RESERVED_LOCATION_COUNT);

    while (true)
*************** linemap_macro_loc_to_exp_point (struct l
*** 1005,1010 ****
--- 1153,1161 ----
  {
    struct line_map *map;

+   if (IS_COMBINED_LOCATION (location))
+     location = location_blocks[location & MAX_SOURCE_LOCATION].locus;
+
    linemap_assert (set && location >= RESERVED_LOCATION_COUNT);

    while (true)
*************** linemap_resolve_location (struct line_ma
*** 1074,1079 ****
--- 1225,1233 ----
  			  enum location_resolution_kind lrk,
  			  const struct line_map **map)
  {
+   if (IS_COMBINED_LOCATION (loc))
+     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+
    if (loc < RESERVED_LOCATION_COUNT)
      {
        /* A reserved location wasn't encoded in a map.  Let's return a
*************** linemap_unwind_toward_expansion (struct
*** 1121,1126 ****
--- 1275,1283 ----
    source_location resolved_location;
    const struct line_map *resolved_map;

+   if (IS_COMBINED_LOCATION (loc))
+     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+
    resolved_location =
      linemap_macro_map_loc_unwind_toward_spelling (*map, loc);
    resolved_map = linemap_lookup (set, resolved_location);
*************** linemap_unwind_to_first_non_reserved_loc
*** 1157,1162 ****
--- 1314,1322 ----
    source_location resolved_loc;
    const struct line_map *map0 = NULL, *map1 = NULL;

+   if (IS_COMBINED_LOCATION (loc))
+     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+
    map0 = linemap_lookup (set, loc);
    if (!linemap_macro_expansion_map_p (map0))
      return loc;
*************** linemap_expand_location (struct line_map
*** 1198,1203 ****
--- 1358,1368 ----
    expanded_location xloc;

    memset (&xloc, 0, sizeof (xloc));
+   if (IS_COMBINED_LOCATION (loc))
+     {
+       loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+       xloc.block = location_blocks[loc & MAX_SOURCE_LOCATION].block;
+     }

    if (loc < RESERVED_LOCATION_COUNT)
      /* The location for this token wasn't generated from a line map.
*************** linemap_dump_location (struct line_maps
*** 1290,1295 ****
--- 1455,1463 ----
    const char *path = "", *from = "";
    int l = -1, c = -1, s = -1, e = -1;

+   if (IS_COMBINED_LOCATION (loc))
+     loc = location_blocks[loc & MAX_SOURCE_LOCATION].locus;
+
    if (loc == 0)
      return;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-07 15:52           ` Dehao Chen
@ 2012-08-13 18:35             ` Dodji Seketeli
  2012-08-14  4:58               ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Dodji Seketeli @ 2012-08-13 18:35 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Richard Guenther, gcc-patches, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey

Hello Dehao,

I have mostly cosmetic comments to make about the libcpp parts.

Dehao Chen <dehao@google.com> writes:

> Index: libcpp/include/line-map.h
> ===================================================================
> *** libcpp/include/line-map.h	(revision 189835)
> --- libcpp/include/line-map.h	(working copy)
> *************** struct GTY(()) line_map_ordinary {
> *** 89,95 ****
>

Just to sum things up, here is what I understand from the libcpp
changes.

The integer space is now segmented like this:

    X  A  B  C
    [        ]  <--- integer space of source_location

C is the smallest possible source_location and X is the biggest
possible.

From X to A, we have instances of source_location encoded in an ad-hoc
client specific (from the point of view of libcpp/line-map) map.

From A to B, we have instances of source_location encoded in macro maps.

From B to C, we have instances of source_location encoded in ordinary
maps.

As of this patch, MAX_SOURCE_LOCATION is A.  X is 0xFFFFFFFF and is not
represented by any particular constant declaration.

From the point of view libcpp the goal of this patch is to 

1/ Provide functions to encode a pair of 
   {non-ad-hoc source_location, client specific data} and yield an
   integer for that (a new instance of source_location).

2/ modify the lookup routines of line-map to have them recognize
   instances of source_location encoded in the ad-hoc map.

If this description is correct, I think a high level comment like this
should be added to line-map.c or line-map.h to help people understand
this in the future, a bit like what has been done for ordinary and macro
maps.

[...]

> + extern void *get_block_from_location (source_location);

I'd call this function get_block_from_ad_hoc_location instead.  Or
something like that, to hint at the fact that the parameter is not an
actual source location.

> + extern source_location get_locus_from_location (source_location);

Likewise, I'd call this get_source_location_from_ad_hoc_loc.

> +
> + #define COMBINE_LOCATION(LOC, BLOCK) \
> +   ((BLOCK) ? get_combine_location ((LOC), (BLOCK)) : (LOC))
> + #define IS_COMBINED_LOCATION(LOC) (((LOC) & MAX_SOURCE_LOCATION) != (LOC))
> +
>   /* Initialize a line map set.  */
>   extern void linemap_init (struct line_maps *);
>
> *************** typedef struct
> *** 594,599 ****
> --- 604,611 ----
>
>     int column;
>
> +   void *block;
> +

I'd just call this 'data' or something like, and add I comment
explaining that its a client specific data that is not manipulated by
libcpp.

>     /* In a system header?. */
>     bool sysp;
>   } expanded_location;


> --- libcpp/line-map.c	(working copy)

[...]


> + struct location_block {
> +   source_location locus;
> +   void *block;
> + };

I think we should have a more general name than "block" here.  I am
thinking that other client code might be willing to associate entities
other than blocks to a given source_location in a scheme similar to this
one.  Also, it seems surprising to have the line-maps library deal with
blocks specifically.

So maybe something like this instead?:

    /* Data structure to associate an arbitrary data to a source location.  */
    struct location_ad_hoc_data {
      source_location locus;
      void *data;
    };


Subsequently, if you agree with this, all the occurrences of 'block' in
the new code (function, types, and variable names) you introduced should
be replaced with 'ad_hoc_data'.

> + source_location
> + get_combine_location (source_location locus, void *block)

Shouldn't this be get_combined_location instead?  Note the 'd' after the
combine.

> --- gcc/input.h	(working copy)

[...]

> + #define LOCATION_LOCUS(LOC) \
> +   ((IS_COMBINED_LOCATION(LOC)) ? get_locus_from_location (LOC) : (LOC))

I think this name sounds confusing.  Maybe something like
SOURCE_LOCATION_FROM_AD_HOC_LOC instead?  And please add a comment to
explain a little bit about this business of ad hoc location that
associates a block with an actual source location.

> + #define LOCATION_BLOCK(LOC) \
> +   ((tree) ((IS_COMBINED_LOCATION (LOC)) ? get_block_from_location (LOC) \
> +   : NULL))

And the name of this macro would then be something like BLOCK_FROM_AD_HOC_LOC.

> + #define IS_UNKNOWN_LOCATION(LOC) \
> +   ((IS_COMBINED_LOCATION (LOC)) ? get_locus_from_location (LOC) == 0 \
> +   : (LOC) == 0)

-- 
		Dodji

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-13 18:35             ` Dodji Seketeli
@ 2012-08-14  4:58               ` Dehao Chen
  2012-08-14  7:56                 ` Dodji Seketeli
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-08-14  4:58 UTC (permalink / raw)
  To: Dodji Seketeli
  Cc: Richard Guenther, gcc-patches, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey

Hi, Dodji,

Thanks a lot for the review. I've updated the patch, which is attached.

Passed bootstrap and all regression tests.

Thanks,
Dehao

gcc/ChangeLog
2012-08-01  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.
	* dewarf2out.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-08-01  Dehao Chen  <dehao@google.com>

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

libcpp/ChangeLog
2012-08-01  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 190209)
--- gcc/gimple-streamer-out.c	(working copy)
*************** output_gimple_stmt (struct output_block
*** 74,80 ****
    streamer_write_bitpack (&bp);

    /* Emit location information for the statement.  */
!   lto_output_location (ob, gimple_location (stmt));

    /* Emit the lexical block holding STMT.  */
    stream_write_tree (ob, gimple_block (stmt), true);
--- 74,80 ----
    streamer_write_bitpack (&bp);

    /* Emit location information for the statement.  */
!   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 190209)
--- gcc/tree.c	(working copy)
*************** build1_stat (enum tree_code code, tree t
*** 3760,3766 ****
    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);
--- 3760,3765 ----
*************** walk_tree_without_duplicates_1 (tree *tp
*** 10831,10847 ****
  }


! tree *
  tree_block (tree t)
  {
    char const c = TREE_CODE_CLASS (TREE_CODE (t));

    if (IS_EXPR_CODE_CLASS (c))
!     return &t->exp.block;
    gcc_unreachable ();
    return NULL;
  }

  /* 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.  */
--- 10830,10857 ----
  }


! tree
  tree_block (tree t)
  {
    char const c = TREE_CODE_CLASS (TREE_CODE (t));

    if (IS_EXPR_CODE_CLASS (c))
!     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 190209)
--- gcc/tree.h	(working copy)
*************** extern void omp_clause_range_check_faile
*** 999,1005 ****

  #endif

! #define TREE_BLOCK(NODE)		*(tree_block (NODE))

  #include "tree-check.h"

--- 999,1006 ----

  #endif

! #define TREE_BLOCK(NODE)		(tree_block (NODE))
! #define TREE_SET_BLOCK(T, B)		(tree_set_block ((T), (B)))

  #include "tree-check.h"

*************** struct GTY(()) tree_constructor {
*** 1702,1708 ****
  #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)
  /* 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)
--- 1703,1709 ----
  #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) (!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)
*************** extern void protected_set_expr_location
*** 1881,1887 ****
  					      OMP_CLAUSE_PRIVATE,	\
  	                                      OMP_CLAUSE_COPYPRIVATE), 0)
  #define OMP_CLAUSE_HAS_LOCATION(NODE) \
!   ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus != UNKNOWN_LOCATION)
  #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,1888 ----
  					      OMP_CLAUSE_PRIVATE,	\
  	                                      OMP_CLAUSE_COPYPRIVATE), 0)
  #define OMP_CLAUSE_HAS_LOCATION(NODE) \
!   (!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.
*************** enum omp_clause_default_kind
*** 1972,1978 ****
  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];
--- 1973,1978 ----
*************** function_args_iter_next (function_args_i
*** 5136,5142 ****
  static inline bool
  inlined_function_outer_scope_p (const_tree block)
  {
!  return BLOCK_SOURCE_LOCATION (block) != UNKNOWN_LOCATION;
  }

  /* Loop over all function arguments of FNTYPE.  In each iteration, PTR is set
--- 5136,5142 ----
  static inline bool
  inlined_function_outer_scope_p (const_tree block)
  {
!  return !IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (block));
  }

  /* Loop over all function arguments of FNTYPE.  In each iteration, PTR is set
*************** extern bool subrange_type_for_debug_p (c
*** 5511,5517 ****
  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 location_t *block_nonartificial_location (tree);
  extern location_t tree_nonartificial_location (tree);

--- 5511,5518 ----
  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 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 190209)
--- gcc/final.c	(working copy)
*************** reemit_insn_block_notes (void)
*** 1605,1611 ****
  					     insn_scope (XVECEXP (body, 0, i)));
  	}
        if (! this_block)
! 	continue;

        if (this_block != cur_block)
  	{
--- 1605,1611 ----
  					     insn_scope (XVECEXP (body, 0, i)));
  	}
        if (! this_block)
! 	this_block = DECL_INITIAL (cfun->decl);

        if (this_block != cur_block)
  	{
*************** final_start_function (rtx first ATTRIBUT
*** 1640,1647 ****

    this_is_asm_operands = 0;

!   last_filename = locator_file (prologue_locator);
!   last_linenum = locator_line (prologue_locator);
    last_discriminator = discriminator = 0;

    high_block_linenum = high_function_linenum = last_linenum;
--- 1640,1647 ----

    this_is_asm_operands = 0;

!   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 190209)
--- gcc/input.c	(working copy)
*************** expand_location_1 (source_location loc,
*** 51,56 ****
--- 51,63 ----
    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));

*************** expand_location_1 (source_location loc,
*** 74,79 ****
--- 81,87 ----
        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 190209)
--- gcc/input.h	(working copy)
*************** extern location_t input_location;
*** 51,56 ****
--- 51,64 ----
  #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 190209)
--- gcc/fold-const.c	(working copy)
*************** static location_t
*** 145,151 ****
  expr_location_or (tree t, location_t loc)
  {
    location_t tloc = EXPR_LOCATION (t);
!   return tloc != UNKNOWN_LOCATION ? tloc : loc;
  }

  /* Similar to protected_set_expr_location, but never modify x in place,
--- 145,151 ----
  expr_location_or (tree t, location_t loc)
  {
    location_t tloc = EXPR_LOCATION (t);
!   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 190209)
--- gcc/toplev.c	(working copy)
*************** general_init (const char *argv0)
*** 1140,1145 ****
--- 1140,1146 ----
    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.  */
*************** toplev_main (int argc, char **argv)
*** 1946,1951 ****
--- 1947,1953 ----
    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 190209)
--- gcc/reorg.c	(working copy)
*************** emit_delay_sequence (rtx insn, rtx list,
*** 545,551 ****
    INSN_DELETED_P (delay_insn) = 0;
    PREV_INSN (delay_insn) = PREV_INSN (seq_insn);

!   INSN_LOCATOR (seq_insn) = INSN_LOCATOR (delay_insn);

    for (li = list; li; li = XEXP (li, 1), i++)
      {
--- 545,551 ----
    INSN_DELETED_P (delay_insn) = 0;
    PREV_INSN (delay_insn) = PREV_INSN (seq_insn);

!   INSN_LOCATION (seq_insn) = INSN_LOCATION (delay_insn);

    for (li = list; li; li = XEXP (li, 1), i++)
      {
*************** emit_delay_sequence (rtx insn, rtx list,
*** 561,569 ****

        /* 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;

        for (note = REG_NOTES (tem); note; note = next)
  	{
--- 561,569 ----

        /* SPARC assembler, for instance, emit warning when debug info is output
           into the delay slot.  */
!       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)
  	{
*************** dbr_schedule (rtx first)
*** 4065,4071 ****
      for (link = crtl->epilogue_delay_list;
           link;
           link = XEXP (link, 1))
!       INSN_LOCATOR (XEXP (link, 0)) = 0;
    }

  #endif
--- 4065,4071 ----
      for (link = crtl->epilogue_delay_list;
           link;
           link = XEXP (link, 1))
!       INSN_LOCATION (XEXP (link, 0)) = 0;
    }

  #endif

Index: gcc/modulo-sched.c
===================================================================
*** gcc/modulo-sched.c	(revision 190209)
--- gcc/modulo-sched.c	(working copy)
*************** loop_single_full_bb_p (struct loop *loop
*** 1246,1254 ****
  /* Dump file:line from INSN's location info to dump_file.  */

  static void
! dump_insn_locator (rtx insn)
  {
!   if (dump_file && INSN_LOCATOR (insn))
      {
        const char *file = insn_file (insn);
        if (file)
--- 1246,1254 ----
  /* Dump file:line from INSN's location info to dump_file.  */

  static void
! dump_insn_location (rtx insn)
  {
!   if (dump_file && INSN_LOCATION (insn))
      {
        const char *file = insn_file (insn);
        if (file)
*************** loop_canon_p (struct loop *loop)
*** 1282,1288 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many exits");
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
--- 1282,1288 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many exits");
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
*************** loop_canon_p (struct loop *loop)
*** 1295,1301 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many BBs.");
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
--- 1295,1301 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop many BBs.");
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
*************** sms_schedule (void)
*** 1421,1427 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}

--- 1421,1427 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}

*************** sms_schedule (void)
*** 1450,1456 ****
  	{
  	  if (dump_file)
  	    {
! 	      dump_insn_locator (tail);
  	      fprintf (dump_file, "\nSMS single-bb-loop\n");
  	      if (profile_info && flag_branch_probabilities)
  	    	{
--- 1450,1456 ----
  	{
  	  if (dump_file)
  	    {
! 	      dump_insn_location (tail);
  	      fprintf (dump_file, "\nSMS single-bb-loop\n");
  	      if (profile_info && flag_branch_probabilities)
  	    	{
*************** sms_schedule (void)
*** 1556,1562 ****
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");

  	  print_ddg (dump_file, g);
--- 1556,1562 ----
  	  rtx insn = BB_END (loop->header);

  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");

  	  print_ddg (dump_file, g);
*************** sms_schedule (void)
*** 1571,1577 ****

        if (dump_file)
  	{
! 	  dump_insn_locator (tail);
  	  fprintf (dump_file, "\nSMS single-bb-loop\n");
  	  if (profile_info && flag_branch_probabilities)
  	    {
--- 1571,1577 ----

        if (dump_file)
  	{
! 	  dump_insn_location (tail);
  	  fprintf (dump_file, "\nSMS single-bb-loop\n");
  	  if (profile_info && flag_branch_probabilities)
  	    {
*************** sms_schedule (void)
*** 1714,1720 ****

            if (dump_file)
              {
! 	      dump_insn_locator (tail);
  	      fprintf (dump_file, " SMS succeeded %d %d (with ii, sc)\n",
  		       ps->ii, stage_count);
  	      print_partial_schedule (ps, dump_file);
--- 1714,1720 ----

            if (dump_file)
              {
! 	      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 190209)
--- gcc/lto-streamer-out.c	(working copy)
*************** lto_output_location_bitpack (struct bitp
*** 155,160 ****
--- 155,161 ----
  {
    expanded_location xloc;

+   loc = LOCATION_LOCUS (loc);
    bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
    if (loc == UNKNOWN_LOCATION)
      return;
Index: gcc/jump.c
===================================================================
*** gcc/jump.c	(revision 190209)
--- gcc/jump.c	(working copy)
*************** rtx_renumbered_equal_p (const_rtx x, con
*** 1818,1825 ****
  	  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)))
  		break;
  	      return 0;
  	    }
--- 1818,1824 ----
  	  if (XINT (x, i) != XINT (y, i))
  	    {
  	      if (((code == ASM_OPERANDS && i == 6)
! 		   || (code == ASM_INPUT && i == 1)))
  		break;
  	      return 0;
  	    }
Index: gcc/ifcvt.c
===================================================================
*** gcc/ifcvt.c	(revision 190209)
--- gcc/ifcvt.c	(working copy)
*************** noce_try_move (struct noce_if_info *if_i
*** 1019,1025 ****
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	}
        return TRUE;
      }
--- 1019,1025 ----
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	}
        return TRUE;
      }
*************** noce_try_store_flag (struct noce_if_info
*** 1064,1070 ****
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
        return TRUE;
      }
    else
--- 1064,1070 ----
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
        return TRUE;
      }
    else
*************** noce_try_store_flag_constants (struct no
*** 1195,1201 ****
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
        return TRUE;
      }

--- 1195,1201 ----
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
        return TRUE;
      }

*************** noce_try_addcc (struct noce_if_info *if_
*** 1243,1249 ****
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATOR (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
--- 1243,1249 ----
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATION (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
*************** noce_try_addcc (struct noce_if_info *if_
*** 1283,1289 ****
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATOR (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
--- 1283,1289 ----
  		return FALSE;

  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATION (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
*************** noce_try_store_flag_mask (struct noce_if
*** 1332,1338 ****
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	  return TRUE;
  	}

--- 1332,1338 ----
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	  return TRUE;
  	}

*************** noce_try_cmove (struct noce_if_info *if_
*** 1481,1487 ****
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	  return TRUE;
  	}
        else
--- 1481,1487 ----
  	    return FALSE;

  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	  return TRUE;
  	}
        else
*************** noce_try_cmove_arith (struct noce_if_inf
*** 1682,1688 ****
    if (!tmp)
      return FALSE;

!   emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    return TRUE;

   end_seq_and_fail:
--- 1682,1688 ----
    if (!tmp)
      return FALSE;

!   emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    return TRUE;

   end_seq_and_fail:
*************** noce_try_minmax (struct noce_if_info *if
*** 1929,1935 ****
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

--- 1929,1935 ----
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

*************** noce_try_abs (struct noce_if_info *if_in
*** 2076,2082 ****
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

--- 2076,2082 ----
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;

*************** noce_try_sign_mask (struct noce_if_info
*** 2155,2161 ****
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR
(if_info->insn_a));
    return TRUE;
  }

--- 2155,2161 ----
    if (!seq)
      return FALSE;

!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION
(if_info->insn_a));
    return TRUE;
  }

*************** noce_try_bitop (struct noce_if_info *if_
*** 2255,2261 ****
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
      }
    return TRUE;
  }
--- 2255,2261 ----
  	return FALSE;

        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
      }
    return TRUE;
  }
*************** noce_process_if_block (struct noce_if_in
*** 2656,2662 ****
        unshare_all_rtl_in_chain (seq);
        end_sequence ();

!       emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATOR (insn_a));
      }

    /* The original THEN and ELSE blocks may now be removed.  The test block
--- 2656,2662 ----
        unshare_all_rtl_in_chain (seq);
        end_sequence ();

!       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
*************** cond_move_process_if_block (struct noce_
*** 2937,2943 ****
        loc_insn = first_active_insn (else_bb);
        gcc_assert (loc_insn);
      }
!   emit_insn_before_setloc (seq, jump, INSN_LOCATOR (loc_insn));

    if (else_bb)
      {
--- 2937,2943 ----
        loc_insn = first_active_insn (else_bb);
        gcc_assert (loc_insn);
      }
!   emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));

    if (else_bb)
      {
*************** find_cond_trap (basic_block test_bb, edg
*** 3655,3661 ****
      return FALSE;

    /* Emit the new insns before cond_earliest.  */
!   emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATOR (trap));

    /* Delete the trap block if possible.  */
    remove_edge (trap_bb == then_bb ? then_edge : else_edge);
--- 3655,3661 ----
      return FALSE;

    /* Emit the new insns before cond_earliest.  */
!   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/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c	(revision 190209)
--- gcc/dwarf2out.c	(working copy)
*************** add_src_coords_attributes (dw_die_ref di
*** 15506,15512 ****
  {
    expanded_location s;

!   if (DECL_SOURCE_LOCATION (decl) == UNKNOWN_LOCATION)
      return;
    s = expand_location (DECL_SOURCE_LOCATION (decl));
    add_AT_file (die, DW_AT_decl_file, lookup_filename (s.file));
--- 15506,15512 ----
  {
    expanded_location s;

!   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 190209)
--- gcc/expr.c	(working copy)
*************** expand_expr_real (tree exp, rtx target,
*** 7802,7820 ****
    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 ();
        input_location = EXPR_LOCATION (exp);
!       set_curr_insn_source_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);
      }
    else
      {
--- 7802,7815 ----
    if (cfun && EXPR_HAS_LOCATION (exp))
      {
        location_t saved_location = input_location;
!       location_t saved_curr_loc = curr_insn_location ();
        input_location = EXPR_LOCATION (exp);
!       set_curr_insn_location (input_location);

        ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);

        input_location = saved_location;
!       set_curr_insn_location (saved_curr_loc);
      }
    else
      {
Index: gcc/tree-parloops.c
===================================================================
*** gcc/tree-parloops.c	(revision 190209)
--- gcc/tree-parloops.c	(working copy)
*************** create_loop_fn (location_t loc)
*** 1404,1409 ****
--- 1404,1410 ----
    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 190209)
--- gcc/recog.c	(working copy)
*************** peep2_attempt (basic_block bb, rtx insn,
*** 3326,3332 ****
    /* 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));
    before_try = PREV_INSN (insn);
    delete_insn_chain (insn, peep2_insn_data[i].insn, false);

--- 3326,3332 ----
    /* Replace the old sequence with the new.  */
    last = emit_insn_after_setloc (attempt,
  				 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 190209)
--- gcc/function.c	(working copy)
*************** static bool contains (const_rtx, htab_t)
*** 133,139 ****
  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;
  \f
  /* Stack of nested functions.  */
  /* Keep track of the cfun stack.  */
--- 133,139 ----
  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_locations (rtx, int) ATTRIBUTE_UNUSED;
  \f
  /* Stack of nested functions.  */
  /* Keep track of the cfun stack.  */
*************** free_after_compilation (struct function
*** 200,206 ****
    f->cfg = NULL;

    regno_reg_rtx = NULL;
-   insn_locators_free ();
  }
  \f
  /* Return size needed for stack frame based on slots so far allocated.
--- 200,205 ----
*************** expand_function_end (void)
*** 4979,4985 ****
  	      probe_stack_range (STACK_OLD_CHECK_PROTECT, max_frame_size);
  	    seq = get_insns ();
  	    end_sequence ();
! 	    set_insn_locators (seq, prologue_locator);
  	    emit_insn_before (seq, stack_check_probe_note);
  	    break;
  	  }
--- 4978,4984 ----
  	      probe_stack_range (STACK_OLD_CHECK_PROTECT, max_frame_size);
  	    seq = get_insns ();
  	    end_sequence ();
! 	    set_insn_locations (seq, prologue_location);
  	    emit_insn_before (seq, stack_check_probe_note);
  	    break;
  	  }
*************** expand_function_end (void)
*** 4994,5000 ****

    /* Output a linenumber for the end of the function.
       SDB depends on this.  */
!   set_curr_insn_source_location (input_location);

    /* Before the return label (if any), clobber the return
       registers so that they are not propagated live to the rest of
--- 4993,4999 ----

    /* Output a linenumber for the end of the function.
       SDB depends on this.  */
!   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
*************** maybe_copy_prologue_epilogue_insn (rtx i
*** 5277,5290 ****
    *slot = copy;
  }

! /* Set the locator of the insn chain starting at INSN to LOC.  */
  static void
! set_insn_locators (rtx insn, int loc)
  {
    while (insn != NULL_RTX)
      {
        if (INSN_P (insn))
! 	INSN_LOCATOR (insn) = loc;
        insn = NEXT_INSN (insn);
      }
  }
--- 5276,5289 ----
    *slot = copy;
  }

! /* Set the location of the insn chain starting at INSN to LOC.  */
  static void
! set_insn_locations (rtx insn, int loc)
  {
    while (insn != NULL_RTX)
      {
        if (INSN_P (insn))
! 	INSN_LOCATION (insn) = loc;
        insn = NEXT_INSN (insn);
      }
  }
*************** thread_prologue_and_epilogue_insns (void
*** 5893,5899 ****
        end_sequence ();

        record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
!       set_insn_locators (split_prologue_seq, prologue_locator);
  #endif
      }

--- 5892,5898 ----
        end_sequence ();

        record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
!       set_insn_locations (split_prologue_seq, prologue_location);
  #endif
      }

*************** thread_prologue_and_epilogue_insns (void
*** 5922,5928 ****

        prologue_seq = get_insns ();
        end_sequence ();
!       set_insn_locators (prologue_seq, prologue_locator);
      }
  #endif

--- 5921,5927 ----

        prologue_seq = get_insns ();
        end_sequence ();
!       set_insn_locations (prologue_seq, prologue_location);
      }
  #endif

*************** thread_prologue_and_epilogue_insns (void
*** 6418,6424 ****

        /* Retain a map of the epilogue insns.  */
        record_insns (seq, NULL, &epilogue_insn_hash);
!       set_insn_locators (seq, epilogue_locator);

        seq = get_insns ();
        returnjump = get_last_insn ();
--- 6417,6423 ----

        /* Retain a map of the epilogue insns.  */
        record_insns (seq, NULL, &epilogue_insn_hash);
!       set_insn_locations (seq, epilogue_location);

        seq = get_insns ();
        returnjump = get_last_insn ();
*************** epilogue_done:
*** 6608,6614 ****
  	     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);

  	  emit_insn_before (seq, insn);
  	}
--- 6607,6613 ----
  	     avoid getting rid of sibcall epilogue insns.  Do this before we
  	     actually emit the sequence.  */
  	  record_insns (seq, NULL, &epilogue_insn_hash);
! 	  set_insn_locations (seq, epilogue_location);

  	  emit_insn_before (seq, insn);
  	}
Index: gcc/print-rtl.c
===================================================================
*** gcc/print-rtl.c	(revision 190209)
--- gcc/print-rtl.c	(working copy)
*************** print_rtx (const_rtx in_rtx)
*** 416,425 ****
  	if (i == 5 && INSN_P (in_rtx))
  	  {
  #ifndef GENERATOR_FILE
! 	    /*  Pretty-print insn locators.  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))
  	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
  #endif
  	  }
--- 416,425 ----
  	if (i == 5 && INSN_P (in_rtx))
  	  {
  #ifndef GENERATOR_FILE
! 	    /*  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_LOCATION (in_rtx) && insn_file (in_rtx))
  	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
  #endif
  	  }
*************** print_rtx (const_rtx in_rtx)
*** 427,442 ****
  	  {
  #ifndef GENERATOR_FILE
  	    fprintf (outfile, " %s:%i",
! 		     locator_file (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)),
! 		     locator_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)));
  #endif
  	  }
  	else if (i == 6 && NOTE_P (in_rtx))
--- 427,442 ----
  	  {
  #ifndef GENERATOR_FILE
  	    fprintf (outfile, " %s:%i",
! 		     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",
! 		     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 190209)
--- gcc/profile.c	(working copy)
*************** branch_prob (void)
*** 966,972 ****
  	     is not computed twice.  */
  	  if (last
  	      && gimple_has_location (last)
! 	      && e->goto_locus != UNKNOWN_LOCATION
  	      && !single_succ_p (bb)
  	      && (LOCATION_FILE (e->goto_locus)
  	          != LOCATION_FILE (gimple_location (last))
--- 966,972 ----
  	     is not computed twice.  */
  	  if (last
  	      && gimple_has_location (last)
! 	      && !IS_UNKNOWN_LOCATION (e->goto_locus)
  	      && !single_succ_p (bb)
  	      && (LOCATION_FILE (e->goto_locus)
  	          != LOCATION_FILE (gimple_location (last))
*************** branch_prob (void)
*** 976,982 ****
  	      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)
--- 976,981 ----
*************** branch_prob (void)
*** 1188,1194 ****

  	  /* Notice GOTO expressions eliminated while constructing the CFG.  */
  	  if (single_succ_p (bb)
! 	      && single_succ_edge (bb)->goto_locus != UNKNOWN_LOCATION)
  	    {
  	      expanded_location curr_location
  		= expand_location (single_succ_edge (bb)->goto_locus);
--- 1187,1193 ----

  	  /* Notice GOTO expressions eliminated while constructing the CFG.  */
  	  if (single_succ_p (bb)
! 	      && !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 190209)
--- gcc/trans-mem.c	(working copy)
*************** ipa_tm_scan_irr_block (basic_block bb)
*** 3795,3801 ****
  	    {
  	      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;
--- 3795,3800 ----
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c	(revision 190209)
--- gcc/gimplify.c	(working copy)
*************** gimplify_call_expr (tree *expr_p, gimple
*** 2591,2597 ****
  	    = 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;
--- 2591,2596 ----
Index: gcc/except.c
===================================================================
*** gcc/except.c	(revision 190209)
--- gcc/except.c	(working copy)
*************** duplicate_eh_regions_1 (struct duplicate
*** 526,532 ****
        break;

      case ERT_MUST_NOT_THROW:
!       new_r->u.must_not_throw = old_r->u.must_not_throw;
        break;
      }

--- 526,535 ----
        break;

      case ERT_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 190209)
--- gcc/emit-rtl.c	(working copy)
*************** try_split (rtx pat, rtx trial, int last)
*** 3634,3640 ****
  	}
      }

!   tem = emit_insn_after_setloc (seq, trial, INSN_LOCATOR (trial));

    delete_insn (trial);
    if (has_barrier)
--- 3634,3640 ----
  	}
      }

!   tem = emit_insn_after_setloc (seq, trial, INSN_LOCATION (trial));

    delete_insn (trial);
    if (has_barrier)
*************** make_insn_raw (rtx pattern)
*** 3670,3676 ****
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

  #ifdef ENABLE_RTL_CHECKING
--- 3670,3676 ----
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

  #ifdef ENABLE_RTL_CHECKING
*************** make_debug_insn_raw (rtx pattern)
*** 3703,3709 ****
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
--- 3703,3709 ----
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
*************** make_jump_insn_raw (rtx pattern)
*** 3723,3729 ****
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    JUMP_LABEL (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
--- 3723,3729 ----
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    JUMP_LABEL (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
*************** make_call_insn_raw (rtx pattern)
*** 3743,3749 ****
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    CALL_INSN_FUNCTION_USAGE (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
--- 3743,3749 ----
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    CALL_INSN_FUNCTION_USAGE (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;

    return insn;
*************** emit_pattern_after_setloc (rtx pattern,
*** 4416,4423 ****
    after = NEXT_INSN (after);
    while (1)
      {
!       if (active_insn_p (after) && !INSN_LOCATOR (after))
! 	INSN_LOCATOR (after) = loc;
        if (after == last)
  	break;
        after = NEXT_INSN (after);
--- 4416,4423 ----
    after = NEXT_INSN (after);
    while (1)
      {
!       if (active_insn_p (after) && !INSN_LOCATION (after))
! 	INSN_LOCATION (after) = loc;
        if (after == last)
  	break;
        after = NEXT_INSN (after);
*************** emit_pattern_after (rtx pattern, rtx aft
*** 4440,4501 ****
        prev = PREV_INSN (prev);

    if (INSN_P (prev))
!     return emit_pattern_after_setloc (pattern, after, INSN_LOCATOR (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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  rtx
  emit_debug_insn_after (rtx pattern, rtx after)
  {
--- 4440,4501 ----
        prev = PREV_INSN (prev);

    if (INSN_P (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_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_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_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_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_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_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_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_LOCATION according
to AFTER.  */
  rtx
  emit_debug_insn_after (rtx pattern, rtx after)
  {
*************** emit_pattern_before_setloc (rtx pattern,
*** 4525,4532 ****
      first = NEXT_INSN (first);
    while (1)
      {
!       if (active_insn_p (first) && !INSN_LOCATOR (first))
! 	INSN_LOCATOR (first) = loc;
        if (first == last)
  	break;
        first = NEXT_INSN (first);
--- 4525,4532 ----
      first = NEXT_INSN (first);
    while (1)
      {
!       if (active_insn_p (first) && !INSN_LOCATION (first))
! 	INSN_LOCATION (first) = loc;
        if (first == last)
  	break;
        first = NEXT_INSN (first);
*************** emit_pattern_before (rtx pattern, rtx be
*** 4550,4556 ****
        next = PREV_INSN (next);

    if (INSN_P (next))
!     return emit_pattern_before_setloc (pattern, before, INSN_LOCATOR (next),
  				       insnp, make_raw);
    else
      return emit_pattern_before_noloc (pattern, before,
--- 4550,4556 ----
        next = PREV_INSN (next);

    if (INSN_P (next))
!     return emit_pattern_before_setloc (pattern, before, INSN_LOCATION (next),
  				       insnp, make_raw);
    else
      return emit_pattern_before_noloc (pattern, before,
*************** emit_pattern_before (rtx pattern, rtx be
*** 4558,4564 ****
                                        NULL, make_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4558,4564 ----
                                        NULL, make_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_insn_before_setloc (rtx pattern, rt
*** 4566,4579 ****
  				     make_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR 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.  */
  rtx
  emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4566,4579 ----
  				     make_insn_raw);
  }

! /* 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_LOCATION according to LOC.  */
  rtx
  emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_jump_insn_before_setloc (rtx patter
*** 4581,4587 ****
  				     make_jump_insn_raw);
  }

! /* Like emit_jump_insn_before_noloc, but set INSN_LOCATOR according
to BEFORE.  */
  rtx
  emit_jump_insn_before (rtx pattern, rtx before)
  {
--- 4581,4587 ----
  				     make_jump_insn_raw);
  }

! /* Like emit_jump_insn_before_noloc, but set INSN_LOCATION according
to BEFORE.  */
  rtx
  emit_jump_insn_before (rtx pattern, rtx before)
  {
*************** emit_jump_insn_before (rtx pattern, rtx
*** 4589,4595 ****
  			      make_jump_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4589,4595 ----
  			      make_jump_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_call_insn_before_setloc (rtx patter
*** 4598,4604 ****
  }

  /* Like emit_call_insn_before_noloc,
!    but set insn_locator according to BEFORE.  */
  rtx
  emit_call_insn_before (rtx pattern, rtx before)
  {
--- 4598,4604 ----
  }

  /* Like emit_call_insn_before_noloc,
!    but set insn_location according to BEFORE.  */
  rtx
  emit_call_insn_before (rtx pattern, rtx before)
  {
*************** emit_call_insn_before (rtx pattern, rtx
*** 4606,4612 ****
  			      make_call_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4606,4612 ----
  			      make_call_insn_raw);
  }

! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_debug_insn_before_setloc (rtx patte
*** 4615,4621 ****
  }

  /* Like emit_debug_insn_before_noloc,
!    but set insn_locator according to BEFORE.  */
  rtx
  emit_debug_insn_before (rtx pattern, rtx before)
  {
--- 4615,4621 ----
  }

  /* Like emit_debug_insn_before_noloc,
!    but set insn_location according to BEFORE.  */
  rtx
  emit_debug_insn_before (rtx pattern, rtx before)
  {
*************** emit_copy_of_insn_after (rtx insn, rtx a
*** 5865,5871 ****
    /* Update LABEL_NUSES.  */
    mark_jump_label (PATTERN (new_rtx), new_rtx, 0);

!   INSN_LOCATOR (new_rtx) = INSN_LOCATOR (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,
--- 5865,5871 ----
    /* Update LABEL_NUSES.  */
    mark_jump_label (PATTERN (new_rtx), new_rtx, 0);

!   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,
*************** gen_hard_reg_clobber (enum machine_mode
*** 5900,6149 ****
  	    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;

  /* 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.  */
  void
! insn_locators_alloc (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);
!
    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)
! {
!   if (curr_rtl_loc >= 0)
!     epilogue_locator = curr_insn_locator ();
!   curr_rtl_loc = -1;
! }
!
! /* 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)
  {
-   /* 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)
  {
    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;
- }
- \f
-
- /* 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 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 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 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);
- }
- \f
-
  /* 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.  */
--- 5900,5965 ----
  	    gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
  }

! 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;

! /* Allocate insn location datastructure.  */
  void
! insn_locations_init (void)
  {
!   prologue_location = epilogue_location = 0;
    curr_location = UNKNOWN_LOCATION;
    last_location = UNKNOWN_LOCATION;
  }

  /* At the end of emit stage, clear current location.  */
  void
! insn_locations_finalize (void)
  {
!   epilogue_location = curr_location;
!   curr_location = UNKNOWN_LOCATION;
  }

  /* Set current location.  */
  void
! set_curr_insn_location (location_t location)
  {
    curr_location = location;
  }

  /* Get current location.  */
  location_t
! curr_insn_location (void)
  {
    return curr_location;
  }

  /* Return lexical scope block insn belongs to.  */
  tree
  insn_scope (const_rtx insn)
  {
!   return LOCATION_BLOCK (INSN_LOCATION (insn));
  }

  /* Return line number of the statement that produced this insn.  */
  int
  insn_line (const_rtx insn)
  {
!   return LOCATION_LINE (INSN_LOCATION (insn));
  }

  /* Return source file of the statement that produced this insn.  */
  const char *
  insn_file (const_rtx insn)
  {
!   return LOCATION_FILE (INSN_LOCATION (insn));
  }

  /* 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 190209)
--- gcc/cfgexpand.c	(working copy)
*************** gimple_assign_rhs_to_tree (gimple stmt)
*** 92,99 ****
  	   && gimple_location (stmt) != EXPR_LOCATION (t))
  	  || (gimple_block (stmt)
  	      && currently_expanding_to_rtl
! 	      && EXPR_P (t)
! 	      && gimple_block (stmt) != TREE_BLOCK (t)))
  	t = copy_node (t);
      }
    else
--- 92,98 ----
  	   && gimple_location (stmt) != EXPR_LOCATION (t))
  	  || (gimple_block (stmt)
  	      && currently_expanding_to_rtl
! 	      && EXPR_P (t)))
  	t = copy_node (t);
      }
    else
*************** gimple_assign_rhs_to_tree (gimple stmt)
*** 101,108 ****

    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;
  }
--- 100,105 ----
*************** expand_gimple_cond (basic_block bb, gimp
*** 1807,1814 ****
    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));

    /* These flags have no purpose in RTL land.  */
    true_edge->flags &= ~EDGE_TRUE_VALUE;
--- 1804,1810 ----
    last2 = last = get_last_insn ();

    extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
!   set_curr_insn_location (gimple_location (stmt));

    /* These flags have no purpose in RTL land.  */
    true_edge->flags &= ~EDGE_TRUE_VALUE;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1821,1833 ****
        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;
        false_edge->flags |= EDGE_FALLTHRU;
        maybe_cleanup_end_of_block (false_edge, last);
        return NULL;
--- 1817,1824 ----
        jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
  		true_edge->probability);
        maybe_dump_rtl_for_gimple_stmt (stmt, last);
!       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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1837,1849 ****
        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;
        true_edge->flags |= EDGE_FALLTHRU;
        maybe_cleanup_end_of_block (true_edge, last);
        return NULL;
--- 1828,1835 ----
        jumpifnot_1 (code, op0, op1, label_rtx_for_bb (false_edge->dest),
  		   false_edge->probability);
        maybe_dump_rtl_for_gimple_stmt (stmt, last);
!       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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1852,1864 ****
    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;
    emit_jump (label_rtx_for_bb (false_edge->dest));

    BB_END (bb) = last;
--- 1838,1845 ----
    jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
  	    true_edge->probability);
    last = get_last_insn ();
!   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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1883,1895 ****

    maybe_dump_rtl_for_gimple_stmt (stmt, last2);

!   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;

    return new_bb;
  }
--- 1864,1874 ----

    maybe_dump_rtl_for_gimple_stmt (stmt, last2);

!   if (!IS_UNKNOWN_LOCATION (true_edge->goto_locus))
      {
!       set_curr_insn_location (true_edge->goto_locus);
!       true_edge->goto_locus = curr_insn_location ();
      }

    return new_bb;
  }
*************** expand_call_stmt (gimple stmt)
*** 1989,1995 ****
      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))
--- 1968,1973 ----
*************** expand_gimple_stmt_1 (gimple stmt)
*** 2024,2031 ****
  {
    tree op0;

!   set_curr_insn_source_location (gimple_location (stmt));
!   set_curr_insn_block (gimple_block (stmt));

    switch (gimple_code (stmt))
      {
--- 2002,2008 ----
  {
    tree op0;

!   set_curr_insn_location (gimple_location (stmt));

    switch (gimple_code (stmt))
      {
*************** expand_gimple_basic_block (basic_block b
*** 3769,3776 ****
  	  tree op;
  	  gimple def;

! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();

  	  /* Look for SSA names that have their last use here (TERed
  	     names always have only one real use).  */
--- 3746,3752 ----
  	  tree op;
  	  gimple def;

! 	  location_t sloc = curr_insn_location ();

  	  /* Look for SSA names that have their last use here (TERed
  	     names always have only one real use).  */
*************** expand_gimple_basic_block (basic_block b
*** 3803,3810 ****
  		    rtx val;
  		    enum machine_mode mode;

! 		    set_curr_insn_source_location (gimple_location (def));
! 		    set_curr_insn_block (gimple_block (def));

  		    DECL_ARTIFICIAL (vexpr) = 1;
  		    TREE_TYPE (vexpr) = TREE_TYPE (value);
--- 3779,3785 ----
  		    rtx val;
  		    enum machine_mode mode;

! 		    set_curr_insn_location (gimple_location (def));

  		    DECL_ARTIFICIAL (vexpr) = 1;
  		    TREE_TYPE (vexpr) = TREE_TYPE (value);
*************** expand_gimple_basic_block (basic_block b
*** 3831,3838 ****
  		      }
  		  }
  	      }
! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}

        currently_expanding_gimple_stmt = stmt;
--- 3806,3812 ----
  		      }
  		  }
  	      }
! 	  set_curr_insn_location (sloc);
  	}

        currently_expanding_gimple_stmt = stmt;
*************** expand_gimple_basic_block (basic_block b
*** 3847,3854 ****
  	}
        else if (gimple_debug_bind_p (stmt))
  	{
! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();
  	  gimple_stmt_iterator nsi = gsi;

  	  for (;;)
--- 3821,3827 ----
  	}
        else if (gimple_debug_bind_p (stmt))
  	{
! 	  location_t sloc = curr_insn_location ();
  	  gimple_stmt_iterator nsi = gsi;

  	  for (;;)
*************** expand_gimple_basic_block (basic_block b
*** 3870,3877 ****

  	      last = get_last_insn ();

! 	      set_curr_insn_source_location (gimple_location (stmt));
! 	      set_curr_insn_block (gimple_block (stmt));

  	      if (DECL_P (var))
  		mode = DECL_MODE (var);
--- 3843,3849 ----

  	      last = get_last_insn ();

! 	      set_curr_insn_location (gimple_location (stmt));

  	      if (DECL_P (var))
  		mode = DECL_MODE (var);
*************** expand_gimple_basic_block (basic_block b
*** 3909,3921 ****
  		break;
  	    }

! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}
        else if (gimple_debug_source_bind_p (stmt))
  	{
! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();
  	  tree var = gimple_debug_source_bind_get_var (stmt);
  	  tree value = gimple_debug_source_bind_get_value (stmt);
  	  rtx val;
--- 3881,3891 ----
  		break;
  	    }

! 	  set_curr_insn_location (sloc);
  	}
        else if (gimple_debug_source_bind_p (stmt))
  	{
! 	  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;
*************** expand_gimple_basic_block (basic_block b
*** 3923,3930 ****

  	  last = get_last_insn ();

! 	  set_curr_insn_source_location (gimple_location (stmt));
! 	  set_curr_insn_block (gimple_block (stmt));

  	  mode = DECL_MODE (var);

--- 3893,3899 ----

  	  last = get_last_insn ();

! 	  set_curr_insn_location (gimple_location (stmt));

  	  mode = DECL_MODE (var);

*************** expand_gimple_basic_block (basic_block b
*** 3942,3949 ****
  	      PAT_VAR_LOCATION_LOC (val) = (rtx)value;
  	    }

! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}
        else
  	{
--- 3911,3917 ----
  	      PAT_VAR_LOCATION_LOC (val) = (rtx)value;
  	    }

! 	  set_curr_insn_location (sloc);
  	}
        else
  	{
*************** expand_gimple_basic_block (basic_block b
*** 3984,3996 ****
    /* 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 ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb)
  	{
  	  emit_jump (label_rtx_for_bb (e->dest));
--- 3952,3959 ----
    /* Expand implicit goto and convert goto_locus.  */
    FOR_EACH_EDGE (e, ei, bb->succs)
      {
!       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));
*************** construct_exit_block (void)
*** 4110,4121 ****

    /* 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)
      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 ();

--- 4073,4081 ----

    /* Make sure the locus is set to the end of the function, so that
       epilogue line numbers and warnings are set properly.  */
!   if (!IS_UNKNOWN_LOCATION (cfun->function_end_locus))
      input_location = cfun->function_end_locus;

    /* Generate rtl for function exit.  */
    expand_function_end ();

*************** gimple_expand_cfg (void)
*** 4334,4353 ****

    rtl_profile_for_bb (ENTRY_BLOCK_PTR);

!   insn_locators_alloc ();
    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
           (DECL_SOURCE_LOCATION (current_function_decl));
        else
!        set_curr_insn_source_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 ();

  #ifdef INSN_SCHEDULING
    init_sched_attrs ();
--- 4294,4312 ----

    rtl_profile_for_bb (ENTRY_BLOCK_PTR);

!   insn_locations_init ();
    if (!DECL_IS_BUILTIN (current_function_decl))
      {
        /* Eventually, all FEs should explicitly set function_start_locus.  */
!       if (IS_UNKNOWN_LOCATION (cfun->function_start_locus))
!        set_curr_insn_location
           (DECL_SOURCE_LOCATION (current_function_decl));
        else
!        set_curr_insn_location (cfun->function_start_locus);
      }
    else
!     set_curr_insn_location (UNKNOWN_LOCATION);
!   prologue_location = curr_insn_location ();

  #ifdef INSN_SCHEDULING
    init_sched_attrs ();
*************** gimple_expand_cfg (void)
*** 4517,4524 ****
    free_histograms ();

    construct_exit_block ();
!   set_curr_insn_block (DECL_INITIAL (current_function_decl));
!   insn_locators_finalize ();

    /* Zap the tree EH table.  */
    set_eh_throw_stmt_table (cfun, NULL);
--- 4476,4482 ----
    free_histograms ();

    construct_exit_block ();
!   insn_locations_finalize ();

    /* Zap the tree EH table.  */
    set_eh_throw_stmt_table (cfun, NULL);
Index: gcc/cfgcleanup.c
===================================================================
*** gcc/cfgcleanup.c	(revision 190209)
--- gcc/cfgcleanup.c	(working copy)
*************** try_forward_edges (int mode, basic_block
*** 481,493 ****
  		  int new_locus = single_succ_edge (target)->goto_locus;
  		  int locus = goto_locus;

! 		  if (new_locus && locus && !locator_eq (new_locus, locus))
  		    new_target = NULL;
  		  else
  		    {
  		      rtx last;

! 		      if (new_locus)
  			locus = new_locus;

  		      last = BB_END (target);
--- 481,495 ----
  		  int new_locus = single_succ_edge (target)->goto_locus;
  		  int locus = goto_locus;

! 		  if (!IS_UNKNOWN_LOCATION (new_locus)
! 		      && !IS_UNKNOWN_LOCATION (locus)
! 		      && new_locus != locus)
  		    new_target = NULL;
  		  else
  		    {
  		      rtx last;

! 		      if (!IS_UNKNOWN_LOCATION (new_locus))
  			locus = new_locus;

  		      last = BB_END (target);
*************** try_forward_edges (int mode, basic_block
*** 495,507 ****
  			last = prev_nondebug_insn (last);

  		      new_locus = last && INSN_P (last)
! 				  ? INSN_LOCATOR (last) : 0;

! 		      if (new_locus && locus && !locator_eq (new_locus, locus))
  			new_target = NULL;
  		      else
  			{
! 			  if (new_locus)
  			    locus = new_locus;

  			  goto_locus = locus;
--- 497,511 ----
  			last = prev_nondebug_insn (last);

  		      new_locus = last && INSN_P (last)
! 				  ? INSN_LOCATION (last) : 0;

! 		      if (!IS_UNKNOWN_LOCATION (new_locus)
! 			  && !IS_UNKNOWN_LOCATION (locus)
! 			  && new_locus != locus)
  			new_target = NULL;
  		      else
  			{
! 			  if (!IS_UNKNOWN_LOCATION (new_locus))
  			    locus = new_locus;

  			  goto_locus = locus;
Index: gcc/tree-ssa-live.c
===================================================================
*** gcc/tree-ssa-live.c	(revision 190209)
--- gcc/tree-ssa-live.c	(working copy)
*************** remove_unused_scope_block_p (tree scope)
*** 585,591 ****
     else
     /* Verfify that only blocks with source location set
        are entry points to the inlined functions.  */
!      gcc_assert (BLOCK_SOURCE_LOCATION (scope) == UNKNOWN_LOCATION);

     TREE_USED (scope) = !unused;
     return unused;
--- 585,591 ----
     else
     /* Verfify that only blocks with source location set
        are entry points to the inlined functions.  */
!      gcc_assert (IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (scope)));

     TREE_USED (scope) = !unused;
     return unused;
*************** dump_scope_block (FILE *file, int indent
*** 613,619 ****
    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)
      {
        expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (scope));
        fprintf (file, " %s:%i", s.file, s.line);
--- 613,619 ----
    fprintf (file, "\n%*s{ Scope block #%i%s%s",indent, "" ,
BLOCK_NUMBER (scope),
    	   TREE_USED (scope) ? "" : " (unused)",
  	   BLOCK_ABSTRACT (scope) ? " (abstract)": "");
!   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);
*************** remove_unused_locals (void)
*** 746,758 ****
            FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_ALL_USES)
              {
  	      tree arg = USE_FROM_PTR (arg_p);
  	      mark_all_vars_used (&arg);
              }
          }

        FOR_EACH_EDGE (e, ei, bb->succs)
  	if (e->goto_locus)
! 	  TREE_USED (e->goto_block) = true;
      }

    /* We do a two-pass approach about the out-of-scope clobbers.  We want
--- 746,763 ----
            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 (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 190209)
--- gcc/lto/lto.c	(working copy)
*************** lto_fixup_prevailing_decls (tree t)
*** 1603,1609 ****
    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));
      }
--- 1603,1608 ----
Index: gcc/tree-streamer-out.c
===================================================================
*** gcc/tree-streamer-out.c	(revision 190209)
--- gcc/tree-streamer-out.c	(working copy)
*************** write_ts_decl_minimal_tree_pointers (str
*** 471,477 ****
  {
    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));
  }


--- 471,477 ----
  {
    stream_write_tree (ob, DECL_NAME (expr), ref_p);
    stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
!   lto_output_location (ob, LOCATION_LOCUS (DECL_SOURCE_LOCATION (expr)));
  }


*************** write_ts_exp_tree_pointers (struct outpu
*** 668,674 ****
    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));
    stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
  }

--- 668,674 ----
    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, LOCATION_LOCUS (EXPR_LOCATION (expr)));
    stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
  }

Index: gcc/rtl.c
===================================================================
*** gcc/rtl.c	(revision 190209)
--- gcc/rtl.c	(working copy)
*************** rtx_equal_p_cb (const_rtx x, const_rtx y
*** 440,446 ****
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && locator_eq (XINT (x, i), XINT (y, i)))
  		break;
  #endif
  	      return 0;
--- 440,446 ----
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && XINT (x, i) == XINT (y, i))
  		break;
  #endif
  	      return 0;
*************** rtx_equal_p (const_rtx x, const_rtx y)
*** 579,585 ****
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && locator_eq (XINT (x, i), XINT (y, i)))
  		break;
  #endif
  	      return 0;
--- 579,585 ----
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && XINT (x, i) == XINT (y, i))
  		break;
  #endif
  	      return 0;
Index: gcc/rtl.h
===================================================================
*** gcc/rtl.h	(revision 190209)
--- gcc/rtl.h	(working copy)
*************** extern void rtl_check_failed_flag (const
*** 747,752 ****
--- 747,753 ----
  #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)
*************** extern void rtl_check_failed_flag (const
*** 810,822 ****
  /* The body of an insn.  */
  #define PATTERN(INSN)	XEXP (INSN, 4)

! #define INSN_LOCATOR(INSN) XINT (INSN, 5)
  /* 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 ()))

  /* Code number of instruction, from when it was recognized.
     -1 means this instruction has not been recognized yet.  */
--- 811,823 ----
  /* The body of an insn.  */
  #define PATTERN(INSN)	XEXP (INSN, 4)

! #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) ? \
! 			 INSN_LOCATION (X) : UNKNOWN_LOCATION)

  /* Code number of instruction, from when it was recognized.
     -1 means this instruction has not been recognized yet.  */
*************** extern rtx prev_cc0_setter (rtx);
*** 1815,1826 ****
  /* 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);

  /* In jump.c */
  extern enum rtx_code reverse_condition (enum rtx_code);
--- 1816,1823 ----
  /* In emit-rtl.c  */
  extern int insn_line (const_rtx);
  extern const char * insn_file (const_rtx);
  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);
*************** extern const struct rtl_hooks general_rt
*** 2657,2670 ****
  /* 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 bool optimize_insn_for_size_p (void);
  extern bool optimize_insn_for_speed_p (void);

--- 2654,2663 ----
  /* Keep this for the nonce.  */
  #define gen_lowpart rtl_hooks.gen_lowpart

! 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 190209)
--- gcc/tree-inline.c	(working copy)
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 799,808 ****
        /* 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);
--- 799,804 ----
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 840,852 ****
  	{
  	  /* 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.  */
  	  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,
--- 836,844 ----
  	{
  	  /* Variable substitution need not be simple.  In particular,
  	     the MEM_REF substitution above.  Make sure that
! 	     TREE_CONSTANT and friends are up-to-date.  */
  	  int invariant = is_gimple_min_invariant (*tp);
  	  walk_tree (&TREE_OPERAND (*tp, 0), remap_gimple_op_r, data, NULL);
  	  recompute_tree_invariant_for_addr_expr (*tp);

  	  /* If this used to be invariant, but is not any longer,
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 858,863 ****
--- 850,871 ----
  	}
      }

+   /* 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;
  }
*************** copy_tree_body_r (tree *tp, int *walk_su
*** 1075,1085 ****
  	      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;
  	}

        if (TREE_CODE (*tp) != OMP_CLAUSE)
--- 1083,1092 ----
  	      tree *n;
  	      n = (tree *) pointer_map_contains (id->decl_map,
  						 TREE_BLOCK (*tp));
  	      if (n)
  		new_block = *n;
  	    }
! 	  TREE_SET_BLOCK (*tp, new_block);
  	}

        if (TREE_CODE (*tp) != OMP_CLAUSE)
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 1949,1954 ****
--- 1956,1962 ----
  	      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
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 1960,1968 ****

  	      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.  */
--- 1968,1974 ----
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 1975,1982 ****
  		  gsi_insert_seq_on_edge (new_edge, stmts);
  		  inserted = true;
  		}
  	      add_phi_arg (new_phi, new_arg, new_edge,
! 			   gimple_phi_arg_location_from_edge (phi, old_edge));
  	    }
  	}
      }
--- 1981,1999 ----
  		  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,
! 			   COMBINE_LOCATION_DATA (locus, block));
  	    }
  	}
      }
*************** expand_call_inline (basic_block bb, gimp
*** 3847,3853 ****
    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);

    /* Local declarations will be replaced by their equivalents in this
       map.  */
--- 3864,3871 ----
    id->block = make_node (BLOCK);
    BLOCK_ABSTRACT_ORIGIN (id->block) = fn;
    BLOCK_SOURCE_LOCATION (id->block) = input_location;
!   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 190209)
--- gcc/tree-streamer-in.c	(working copy)
*************** lto_input_ts_exp_tree_pointers (struct l
*** 776,782 ****

    loc = lto_input_location (ib, data_in);
    SET_EXPR_LOCATION (expr, loc);
!   TREE_BLOCK (expr) = stream_read_tree (ib, data_in);
  }


--- 776,782 ----

    loc = lto_input_location (ib, data_in);
    SET_EXPR_LOCATION (expr, loc);
!   TREE_SET_BLOCK (expr, stream_read_tree (ib, data_in));
  }


Index: gcc/combine.c
===================================================================
*** gcc/combine.c	(revision 190209)
--- gcc/combine.c	(working copy)
*************** try_combine (rtx i3, rtx i2, rtx i1, rtx
*** 2741,2747 ****

  	  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);

  	  SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
  	  SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
--- 2741,2747 ----

  	  i1 = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
  			     BLOCK_FOR_INSN (i2), XVECEXP (PATTERN (i2), 0, 1),
! 			     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 190209)
--- gcc/tree-outof-ssa.c	(working copy)
*************** set_location_for_edge (edge e)
*** 108,115 ****
  {
    if (e->goto_locus)
      {
!       set_curr_insn_source_location (e->goto_locus);
!       set_curr_insn_block (e->goto_block);
      }
    else
      {
--- 108,114 ----
  {
    if (e->goto_locus)
      {
!       set_curr_insn_location (e->goto_locus);
      }
    else
      {
*************** set_location_for_edge (edge e)
*** 125,132 ****
  		continue;
  	      if (gimple_has_location (stmt) || gimple_block (stmt))
  		{
! 		  set_curr_insn_source_location (gimple_location (stmt));
! 		  set_curr_insn_block (gimple_block (stmt));
  		  return;
  		}
  	    }
--- 124,130 ----
  		continue;
  	      if (gimple_has_location (stmt) || gimple_block (stmt))
  		{
! 		  set_curr_insn_location (gimple_location (stmt));
  		  return;
  		}
  	    }
*************** insert_partition_copy_on_edge (edge e, i
*** 191,197 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);

    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (SA.partition_to_pseudo[dest],
--- 189,195 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_location (locus);

    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (SA.partition_to_pseudo[dest],
*************** insert_value_copy_on_edge (edge e, int d
*** 228,234 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);

    start_sequence ();

--- 226,232 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_location (locus);

    start_sequence ();

*************** insert_rtx_to_part_on_edge (edge e, int
*** 284,290 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_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
--- 282,288 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (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
*************** insert_part_to_rtx_on_edge (edge e, rtx
*** 320,326 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);

    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (dest,
--- 318,324 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (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 190209)
--- gcc/basic-block.h	(working copy)
*************** struct GTY(()) edge_def {
*** 47,54 ****
    /* Auxiliary info specific to a pass.  */
    PTR GTY ((skip (""))) aux;

!   /* Location of any goto implicit in the edge and associated BLOCK.  */
!   tree goto_block;
    location_t goto_locus;

    /* The index number corresponding to this edge in the edge vector
--- 47,53 ----
    /* Auxiliary info specific to a pass.  */
    PTR GTY ((skip (""))) aux;

!   /* 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 190209)
--- gcc/gimple.h	(working copy)
*************** struct GTY(()) gimple_statement_base {
*** 210,219 ****
       and the prev pointer being the last.  */
    gimple next;
    gimple GTY((skip)) prev;
-
-   /* [ WORD 6 ]
-      Lexical block holding this statement.  */
-   tree block;
  };


--- 210,215 ----
*************** gimple_bb (const_gimple g)
*** 1198,1204 ****
  static inline tree
  gimple_block (const_gimple g)
  {
!   return g->gsbase.block;
  }


--- 1194,1200 ----
  static inline tree
  gimple_block (const_gimple g)
  {
!   return LOCATION_BLOCK (g->gsbase.location);
  }


*************** gimple_block (const_gimple g)
*** 1207,1213 ****
  static inline void
  gimple_set_block (gimple g, tree block)
  {
!   g->gsbase.block = block;
  }


--- 1203,1209 ----
  static inline void
  gimple_set_block (gimple g, tree block)
  {
!   g->gsbase.location = COMBINE_LOCATION_DATA (g->gsbase.location, block);
  }


*************** gimple_set_location (gimple g, location_
*** 1242,1248 ****
  static inline bool
  gimple_has_location (const_gimple g)
  {
!   return gimple_location (g) != UNKNOWN_LOCATION;
  }


--- 1238,1244 ----
  static inline bool
  gimple_has_location (const_gimple g)
  {
!   return !IS_UNKNOWN_LOCATION (gimple_location (g));
  }


Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c	(revision 190209)
--- gcc/tree-cfg.c	(working copy)
*************** make_cond_expr_edges (basic_block bb)
*** 809,823 ****
    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.  */
--- 809,819 ----
*************** make_goto_expr_edges (basic_block bb)
*** 1027,1034 ****
        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;
      }
--- 1023,1028 ----
*************** gimple_can_merge_blocks_p (basic_block a
*** 1504,1510 ****

    /* When not optimizing, don't merge if we'd lose goto_locus.  */
    if (!optimize
!       && single_succ_edge (a)->goto_locus != UNKNOWN_LOCATION)
      {
        location_t goto_locus = single_succ_edge (a)->goto_locus;
        gimple_stmt_iterator prev, next;
--- 1498,1504 ----

    /* When not optimizing, don't merge if we'd lose goto_locus.  */
    if (!optimize
!       && single_succ_edge (a)->goto_locus)
      {
        location_t goto_locus = single_succ_edge (a)->goto_locus;
        gimple_stmt_iterator prev, next;
*************** move_stmt_op (tree *tp, int *walk_subtre
*** 5993,6001 ****
    tree t = *tp;

    if (EXPR_P (t))
!     /* We should never have TREE_BLOCK set on non-statements.  */
!     gcc_assert (!TREE_BLOCK (t));
!
    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
      {
        if (TREE_CODE (t) == SSA_NAME)
--- 5987,5993 ----
    tree t = *tp;

    if (EXPR_P (t))
!     ;
    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
      {
        if (TREE_CODE (t) == SSA_NAME)
*************** move_block_to_fn (struct function *dest_
*** 6295,6306 ****
      }

    FOR_EACH_EDGE (e, ei, bb->succs)
!     if (e->goto_locus)
        {
! 	tree block = e->goto_block;
  	if (d->orig_block == NULL_TREE
  	    || block == d->orig_block)
! 	  e->goto_block = d->new_block;
  #ifdef ENABLE_CHECKING
  	else if (block != d->new_block)
  	  {
--- 6287,6298 ----
      }

    FOR_EACH_EDGE (e, ei, bb->succs)
!     if (!IS_UNKNOWN_LOCATION (e->goto_locus))
        {
! 	tree block = LOCATION_BLOCK (e->goto_locus);
  	if (d->orig_block == NULL_TREE
  	    || block == d->orig_block)
! 	  e->goto_locus = COMBINE_LOCATION_DATA (e->goto_locus, d->new_block);
  #ifdef ENABLE_CHECKING
  	else if (block != d->new_block)
  	  {
Index: gcc/config/alpha/alpha.c
===================================================================
*** gcc/config/alpha/alpha.c	(revision 190209)
--- gcc/config/alpha/alpha.c	(working copy)
*************** alpha_output_mi_thunk_osf (FILE *file, t
*** 8362,8368 ****
       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);
--- 8362,8367 ----
Index: gcc/config/sparc/sparc.c
===================================================================
*** gcc/config/sparc/sparc.c	(revision 190209)
--- gcc/config/sparc/sparc.c	(working copy)
*************** sparc_output_mi_thunk (FILE *file, tree
*** 10654,10660 ****
       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);
--- 10654,10659 ----
Index: gcc/config/i386/i386.c
===================================================================
*** gcc/config/i386/i386.c	(revision 190209)
--- gcc/config/i386/i386.c	(working copy)
*************** x86_output_mi_thunk (FILE *file,
*** 33227,33233 ****
    /* 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);
--- 33227,33232 ----
Index: gcc/config/tilegx/tilegx.c
===================================================================
*** gcc/config/tilegx/tilegx.c	(revision 190209)
--- gcc/config/tilegx/tilegx.c	(working copy)
*************** tilegx_output_mi_thunk (FILE *file, tree
*** 4804,4810 ****
       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);
--- 4804,4809 ----
Index: gcc/config/sh/sh.c
===================================================================
*** gcc/config/sh/sh.c	(revision 190209)
--- gcc/config/sh/sh.c	(working copy)
*************** sh_output_mi_thunk (FILE *file, tree thu
*** 11991,11997 ****
       the insns emitted.  Note that use_thunk calls
       assemble_start_function and assemble_end_function.  */

-   insn_locators_alloc ();
    insns = get_insns ();

    if (optimize > 0)
--- 11991,11996 ----
Index: gcc/config/ia64/ia64.c
===================================================================
*** gcc/config/ia64/ia64.c	(revision 190209)
--- gcc/config/ia64/ia64.c	(working copy)
*************** ia64_output_mi_thunk (FILE *file, tree t
*** 10848,10854 ****
       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);
--- 10848,10853 ----
Index: gcc/config/rs6000/rs6000.c
===================================================================
*** gcc/config/rs6000/rs6000.c	(revision 190209)
--- gcc/config/rs6000/rs6000.c	(working copy)
*************** rs6000_output_mi_thunk (FILE *file, tree
*** 21689,21695 ****
       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);
--- 21689,21694 ----
Index: gcc/config/score/score.c
===================================================================
*** gcc/config/score/score.c	(revision 190209)
--- gcc/config/score/score.c	(working copy)
*************** score_output_mi_thunk (FILE *file, tree
*** 505,511 ****
    /* 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);
--- 505,510 ----
Index: gcc/config/tilepro/tilepro.c
===================================================================
*** gcc/config/tilepro/tilepro.c	(revision 190209)
--- gcc/config/tilepro/tilepro.c	(working copy)
*************** tilepro_asm_output_mi_thunk (FILE *file,
*** 4407,4413 ****
       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);
--- 4407,4412 ----
Index: gcc/config/mips/mips.c
===================================================================
*** gcc/config/mips/mips.c	(revision 190209)
--- gcc/config/mips/mips.c	(working copy)
*************** mips_output_mi_thunk (FILE *file, tree t
*** 15746,15752 ****
    /* 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);
--- 15746,15751 ----
Index: gcc/cfgrtl.c
===================================================================
*** gcc/cfgrtl.c	(revision 190209)
--- gcc/cfgrtl.c	(working copy)
*************** rtl_split_block (basic_block bb, void *i
*** 720,738 ****
  static bool
  unique_locus_on_edge_between_p (basic_block a, basic_block b)
  {
!   const int goto_locus = EDGE_SUCC (a, 0)->goto_locus;
    rtx insn, end;

!   if (!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))
      insn = PREV_INSN (insn);

!   if (insn != end && locator_eq (INSN_LOCATOR (insn), goto_locus))
      return false;

    /* Then scan block B forward.  */
--- 720,738 ----
  static bool
  unique_locus_on_edge_between_p (basic_block a, basic_block b)
  {
!   const location_t goto_locus = EDGE_SUCC (a, 0)->goto_locus;
    rtx insn, end;

!   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_HAS_LOCATION (insn)))
      insn = PREV_INSN (insn);

!   if (insn != end && INSN_LOCATION (insn) == goto_locus)
      return false;

    /* Then scan block B forward.  */
*************** unique_locus_on_edge_between_p (basic_bl
*** 743,750 ****
        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))
  	return false;
      }

--- 743,750 ----
        while (insn != end && !NONDEBUG_INSN_P (insn))
  	insn = NEXT_INSN (insn);

!       if (insn != end && INSN_HAS_LOCATION (insn)
! 	  && INSN_LOCATION (insn) == goto_locus)
  	return false;
      }

*************** emit_nop_for_unique_locus_between (basic
*** 761,767 ****
      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;
  }

  /* Blocks A and B are to be merged into a single block A.  The insns
--- 761,767 ----
      return;

    BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
!   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
*************** force_nonfallthru_and_redirect (edge e,
*** 1478,1484 ****
    else
      jump_block = e->src;

!   if (e->goto_locus && e->goto_block == NULL)
      loc = e->goto_locus;
    else
      loc = 0;
--- 1478,1484 ----
    else
      jump_block = e->src;

!   if (!IS_UNKNOWN_LOCATION (e->goto_locus))
      loc = e->goto_locus;
    else
      loc = 0;
*************** fixup_reorder_chain (void)
*** 3336,3342 ****
          edge_iterator ei;

          FOR_EACH_EDGE (e, ei, bb->succs)
! 	  if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
  	    {
  	      edge e2;
  	      edge_iterator ei2;
--- 3336,3343 ----
          edge_iterator ei;

          FOR_EACH_EDGE (e, ei, bb->succs)
! 	  if (!IS_UNKNOWN_LOCATION (e->goto_locus)
! 	      && !(e->flags & EDGE_ABNORMAL))
  	    {
  	      edge e2;
  	      edge_iterator ei2;
*************** fixup_reorder_chain (void)
*** 3346,3360 ****
  	      insn = BB_END (e->src);
  	      end = PREV_INSN (BB_HEAD (e->src));
  	      while (insn != end
! 		     && (!NONDEBUG_INSN_P (insn) || INSN_LOCATOR (insn) == 0))
  		insn = PREV_INSN (insn);
  	      if (insn != end
! 		  && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
  		continue;
  	      if (simplejump_p (BB_END (e->src))
! 		  && INSN_LOCATOR (BB_END (e->src)) == 0)
  		{
! 		  INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
  		  continue;
  		}
  	      dest = e->dest;
--- 3347,3361 ----
  	      insn = BB_END (e->src);
  	      end = PREV_INSN (BB_HEAD (e->src));
  	      while (insn != end
! 		     && (!NONDEBUG_INSN_P (insn) || !INSN_HAS_LOCATION (insn)))
  		insn = PREV_INSN (insn);
  	      if (insn != end
! 		  && INSN_LOCATION (insn) == e->goto_locus)
  		continue;
  	      if (simplejump_p (BB_END (e->src))
! 		  && !INSN_HAS_LOCATION (BB_END (e->src)))
  		{
! 		  INSN_LOCATION (BB_END (e->src)) = e->goto_locus;
  		  continue;
  		}
  	      dest = e->dest;
*************** fixup_reorder_chain (void)
*** 3370,3393 ****
  		  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))
  		    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;

  	      /* 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
  		    && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
! 		    && locator_eq (e->goto_locus, e2->goto_locus))
  		  redirect_edge_and_branch (e2, nb);
  		else
  		  ei_next (&ei2);
--- 3371,3394 ----
  		  end = NEXT_INSN (BB_END (dest));
  		  while (insn != end && !NONDEBUG_INSN_P (insn))
  		    insn = NEXT_INSN (insn);
! 		  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_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 (!IS_UNKNOWN_LOCATION (e2->goto_locus)
  		    && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
! 		    && e->goto_locus == e2->goto_locus)
  		  redirect_edge_and_branch (e2, nb);
  		else
  		  ei_next (&ei2);
*************** cfg_layout_merge_blocks (basic_block a,
*** 4087,4093 ****
      }

    /* If B was a forwarder block, propagate the locus on the edge.  */
!   if (forwarder_p && !EDGE_SUCC (b, 0)->goto_locus)
      EDGE_SUCC (b, 0)->goto_locus = EDGE_SUCC (a, 0)->goto_locus;

    if (dump_file)
--- 4088,4094 ----
      }

    /* If B was a forwarder block, propagate the locus on the edge.  */
!   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 190209)
--- gcc/stmt.c	(working copy)
*************** emit_case_nodes (rtx index, case_node_pt
*** 2397,2403 ****
  		 then emit the code for one side at a time.  */

  	      tree test_label
! 		= build_decl (CURR_INSN_LOCATION,
  			      LABEL_DECL, NULL_TREE, NULL_TREE);

  	      /* See if the value is on the right.  */
--- 2397,2403 ----
  		 then emit the code for one side at a time.  */

  	      tree test_label
! 		= build_decl (curr_insn_location (),
  			      LABEL_DECL, NULL_TREE, NULL_TREE);

  	      /* See if the value is on the right.  */
*************** emit_case_nodes (rtx index, case_node_pt
*** 2521,2527 ****
  	      /* Right hand node requires testing.
  		 Branch to a label where we will handle it later.  */

! 	      test_label = build_decl (CURR_INSN_LOCATION,
  				       LABEL_DECL, NULL_TREE, NULL_TREE);
  	      emit_cmp_and_jump_insns (index,
  				       convert_modes
--- 2521,2527 ----
  	      /* Right hand node requires testing.
  		 Branch to a label where we will handle it later.  */

! 	      test_label = build_decl (curr_insn_location (),
  				       LABEL_DECL, NULL_TREE, NULL_TREE);
  	      emit_cmp_and_jump_insns (index,
  				       convert_modes
Index: libcpp/line-map.c
===================================================================
*** libcpp/line-map.c	(revision 190209)
--- libcpp/line-map.c	(working copy)
*************** along with this program; see the file CO
*** 25,30 ****
--- 25,31 ----
  #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 *,
*************** static source_location linemap_macro_loc
*** 50,55 ****
--- 51,185 ----
  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 map it to a new unsigned integer, and replace it with 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 to 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
*************** linemap_position_for_line_and_column (st
*** 509,514 ****
--- 639,646 ----
  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);
*************** linemap_ordinary_map_lookup (struct line
*** 525,530 ****
--- 657,665 ----
    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;

*************** linemap_macro_map_lookup (struct line_ma
*** 570,575 ****
--- 705,713 ----
    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)
*************** linemap_macro_map_loc_to_def_point (cons
*** 648,653 ****
--- 786,794 ----
  {
    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);
*************** linemap_macro_map_loc_unwind_toward_spel
*** 672,677 ****
--- 813,821 ----
  {
    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);
*************** linemap_get_expansion_line (struct line_
*** 696,701 ****
--- 840,848 ----
  {
    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;

*************** linemap_get_expansion_filename (struct l
*** 720,725 ****
--- 867,875 ----
  {
    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;

*************** linemap_location_in_system_header_p (str
*** 754,759 ****
--- 904,912 ----
  {
    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;

*************** bool
*** 793,798 ****
--- 946,954 ----
  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)));
*************** linemap_macro_loc_to_spelling_point (str
*** 933,938 ****
--- 1089,1097 ----
  {
    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)
*************** linemap_macro_loc_to_def_point (struct l
*** 967,972 ****
--- 1126,1134 ----
  {
    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)
*************** linemap_macro_loc_to_exp_point (struct l
*** 1005,1010 ****
--- 1167,1175 ----
  {
    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)
*************** linemap_resolve_location (struct line_ma
*** 1074,1079 ****
--- 1239,1247 ----
  			  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
*************** linemap_unwind_toward_expansion (struct
*** 1121,1126 ****
--- 1289,1297 ----
    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);
*************** linemap_unwind_to_first_non_reserved_loc
*** 1157,1162 ****
--- 1328,1336 ----
    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;
*************** linemap_expand_location (struct line_map
*** 1198,1203 ****
--- 1372,1382 ----
    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.
*************** linemap_dump_location (struct line_maps
*** 1290,1295 ****
--- 1469,1477 ----
    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;

Index: libcpp/include/line-map.h
===================================================================
*** libcpp/include/line-map.h	(revision 190209)
--- libcpp/include/line-map.h	(working copy)
*************** struct GTY(()) line_map_ordinary {
*** 89,95 ****

  /* This is the highest possible source location encoded within an
     ordinary or macro map.  */
! #define MAX_SOURCE_LOCATION 0xFFFFFFFF

  struct cpp_hashnode;

--- 89,95 ----

  /* This is the highest possible source location encoded within an
     ordinary or macro map.  */
! #define MAX_SOURCE_LOCATION 0x7FFFFFFF

  struct cpp_hashnode;

*************** struct GTY(()) line_maps {
*** 408,413 ****
--- 408,423 ----
  #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 *);

*************** typedef struct
*** 594,599 ****
--- 604,611 ----

    int column;

+   void *data;
+
    /* In a system header?. */
    bool sysp;
  } expanded_location;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-14  4:58               ` Dehao Chen
@ 2012-08-14  7:56                 ` Dodji Seketeli
  2012-08-14 17:13                   ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Dodji Seketeli @ 2012-08-14  7:56 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Richard Guenther, gcc-patches, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey, Jason Merrill

Dehao Chen <dehao@google.com> writes:

> Index: libcpp/line-map.c

[...]

> + /* 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 map it to a new unsigned integer, and replace it with the original

I think you should remove the words "it with".

> +    location to represent the mapping.

So it should read (so far):

    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 to the location_adhoc_data array,

s/index to/index/

> +    in which the locus and associated data is stored.  */

> + /* 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);
> + 	}
> +     }

I am wondering if there isn't an indentation issue here.

> +   return ((*slot) - location_adhoc_data) | 0x80000000;
> + }
> +

Other than that, I don't really have anything worthwhile to say.  I am
deferring to the maintainers now :-)

Thank you for bearing with me.

-- 
		Dodji

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-14  7:56                 ` Dodji Seketeli
@ 2012-08-14 17:13                   ` Dehao Chen
  2012-08-20  1:19                     ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-08-14 17:13 UTC (permalink / raw)
  To: Dodji Seketeli
  Cc: Richard Guenther, gcc-patches, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey, Jason Merrill

Hi, Dodji,

Thanks for the review. I've fixed all the addressed issues. I'm
attaching the related changes:

Thanks,
Dehao

libcpp/ChangeLog:
2012-08-01  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: libcpp/line-map.c
===================================================================
--- libcpp/line-map.c	(revision 190209)
+++ libcpp/line-map.c	(working copy)
@@ -25,6 +25,7 @@
 #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 @@
 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 @@
 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 @@
   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 @@
   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 @@
 {
   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 @@
 {
   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 @@
 {
   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 @@
 {
   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 @@
 {
   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 @@
 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 @@
 {
   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 @@
 {
   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 @@
 {
   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 @@
 			  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 @@
   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 @@
   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 @@
   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 @@
   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;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-14 17:13                   ` Dehao Chen
@ 2012-08-20  1:19                     ` Dehao Chen
  2012-08-21 13:25                       ` Richard Guenther
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-08-20  1:19 UTC (permalink / raw)
  To: Dodji Seketeli
  Cc: Richard Guenther, gcc-patches, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey, Jason Merrill

ping....

Thanks,
Dehao

On Tue, Aug 14, 2012 at 10:13 AM, Dehao Chen <dehao@google.com> wrote:
> Hi, Dodji,
>
> Thanks for the review. I've fixed all the addressed issues. I'm
> attaching the related changes:
>
> Thanks,
> Dehao
>
> libcpp/ChangeLog:
> 2012-08-01  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: libcpp/line-map.c
> ===================================================================
> --- libcpp/line-map.c   (revision 190209)
> +++ libcpp/line-map.c   (working copy)
> @@ -25,6 +25,7 @@
>  #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 @@
>  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 @@
>  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 @@
>    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 @@
>    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 @@
>  {
>    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 @@
>  {
>    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 @@
>  {
>    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 @@
>  {
>    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 @@
>  {
>    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 @@
>  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 @@
>  {
>    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 @@
>  {
>    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 @@
>  {
>    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 @@
>                           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 @@
>    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 @@
>    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 @@
>    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 @@
>    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;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-20  1:19                     ` Dehao Chen
@ 2012-08-21 13:25                       ` Richard Guenther
  2012-08-21 23:54                         ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-08-21 13:25 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Dodji Seketeli, gcc-patches, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey, Jason Merrill

On Mon, Aug 20, 2012 at 3:18 AM, Dehao Chen <dehao@google.com> wrote:
> ping....

Conceptually I like the change.  Can a libcpp maintainer please have a 2nd
look?

Dehao, did you do any compile-time and memory-usage benchmarks?

Thanks,
Richard.

> Thanks,
> Dehao
>
> On Tue, Aug 14, 2012 at 10:13 AM, Dehao Chen <dehao@google.com> wrote:
>> Hi, Dodji,
>>
>> Thanks for the review. I've fixed all the addressed issues. I'm
>> attaching the related changes:
>>
>> Thanks,
>> Dehao
>>
>> libcpp/ChangeLog:
>> 2012-08-01  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: libcpp/line-map.c
>> ===================================================================
>> --- libcpp/line-map.c   (revision 190209)
>> +++ libcpp/line-map.c   (working copy)
>> @@ -25,6 +25,7 @@
>>  #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 @@
>>  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 @@
>>  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 @@
>>    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 @@
>>    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 @@
>>  {
>>    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 @@
>>  {
>>    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 @@
>>  {
>>    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 @@
>>  {
>>    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 @@
>>  {
>>    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 @@
>>  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 @@
>>  {
>>    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 @@
>>  {
>>    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 @@
>>  {
>>    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 @@
>>                           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 @@
>>    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 @@
>>    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 @@
>>    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 @@
>>    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;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-21 13:25                       ` Richard Guenther
@ 2012-08-21 23:54                         ` Dehao Chen
  2012-09-04 20:47                           ` Dehao Chen
  2012-09-06  9:46                           ` Richard Guenther
  0 siblings, 2 replies; 93+ messages in thread
From: Dehao Chen @ 2012-08-21 23:54 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Dodji Seketeli, gcc-patches, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey, Jason Merrill

On Tue, Aug 21, 2012 at 6:25 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Mon, Aug 20, 2012 at 3:18 AM, Dehao Chen <dehao@google.com> wrote:
>> ping....
>
> Conceptually I like the change.  Can a libcpp maintainer please have a 2nd
> look?
>
> Dehao, did you do any compile-time and memory-usage benchmarks?

I don't have a memory benchmarks at hand. But I've tested it through
some huge apps, each of which takes more than 1 hour to build on a
modern machine. None of them had observed noticeable memory footprint
and compile time increase.

Thanks,
Dehao

>
> Thanks,
> Richard.
>
>> Thanks,
>> Dehao
>>
>> On Tue, Aug 14, 2012 at 10:13 AM, Dehao Chen <dehao@google.com> wrote:
>>> Hi, Dodji,
>>>
>>> Thanks for the review. I've fixed all the addressed issues. I'm
>>> attaching the related changes:
>>>
>>> Thanks,
>>> Dehao
>>>
>>> libcpp/ChangeLog:
>>> 2012-08-01  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: libcpp/line-map.c
>>> ===================================================================
>>> --- libcpp/line-map.c   (revision 190209)
>>> +++ libcpp/line-map.c   (working copy)
>>> @@ -25,6 +25,7 @@
>>>  #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 @@
>>>  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 @@
>>>  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 @@
>>>    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 @@
>>>    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 @@
>>>  {
>>>    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 @@
>>>  {
>>>    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 @@
>>>  {
>>>    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 @@
>>>  {
>>>    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 @@
>>>  {
>>>    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 @@
>>>  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 @@
>>>  {
>>>    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 @@
>>>  {
>>>    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 @@
>>>  {
>>>    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 @@
>>>                           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 @@
>>>    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 @@
>>>    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 @@
>>>    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 @@
>>>    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;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-21 23:54                         ` Dehao Chen
@ 2012-09-04 20:47                           ` Dehao Chen
  2012-09-06  9:46                           ` Richard Guenther
  1 sibling, 0 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-04 20:47 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Dodji Seketeli, gcc-patches, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey, Jason Merrill

ping...

Thanks,
Dehao

On Tue, Aug 21, 2012 at 4:54 PM, Dehao Chen <dehao@google.com> wrote:
> On Tue, Aug 21, 2012 at 6:25 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Mon, Aug 20, 2012 at 3:18 AM, Dehao Chen <dehao@google.com> wrote:
>>> ping....
>>
>> Conceptually I like the change.  Can a libcpp maintainer please have a 2nd
>> look?
>>
>> Dehao, did you do any compile-time and memory-usage benchmarks?
>
> I don't have a memory benchmarks at hand. But I've tested it through
> some huge apps, each of which takes more than 1 hour to build on a
> modern machine. None of them had observed noticeable memory footprint
> and compile time increase.
>
> Thanks,
> Dehao
>
>>
>> Thanks,
>> Richard.
>>
>>> Thanks,
>>> Dehao
>>>
>>> On Tue, Aug 14, 2012 at 10:13 AM, Dehao Chen <dehao@google.com> wrote:
>>>> Hi, Dodji,
>>>>
>>>> Thanks for the review. I've fixed all the addressed issues. I'm
>>>> attaching the related changes:
>>>>
>>>> Thanks,
>>>> Dehao
>>>>
>>>> libcpp/ChangeLog:
>>>> 2012-08-01  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: libcpp/line-map.c
>>>> ===================================================================
>>>> --- libcpp/line-map.c   (revision 190209)
>>>> +++ libcpp/line-map.c   (working copy)
>>>> @@ -25,6 +25,7 @@
>>>>  #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 @@
>>>>  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 @@
>>>>  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 @@
>>>>    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 @@
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>                           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 @@
>>>>    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 @@
>>>>    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 @@
>>>>    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 @@
>>>>    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;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-08-21 23:54                         ` Dehao Chen
  2012-09-04 20:47                           ` Dehao Chen
@ 2012-09-06  9:46                           ` Richard Guenther
  2012-09-07 11:08                             ` Diego Novillo
  1 sibling, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-09-06  9:46 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Dodji Seketeli, gcc-patches, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey, Jason Merrill, Richard Henderson

On Wed, Aug 22, 2012 at 1:54 AM, Dehao Chen <dehao@google.com> wrote:
> On Tue, Aug 21, 2012 at 6:25 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Mon, Aug 20, 2012 at 3:18 AM, Dehao Chen <dehao@google.com> wrote:
>>> ping....
>>
>> Conceptually I like the change.  Can a libcpp maintainer please have a 2nd
>> look?
>>
>> Dehao, did you do any compile-time and memory-usage benchmarks?
>
> I don't have a memory benchmarks at hand. But I've tested it through
> some huge apps, each of which takes more than 1 hour to build on a
> modern machine. None of them had observed noticeable memory footprint
> and compile time increase.

Thanks.

I'd like to see a 2nd "ok", but hereby I give a first one ;)  It's a big change
but definitely a good one.

Thanks again,
Richard.


> Thanks,
> Dehao
>
>>
>> Thanks,
>> Richard.
>>
>>> Thanks,
>>> Dehao
>>>
>>> On Tue, Aug 14, 2012 at 10:13 AM, Dehao Chen <dehao@google.com> wrote:
>>>> Hi, Dodji,
>>>>
>>>> Thanks for the review. I've fixed all the addressed issues. I'm
>>>> attaching the related changes:
>>>>
>>>> Thanks,
>>>> Dehao
>>>>
>>>> libcpp/ChangeLog:
>>>> 2012-08-01  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: libcpp/line-map.c
>>>> ===================================================================
>>>> --- libcpp/line-map.c   (revision 190209)
>>>> +++ libcpp/line-map.c   (working copy)
>>>> @@ -25,6 +25,7 @@
>>>>  #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 @@
>>>>  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 @@
>>>>  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 @@
>>>>    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 @@
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>  {
>>>>    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 @@
>>>>                           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 @@
>>>>    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 @@
>>>>    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 @@
>>>>    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 @@
>>>>    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;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-06  9:46                           ` Richard Guenther
@ 2012-09-07 11:08                             ` Diego Novillo
  2012-09-07 14:56                               ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Diego Novillo @ 2012-09-07 11:08 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Dehao Chen, Dodji Seketeli, gcc-patches, Jakub Jelinek,
	Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

On 2012-09-06 05:46 , Richard Guenther wrote:
> On Wed, Aug 22, 2012 at 1:54 AM, Dehao Chen <dehao@google.com> wrote:
>> On Tue, Aug 21, 2012 at 6:25 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Mon, Aug 20, 2012 at 3:18 AM, Dehao Chen <dehao@google.com> wrote:
>>>> ping....
>>>
>>> Conceptually I like the change.  Can a libcpp maintainer please have a 2nd
>>> look?
>>>
>>> Dehao, did you do any compile-time and memory-usage benchmarks?
>>
>> I don't have a memory benchmarks at hand. But I've tested it through
>> some huge apps, each of which takes more than 1 hour to build on a
>> modern machine. None of them had observed noticeable memory footprint
>> and compile time increase.
>
> Thanks.
>
> I'd like to see a 2nd "ok", but hereby I give a first one ;)  It's a big change
> but definitely a good one.

Dehao, could you attach a final, and complete, patch?  I've seen 3 or 4 
patches in this thread.  The latest version is only a fragment of the 
full patch.


Thanks.  Diego.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-07 11:08                             ` Diego Novillo
@ 2012-09-07 14:56                               ` Dehao Chen
  2012-09-07 17:29                                 ` Diego Novillo
  2012-09-13 16:49                                 ` Tom Tromey
  0 siblings, 2 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-07 14:56 UTC (permalink / raw)
  To: Diego Novillo
  Cc: Richard Guenther, Dodji Seketeli, gcc-patches, Jakub Jelinek,
	Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

[-- Attachment #1: Type: text/plain, Size: 7366 bytes --]

Hi, Diego,

Thanks a lot for taking time to review this. Attached is the up-to-date patch.

This patch has bootstrapped and passed gcc regression tests.

Thanks,
Dehao

gcc/ChangeLog:
2012-08-01  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.
	* dewarf2out.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-08-01  Dehao Chen  <dehao@google.com>

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

libcpp/ChangeLog:
2012-08-01  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.

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 125295 bytes --]

Index: gcc/gimple-streamer-out.c
===================================================================
*** gcc/gimple-streamer-out.c	(revision 190209)
--- gcc/gimple-streamer-out.c	(working copy)
*************** output_gimple_stmt (struct output_block 
*** 74,80 ****
    streamer_write_bitpack (&bp);
  
    /* Emit location information for the statement.  */
!   lto_output_location (ob, gimple_location (stmt));
  
    /* Emit the lexical block holding STMT.  */
    stream_write_tree (ob, gimple_block (stmt), true);
--- 74,80 ----
    streamer_write_bitpack (&bp);
  
    /* Emit location information for the statement.  */
!   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 190209)
--- gcc/tree.c	(working copy)
*************** build1_stat (enum tree_code code, tree t
*** 3760,3766 ****
    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);
--- 3760,3765 ----
*************** walk_tree_without_duplicates_1 (tree *tp
*** 10831,10847 ****
  }
  
  
! tree *
  tree_block (tree t)
  {
    char const c = TREE_CODE_CLASS (TREE_CODE (t));
  
    if (IS_EXPR_CODE_CLASS (c))
!     return &t->exp.block;
    gcc_unreachable ();
    return NULL;
  }
  
  /* 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.  */
--- 10830,10857 ----
  }
  
  
! tree
  tree_block (tree t)
  {
    char const c = TREE_CODE_CLASS (TREE_CODE (t));
  
    if (IS_EXPR_CODE_CLASS (c))
!     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 190209)
--- gcc/tree.h	(working copy)
*************** extern void omp_clause_range_check_faile
*** 999,1005 ****
  
  #endif
  
! #define TREE_BLOCK(NODE)		*(tree_block (NODE))
  
  #include "tree-check.h"
  
--- 999,1006 ----
  
  #endif
  
! #define TREE_BLOCK(NODE)		(tree_block (NODE))
! #define TREE_SET_BLOCK(T, B)		(tree_set_block ((T), (B)))
  
  #include "tree-check.h"
  
*************** struct GTY(()) tree_constructor {
*** 1702,1708 ****
  #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)
  /* 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)
--- 1703,1709 ----
  #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) (!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)
*************** extern void protected_set_expr_location 
*** 1881,1887 ****
  					      OMP_CLAUSE_PRIVATE,	\
  	                                      OMP_CLAUSE_COPYPRIVATE), 0)
  #define OMP_CLAUSE_HAS_LOCATION(NODE) \
!   ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus != UNKNOWN_LOCATION)
  #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,1888 ----
  					      OMP_CLAUSE_PRIVATE,	\
  	                                      OMP_CLAUSE_COPYPRIVATE), 0)
  #define OMP_CLAUSE_HAS_LOCATION(NODE) \
!   (!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.
*************** enum omp_clause_default_kind
*** 1972,1978 ****
  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];
--- 1973,1978 ----
*************** function_args_iter_next (function_args_i
*** 5136,5142 ****
  static inline bool
  inlined_function_outer_scope_p (const_tree block)
  {
!  return BLOCK_SOURCE_LOCATION (block) != UNKNOWN_LOCATION;
  }
  
  /* Loop over all function arguments of FNTYPE.  In each iteration, PTR is set
--- 5136,5142 ----
  static inline bool
  inlined_function_outer_scope_p (const_tree block)
  {
!  return !IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (block));
  }
  
  /* Loop over all function arguments of FNTYPE.  In each iteration, PTR is set
*************** extern bool subrange_type_for_debug_p (c
*** 5511,5517 ****
  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 location_t *block_nonartificial_location (tree);
  extern location_t tree_nonartificial_location (tree);
  
--- 5511,5518 ----
  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 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 190209)
--- gcc/final.c	(working copy)
*************** reemit_insn_block_notes (void)
*** 1605,1611 ****
  					     insn_scope (XVECEXP (body, 0, i)));
  	}
        if (! this_block)
! 	continue;
  
        if (this_block != cur_block)
  	{
--- 1605,1611 ----
  					     insn_scope (XVECEXP (body, 0, i)));
  	}
        if (! this_block)
! 	this_block = DECL_INITIAL (cfun->decl);
  
        if (this_block != cur_block)
  	{
*************** final_start_function (rtx first ATTRIBUT
*** 1640,1647 ****
  
    this_is_asm_operands = 0;
  
!   last_filename = locator_file (prologue_locator);
!   last_linenum = locator_line (prologue_locator);
    last_discriminator = discriminator = 0;
  
    high_block_linenum = high_function_linenum = last_linenum;
--- 1640,1647 ----
  
    this_is_asm_operands = 0;
  
!   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 190209)
--- gcc/input.c	(working copy)
*************** expand_location_1 (source_location loc,
*** 51,56 ****
--- 51,63 ----
    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));
  
*************** expand_location_1 (source_location loc,
*** 74,79 ****
--- 81,87 ----
        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 190209)
--- gcc/input.h	(working copy)
*************** extern location_t input_location;
*** 51,56 ****
--- 51,64 ----
  #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 190209)
--- gcc/fold-const.c	(working copy)
*************** static location_t
*** 145,151 ****
  expr_location_or (tree t, location_t loc)
  {
    location_t tloc = EXPR_LOCATION (t);
!   return tloc != UNKNOWN_LOCATION ? tloc : loc;
  }
  
  /* Similar to protected_set_expr_location, but never modify x in place,
--- 145,151 ----
  expr_location_or (tree t, location_t loc)
  {
    location_t tloc = EXPR_LOCATION (t);
!   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 190209)
--- gcc/toplev.c	(working copy)
*************** general_init (const char *argv0)
*** 1140,1145 ****
--- 1140,1146 ----
    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.  */
*************** toplev_main (int argc, char **argv)
*** 1946,1951 ****
--- 1947,1953 ----
    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 190209)
--- gcc/reorg.c	(working copy)
*************** emit_delay_sequence (rtx insn, rtx list,
*** 545,551 ****
    INSN_DELETED_P (delay_insn) = 0;
    PREV_INSN (delay_insn) = PREV_INSN (seq_insn);
  
!   INSN_LOCATOR (seq_insn) = INSN_LOCATOR (delay_insn);
  
    for (li = list; li; li = XEXP (li, 1), i++)
      {
--- 545,551 ----
    INSN_DELETED_P (delay_insn) = 0;
    PREV_INSN (delay_insn) = PREV_INSN (seq_insn);
  
!   INSN_LOCATION (seq_insn) = INSN_LOCATION (delay_insn);
  
    for (li = list; li; li = XEXP (li, 1), i++)
      {
*************** emit_delay_sequence (rtx insn, rtx list,
*** 561,569 ****
  
        /* 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;
  
        for (note = REG_NOTES (tem); note; note = next)
  	{
--- 561,569 ----
  
        /* SPARC assembler, for instance, emit warning when debug info is output
           into the delay slot.  */
!       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)
  	{
*************** dbr_schedule (rtx first)
*** 4065,4071 ****
      for (link = crtl->epilogue_delay_list;
           link;
           link = XEXP (link, 1))
!       INSN_LOCATOR (XEXP (link, 0)) = 0;
    }
  
  #endif
--- 4065,4071 ----
      for (link = crtl->epilogue_delay_list;
           link;
           link = XEXP (link, 1))
!       INSN_LOCATION (XEXP (link, 0)) = 0;
    }
  
  #endif
Index: gcc/modulo-sched.c
===================================================================
*** gcc/modulo-sched.c	(revision 190209)
--- gcc/modulo-sched.c	(working copy)
*************** loop_single_full_bb_p (struct loop *loop
*** 1246,1254 ****
  /* Dump file:line from INSN's location info to dump_file.  */
  
  static void
! dump_insn_locator (rtx insn)
  {
!   if (dump_file && INSN_LOCATOR (insn))
      {
        const char *file = insn_file (insn);
        if (file)
--- 1246,1254 ----
  /* Dump file:line from INSN's location info to dump_file.  */
  
  static void
! dump_insn_location (rtx insn)
  {
!   if (dump_file && INSN_LOCATION (insn))
      {
        const char *file = insn_file (insn);
        if (file)
*************** loop_canon_p (struct loop *loop)
*** 1282,1288 ****
  	  rtx insn = BB_END (loop->header);
  
  	  fprintf (dump_file, "SMS loop many exits");
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
--- 1282,1288 ----
  	  rtx insn = BB_END (loop->header);
  
  	  fprintf (dump_file, "SMS loop many exits");
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
*************** loop_canon_p (struct loop *loop)
*** 1295,1301 ****
  	  rtx insn = BB_END (loop->header);
  
  	  fprintf (dump_file, "SMS loop many BBs.");
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
--- 1295,1301 ----
  	  rtx insn = BB_END (loop->header);
  
  	  fprintf (dump_file, "SMS loop many BBs.");
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}
        return false;
*************** sms_schedule (void)
*** 1421,1427 ****
  	  rtx insn = BB_END (loop->header);
  
  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  	}
  
--- 1421,1427 ----
  	  rtx insn = BB_END (loop->header);
  
  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  	}
  
*************** sms_schedule (void)
*** 1450,1456 ****
  	{
  	  if (dump_file)
  	    {
! 	      dump_insn_locator (tail);
  	      fprintf (dump_file, "\nSMS single-bb-loop\n");
  	      if (profile_info && flag_branch_probabilities)
  	    	{
--- 1450,1456 ----
  	{
  	  if (dump_file)
  	    {
! 	      dump_insn_location (tail);
  	      fprintf (dump_file, "\nSMS single-bb-loop\n");
  	      if (profile_info && flag_branch_probabilities)
  	    	{
*************** sms_schedule (void)
*** 1556,1562 ****
  	  rtx insn = BB_END (loop->header);
  
  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_locator (insn);
  	  fprintf (dump_file, "\n");
  
  	  print_ddg (dump_file, g);
--- 1556,1562 ----
  	  rtx insn = BB_END (loop->header);
  
  	  fprintf (dump_file, "SMS loop num: %d", loop->num);
! 	  dump_insn_location (insn);
  	  fprintf (dump_file, "\n");
  
  	  print_ddg (dump_file, g);
*************** sms_schedule (void)
*** 1571,1577 ****
  
        if (dump_file)
  	{
! 	  dump_insn_locator (tail);
  	  fprintf (dump_file, "\nSMS single-bb-loop\n");
  	  if (profile_info && flag_branch_probabilities)
  	    {
--- 1571,1577 ----
  
        if (dump_file)
  	{
! 	  dump_insn_location (tail);
  	  fprintf (dump_file, "\nSMS single-bb-loop\n");
  	  if (profile_info && flag_branch_probabilities)
  	    {
*************** sms_schedule (void)
*** 1714,1720 ****
  
            if (dump_file)
              {
! 	      dump_insn_locator (tail);
  	      fprintf (dump_file, " SMS succeeded %d %d (with ii, sc)\n",
  		       ps->ii, stage_count);
  	      print_partial_schedule (ps, dump_file);
--- 1714,1720 ----
  
            if (dump_file)
              {
! 	      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 190209)
--- gcc/lto-streamer-out.c	(working copy)
*************** lto_output_location_bitpack (struct bitp
*** 155,160 ****
--- 155,161 ----
  {
    expanded_location xloc;
  
+   loc = LOCATION_LOCUS (loc);
    bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1);
    if (loc == UNKNOWN_LOCATION)
      return;
Index: gcc/jump.c
===================================================================
*** gcc/jump.c	(revision 190209)
--- gcc/jump.c	(working copy)
*************** rtx_renumbered_equal_p (const_rtx x, con
*** 1818,1825 ****
  	  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)))
  		break;
  	      return 0;
  	    }
--- 1818,1824 ----
  	  if (XINT (x, i) != XINT (y, i))
  	    {
  	      if (((code == ASM_OPERANDS && i == 6)
! 		   || (code == ASM_INPUT && i == 1)))
  		break;
  	      return 0;
  	    }
Index: gcc/ifcvt.c
===================================================================
*** gcc/ifcvt.c	(revision 190209)
--- gcc/ifcvt.c	(working copy)
*************** noce_try_move (struct noce_if_info *if_i
*** 1019,1025 ****
  	    return FALSE;
  
  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	}
        return TRUE;
      }
--- 1019,1025 ----
  	    return FALSE;
  
  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	}
        return TRUE;
      }
*************** noce_try_store_flag (struct noce_if_info
*** 1064,1070 ****
  	return FALSE;
  
        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
        return TRUE;
      }
    else
--- 1064,1070 ----
  	return FALSE;
  
        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
        return TRUE;
      }
    else
*************** noce_try_store_flag_constants (struct no
*** 1195,1201 ****
  	return FALSE;
  
        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
        return TRUE;
      }
  
--- 1195,1201 ----
  	return FALSE;
  
        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
        return TRUE;
      }
  
*************** noce_try_addcc (struct noce_if_info *if_
*** 1243,1249 ****
  		return FALSE;
  
  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATOR (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
--- 1243,1249 ----
  		return FALSE;
  
  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATION (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
*************** noce_try_addcc (struct noce_if_info *if_
*** 1283,1289 ****
  		return FALSE;
  
  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATOR (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
--- 1283,1289 ----
  		return FALSE;
  
  	      emit_insn_before_setloc (seq, if_info->jump,
! 				       INSN_LOCATION (if_info->insn_a));
  	      return TRUE;
  	    }
  	  end_sequence ();
*************** noce_try_store_flag_mask (struct noce_if
*** 1332,1338 ****
  	    return FALSE;
  
  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	  return TRUE;
  	}
  
--- 1332,1338 ----
  	    return FALSE;
  
  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	  return TRUE;
  	}
  
*************** noce_try_cmove (struct noce_if_info *if_
*** 1481,1487 ****
  	    return FALSE;
  
  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATOR (if_info->insn_a));
  	  return TRUE;
  	}
        else
--- 1481,1487 ----
  	    return FALSE;
  
  	  emit_insn_before_setloc (seq, if_info->jump,
! 				   INSN_LOCATION (if_info->insn_a));
  	  return TRUE;
  	}
        else
*************** noce_try_cmove_arith (struct noce_if_inf
*** 1682,1688 ****
    if (!tmp)
      return FALSE;
  
!   emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR (if_info->insn_a));
    return TRUE;
  
   end_seq_and_fail:
--- 1682,1688 ----
    if (!tmp)
      return FALSE;
  
!   emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATION (if_info->insn_a));
    return TRUE;
  
   end_seq_and_fail:
*************** noce_try_minmax (struct noce_if_info *if
*** 1929,1935 ****
    if (!seq)
      return FALSE;
  
!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;
  
--- 1929,1935 ----
    if (!seq)
      return FALSE;
  
!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;
  
*************** noce_try_abs (struct noce_if_info *if_in
*** 2076,2082 ****
    if (!seq)
      return FALSE;
  
!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;
  
--- 2076,2082 ----
    if (!seq)
      return FALSE;
  
!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
    if_info->cond = cond;
    if_info->cond_earliest = earliest;
  
*************** noce_try_sign_mask (struct noce_if_info 
*** 2155,2161 ****
    if (!seq)
      return FALSE;
  
!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
    return TRUE;
  }
  
--- 2155,2161 ----
    if (!seq)
      return FALSE;
  
!   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
    return TRUE;
  }
  
*************** noce_try_bitop (struct noce_if_info *if_
*** 2255,2261 ****
  	return FALSE;
  
        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATOR (if_info->insn_a));
      }
    return TRUE;
  }
--- 2255,2261 ----
  	return FALSE;
  
        emit_insn_before_setloc (seq, if_info->jump,
! 			       INSN_LOCATION (if_info->insn_a));
      }
    return TRUE;
  }
*************** noce_process_if_block (struct noce_if_in
*** 2656,2662 ****
        unshare_all_rtl_in_chain (seq);
        end_sequence ();
  
!       emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATOR (insn_a));
      }
  
    /* The original THEN and ELSE blocks may now be removed.  The test block
--- 2656,2662 ----
        unshare_all_rtl_in_chain (seq);
        end_sequence ();
  
!       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
*************** cond_move_process_if_block (struct noce_
*** 2937,2943 ****
        loc_insn = first_active_insn (else_bb);
        gcc_assert (loc_insn);
      }
!   emit_insn_before_setloc (seq, jump, INSN_LOCATOR (loc_insn));
  
    if (else_bb)
      {
--- 2937,2943 ----
        loc_insn = first_active_insn (else_bb);
        gcc_assert (loc_insn);
      }
!   emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));
  
    if (else_bb)
      {
*************** find_cond_trap (basic_block test_bb, edg
*** 3655,3661 ****
      return FALSE;
  
    /* Emit the new insns before cond_earliest.  */
!   emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATOR (trap));
  
    /* Delete the trap block if possible.  */
    remove_edge (trap_bb == then_bb ? then_edge : else_edge);
--- 3655,3661 ----
      return FALSE;
  
    /* Emit the new insns before cond_earliest.  */
!   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/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c	(revision 190209)
--- gcc/dwarf2out.c	(working copy)
*************** add_src_coords_attributes (dw_die_ref di
*** 15506,15512 ****
  {
    expanded_location s;
  
!   if (DECL_SOURCE_LOCATION (decl) == UNKNOWN_LOCATION)
      return;
    s = expand_location (DECL_SOURCE_LOCATION (decl));
    add_AT_file (die, DW_AT_decl_file, lookup_filename (s.file));
--- 15506,15512 ----
  {
    expanded_location s;
  
!   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 190209)
--- gcc/expr.c	(working copy)
*************** expand_expr_real (tree exp, rtx target, 
*** 7802,7820 ****
    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 ();
        input_location = EXPR_LOCATION (exp);
!       set_curr_insn_source_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);
      }
    else
      {
--- 7802,7815 ----
    if (cfun && EXPR_HAS_LOCATION (exp))
      {
        location_t saved_location = input_location;
!       location_t saved_curr_loc = curr_insn_location ();
        input_location = EXPR_LOCATION (exp);
!       set_curr_insn_location (input_location);
  
        ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
  
        input_location = saved_location;
!       set_curr_insn_location (saved_curr_loc);
      }
    else
      {
Index: gcc/tree-parloops.c
===================================================================
*** gcc/tree-parloops.c	(revision 190209)
--- gcc/tree-parloops.c	(working copy)
*************** create_loop_fn (location_t loc)
*** 1404,1409 ****
--- 1404,1410 ----
    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 190209)
--- gcc/recog.c	(working copy)
*************** peep2_attempt (basic_block bb, rtx insn,
*** 3326,3332 ****
    /* 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));
    before_try = PREV_INSN (insn);
    delete_insn_chain (insn, peep2_insn_data[i].insn, false);
  
--- 3326,3332 ----
    /* Replace the old sequence with the new.  */
    last = emit_insn_after_setloc (attempt,
  				 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 190209)
--- gcc/function.c	(working copy)
*************** static bool contains (const_rtx, htab_t)
*** 133,139 ****
  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;
  \f
  /* Stack of nested functions.  */
  /* Keep track of the cfun stack.  */
--- 133,139 ----
  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_locations (rtx, int) ATTRIBUTE_UNUSED;
  \f
  /* Stack of nested functions.  */
  /* Keep track of the cfun stack.  */
*************** free_after_compilation (struct function 
*** 200,206 ****
    f->cfg = NULL;
  
    regno_reg_rtx = NULL;
-   insn_locators_free ();
  }
  \f
  /* Return size needed for stack frame based on slots so far allocated.
--- 200,205 ----
*************** expand_function_end (void)
*** 4979,4985 ****
  	      probe_stack_range (STACK_OLD_CHECK_PROTECT, max_frame_size);
  	    seq = get_insns ();
  	    end_sequence ();
! 	    set_insn_locators (seq, prologue_locator);
  	    emit_insn_before (seq, stack_check_probe_note);
  	    break;
  	  }
--- 4978,4984 ----
  	      probe_stack_range (STACK_OLD_CHECK_PROTECT, max_frame_size);
  	    seq = get_insns ();
  	    end_sequence ();
! 	    set_insn_locations (seq, prologue_location);
  	    emit_insn_before (seq, stack_check_probe_note);
  	    break;
  	  }
*************** expand_function_end (void)
*** 4994,5000 ****
  
    /* Output a linenumber for the end of the function.
       SDB depends on this.  */
!   set_curr_insn_source_location (input_location);
  
    /* Before the return label (if any), clobber the return
       registers so that they are not propagated live to the rest of
--- 4993,4999 ----
  
    /* Output a linenumber for the end of the function.
       SDB depends on this.  */
!   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
*************** maybe_copy_prologue_epilogue_insn (rtx i
*** 5277,5290 ****
    *slot = copy;
  }
  
! /* Set the locator of the insn chain starting at INSN to LOC.  */
  static void
! set_insn_locators (rtx insn, int loc)
  {
    while (insn != NULL_RTX)
      {
        if (INSN_P (insn))
! 	INSN_LOCATOR (insn) = loc;
        insn = NEXT_INSN (insn);
      }
  }
--- 5276,5289 ----
    *slot = copy;
  }
  
! /* Set the location of the insn chain starting at INSN to LOC.  */
  static void
! set_insn_locations (rtx insn, int loc)
  {
    while (insn != NULL_RTX)
      {
        if (INSN_P (insn))
! 	INSN_LOCATION (insn) = loc;
        insn = NEXT_INSN (insn);
      }
  }
*************** thread_prologue_and_epilogue_insns (void
*** 5893,5899 ****
        end_sequence ();
  
        record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
!       set_insn_locators (split_prologue_seq, prologue_locator);
  #endif
      }
  
--- 5892,5898 ----
        end_sequence ();
  
        record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
!       set_insn_locations (split_prologue_seq, prologue_location);
  #endif
      }
  
*************** thread_prologue_and_epilogue_insns (void
*** 5922,5928 ****
  
        prologue_seq = get_insns ();
        end_sequence ();
!       set_insn_locators (prologue_seq, prologue_locator);
      }
  #endif
  
--- 5921,5927 ----
  
        prologue_seq = get_insns ();
        end_sequence ();
!       set_insn_locations (prologue_seq, prologue_location);
      }
  #endif
  
*************** thread_prologue_and_epilogue_insns (void
*** 6418,6424 ****
  
        /* Retain a map of the epilogue insns.  */
        record_insns (seq, NULL, &epilogue_insn_hash);
!       set_insn_locators (seq, epilogue_locator);
  
        seq = get_insns ();
        returnjump = get_last_insn ();
--- 6417,6423 ----
  
        /* Retain a map of the epilogue insns.  */
        record_insns (seq, NULL, &epilogue_insn_hash);
!       set_insn_locations (seq, epilogue_location);
  
        seq = get_insns ();
        returnjump = get_last_insn ();
*************** epilogue_done:
*** 6608,6614 ****
  	     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);
  
  	  emit_insn_before (seq, insn);
  	}
--- 6607,6613 ----
  	     avoid getting rid of sibcall epilogue insns.  Do this before we
  	     actually emit the sequence.  */
  	  record_insns (seq, NULL, &epilogue_insn_hash);
! 	  set_insn_locations (seq, epilogue_location);
  
  	  emit_insn_before (seq, insn);
  	}
Index: gcc/print-rtl.c
===================================================================
*** gcc/print-rtl.c	(revision 190209)
--- gcc/print-rtl.c	(working copy)
*************** print_rtx (const_rtx in_rtx)
*** 416,425 ****
  	if (i == 5 && INSN_P (in_rtx))
  	  {
  #ifndef GENERATOR_FILE
! 	    /*  Pretty-print insn locators.  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))
  	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
  #endif
  	  }
--- 416,425 ----
  	if (i == 5 && INSN_P (in_rtx))
  	  {
  #ifndef GENERATOR_FILE
! 	    /*  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_LOCATION (in_rtx) && insn_file (in_rtx))
  	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
  #endif
  	  }
*************** print_rtx (const_rtx in_rtx)
*** 427,442 ****
  	  {
  #ifndef GENERATOR_FILE
  	    fprintf (outfile, " %s:%i",
! 		     locator_file (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)),
! 		     locator_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)));
  #endif
  	  }
  	else if (i == 6 && NOTE_P (in_rtx))
--- 427,442 ----
  	  {
  #ifndef GENERATOR_FILE
  	    fprintf (outfile, " %s:%i",
! 		     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",
! 		     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 190209)
--- gcc/profile.c	(working copy)
*************** branch_prob (void)
*** 966,972 ****
  	     is not computed twice.  */
  	  if (last
  	      && gimple_has_location (last)
! 	      && e->goto_locus != UNKNOWN_LOCATION
  	      && !single_succ_p (bb)
  	      && (LOCATION_FILE (e->goto_locus)
  	          != LOCATION_FILE (gimple_location (last))
--- 966,972 ----
  	     is not computed twice.  */
  	  if (last
  	      && gimple_has_location (last)
! 	      && !IS_UNKNOWN_LOCATION (e->goto_locus)
  	      && !single_succ_p (bb)
  	      && (LOCATION_FILE (e->goto_locus)
  	          != LOCATION_FILE (gimple_location (last))
*************** branch_prob (void)
*** 976,982 ****
  	      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)
--- 976,981 ----
*************** branch_prob (void)
*** 1188,1194 ****
  
  	  /* Notice GOTO expressions eliminated while constructing the CFG.  */
  	  if (single_succ_p (bb)
! 	      && single_succ_edge (bb)->goto_locus != UNKNOWN_LOCATION)
  	    {
  	      expanded_location curr_location
  		= expand_location (single_succ_edge (bb)->goto_locus);
--- 1187,1193 ----
  
  	  /* Notice GOTO expressions eliminated while constructing the CFG.  */
  	  if (single_succ_p (bb)
! 	      && !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 190209)
--- gcc/trans-mem.c	(working copy)
*************** ipa_tm_scan_irr_block (basic_block bb)
*** 3795,3801 ****
  	    {
  	      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;
--- 3795,3800 ----
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c	(revision 190209)
--- gcc/gimplify.c	(working copy)
*************** gimplify_call_expr (tree *expr_p, gimple
*** 2591,2597 ****
  	    = 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;
--- 2591,2596 ----
Index: gcc/except.c
===================================================================
*** gcc/except.c	(revision 190209)
--- gcc/except.c	(working copy)
*************** duplicate_eh_regions_1 (struct duplicate
*** 526,532 ****
        break;
  
      case ERT_MUST_NOT_THROW:
!       new_r->u.must_not_throw = old_r->u.must_not_throw;
        break;
      }
  
--- 526,535 ----
        break;
  
      case ERT_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 190209)
--- gcc/emit-rtl.c	(working copy)
*************** try_split (rtx pat, rtx trial, int last)
*** 3634,3640 ****
  	}
      }
  
!   tem = emit_insn_after_setloc (seq, trial, INSN_LOCATOR (trial));
  
    delete_insn (trial);
    if (has_barrier)
--- 3634,3640 ----
  	}
      }
  
!   tem = emit_insn_after_setloc (seq, trial, INSN_LOCATION (trial));
  
    delete_insn (trial);
    if (has_barrier)
*************** make_insn_raw (rtx pattern)
*** 3670,3676 ****
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;
  
  #ifdef ENABLE_RTL_CHECKING
--- 3670,3676 ----
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;
  
  #ifdef ENABLE_RTL_CHECKING
*************** make_debug_insn_raw (rtx pattern)
*** 3703,3709 ****
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;
  
    return insn;
--- 3703,3709 ----
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;
  
    return insn;
*************** make_jump_insn_raw (rtx pattern)
*** 3723,3729 ****
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    JUMP_LABEL (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;
  
    return insn;
--- 3723,3729 ----
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    JUMP_LABEL (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;
  
    return insn;
*************** make_call_insn_raw (rtx pattern)
*** 3743,3749 ****
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    CALL_INSN_FUNCTION_USAGE (insn) = NULL;
!   INSN_LOCATOR (insn) = curr_insn_locator ();
    BLOCK_FOR_INSN (insn) = NULL;
  
    return insn;
--- 3743,3749 ----
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;
    CALL_INSN_FUNCTION_USAGE (insn) = NULL;
!   INSN_LOCATION (insn) = curr_insn_location ();
    BLOCK_FOR_INSN (insn) = NULL;
  
    return insn;
*************** emit_pattern_after_setloc (rtx pattern, 
*** 4416,4423 ****
    after = NEXT_INSN (after);
    while (1)
      {
!       if (active_insn_p (after) && !INSN_LOCATOR (after))
! 	INSN_LOCATOR (after) = loc;
        if (after == last)
  	break;
        after = NEXT_INSN (after);
--- 4416,4423 ----
    after = NEXT_INSN (after);
    while (1)
      {
!       if (active_insn_p (after) && !INSN_LOCATION (after))
! 	INSN_LOCATION (after) = loc;
        if (after == last)
  	break;
        after = NEXT_INSN (after);
*************** emit_pattern_after (rtx pattern, rtx aft
*** 4440,4501 ****
        prev = PREV_INSN (prev);
  
    if (INSN_P (prev))
!     return emit_pattern_after_setloc (pattern, after, INSN_LOCATOR (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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  rtx
  emit_debug_insn_after (rtx pattern, rtx after)
  {
--- 4440,4501 ----
        prev = PREV_INSN (prev);
  
    if (INSN_P (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_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_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_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_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_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_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_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_LOCATION according to AFTER.  */
  rtx
  emit_debug_insn_after (rtx pattern, rtx after)
  {
*************** emit_pattern_before_setloc (rtx pattern,
*** 4525,4532 ****
      first = NEXT_INSN (first);
    while (1)
      {
!       if (active_insn_p (first) && !INSN_LOCATOR (first))
! 	INSN_LOCATOR (first) = loc;
        if (first == last)
  	break;
        first = NEXT_INSN (first);
--- 4525,4532 ----
      first = NEXT_INSN (first);
    while (1)
      {
!       if (active_insn_p (first) && !INSN_LOCATION (first))
! 	INSN_LOCATION (first) = loc;
        if (first == last)
  	break;
        first = NEXT_INSN (first);
*************** emit_pattern_before (rtx pattern, rtx be
*** 4550,4556 ****
        next = PREV_INSN (next);
  
    if (INSN_P (next))
!     return emit_pattern_before_setloc (pattern, before, INSN_LOCATOR (next),
  				       insnp, make_raw);
    else
      return emit_pattern_before_noloc (pattern, before,
--- 4550,4556 ----
        next = PREV_INSN (next);
  
    if (INSN_P (next))
!     return emit_pattern_before_setloc (pattern, before, INSN_LOCATION (next),
  				       insnp, make_raw);
    else
      return emit_pattern_before_noloc (pattern, before,
*************** emit_pattern_before (rtx pattern, rtx be
*** 4558,4564 ****
                                        NULL, make_raw);
  }
  
! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4558,4564 ----
                                        NULL, make_raw);
  }
  
! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_insn_before_setloc (rtx pattern, rt
*** 4566,4579 ****
  				     make_insn_raw);
  }
  
! /* Like emit_insn_before_noloc, but set INSN_LOCATOR 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.  */
  rtx
  emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4566,4579 ----
  				     make_insn_raw);
  }
  
! /* 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_LOCATION according to LOC.  */
  rtx
  emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_jump_insn_before_setloc (rtx patter
*** 4581,4587 ****
  				     make_jump_insn_raw);
  }
  
! /* Like emit_jump_insn_before_noloc, but set INSN_LOCATOR according to BEFORE.  */
  rtx
  emit_jump_insn_before (rtx pattern, rtx before)
  {
--- 4581,4587 ----
  				     make_jump_insn_raw);
  }
  
! /* Like emit_jump_insn_before_noloc, but set INSN_LOCATION according to BEFORE.  */
  rtx
  emit_jump_insn_before (rtx pattern, rtx before)
  {
*************** emit_jump_insn_before (rtx pattern, rtx 
*** 4589,4595 ****
  			      make_jump_insn_raw);
  }
  
! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4589,4595 ----
  			      make_jump_insn_raw);
  }
  
! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_call_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_call_insn_before_setloc (rtx patter
*** 4598,4604 ****
  }
  
  /* Like emit_call_insn_before_noloc,
!    but set insn_locator according to BEFORE.  */
  rtx
  emit_call_insn_before (rtx pattern, rtx before)
  {
--- 4598,4604 ----
  }
  
  /* Like emit_call_insn_before_noloc,
!    but set insn_location according to BEFORE.  */
  rtx
  emit_call_insn_before (rtx pattern, rtx before)
  {
*************** emit_call_insn_before (rtx pattern, rtx 
*** 4606,4612 ****
  			      make_call_insn_raw);
  }
  
! /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to LOC.  */
  rtx
  emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
--- 4606,4612 ----
  			      make_call_insn_raw);
  }
  
! /* Like emit_insn_before_noloc, but set INSN_LOCATION according to LOC.  */
  rtx
  emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc)
  {
*************** emit_debug_insn_before_setloc (rtx patte
*** 4615,4621 ****
  }
  
  /* Like emit_debug_insn_before_noloc,
!    but set insn_locator according to BEFORE.  */
  rtx
  emit_debug_insn_before (rtx pattern, rtx before)
  {
--- 4615,4621 ----
  }
  
  /* Like emit_debug_insn_before_noloc,
!    but set insn_location according to BEFORE.  */
  rtx
  emit_debug_insn_before (rtx pattern, rtx before)
  {
*************** emit_copy_of_insn_after (rtx insn, rtx a
*** 5865,5871 ****
    /* Update LABEL_NUSES.  */
    mark_jump_label (PATTERN (new_rtx), new_rtx, 0);
  
!   INSN_LOCATOR (new_rtx) = INSN_LOCATOR (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,
--- 5865,5871 ----
    /* Update LABEL_NUSES.  */
    mark_jump_label (PATTERN (new_rtx), new_rtx, 0);
  
!   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,
*************** gen_hard_reg_clobber (enum machine_mode 
*** 5900,6149 ****
  	    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;
  
  /* 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.  */
  void
! insn_locators_alloc (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);
! 
    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)
! {
!   if (curr_rtl_loc >= 0)
!     epilogue_locator = curr_insn_locator ();
!   curr_rtl_loc = -1;
! }
! 
! /* 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)
  {
-   /* 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)
  {
    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;
- }
- \f
- 
- /* 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 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 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 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);
- }
- \f
- 
  /* 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.  */
--- 5900,5965 ----
  	    gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
  }
  
! 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;
  
! /* Allocate insn location datastructure.  */
  void
! insn_locations_init (void)
  {
!   prologue_location = epilogue_location = 0;
    curr_location = UNKNOWN_LOCATION;
    last_location = UNKNOWN_LOCATION;
  }
  
  /* At the end of emit stage, clear current location.  */
  void
! insn_locations_finalize (void)
  {
!   epilogue_location = curr_location;
!   curr_location = UNKNOWN_LOCATION;
  }
  
  /* Set current location.  */
  void
! set_curr_insn_location (location_t location)
  {
    curr_location = location;
  }
  
  /* Get current location.  */
  location_t
! curr_insn_location (void)
  {
    return curr_location;
  }
  
  /* Return lexical scope block insn belongs to.  */
  tree
  insn_scope (const_rtx insn)
  {
!   return LOCATION_BLOCK (INSN_LOCATION (insn));
  }
  
  /* Return line number of the statement that produced this insn.  */
  int
  insn_line (const_rtx insn)
  {
!   return LOCATION_LINE (INSN_LOCATION (insn));
  }
  
  /* Return source file of the statement that produced this insn.  */
  const char *
  insn_file (const_rtx insn)
  {
!   return LOCATION_FILE (INSN_LOCATION (insn));
  }
  
  /* 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 190209)
--- gcc/cfgexpand.c	(working copy)
*************** gimple_assign_rhs_to_tree (gimple stmt)
*** 92,99 ****
  	   && gimple_location (stmt) != EXPR_LOCATION (t))
  	  || (gimple_block (stmt)
  	      && currently_expanding_to_rtl
! 	      && EXPR_P (t)
! 	      && gimple_block (stmt) != TREE_BLOCK (t)))
  	t = copy_node (t);
      }
    else
--- 92,98 ----
  	   && gimple_location (stmt) != EXPR_LOCATION (t))
  	  || (gimple_block (stmt)
  	      && currently_expanding_to_rtl
! 	      && EXPR_P (t)))
  	t = copy_node (t);
      }
    else
*************** gimple_assign_rhs_to_tree (gimple stmt)
*** 101,108 ****
  
    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;
  }
--- 100,105 ----
*************** expand_gimple_cond (basic_block bb, gimp
*** 1807,1814 ****
    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));
  
    /* These flags have no purpose in RTL land.  */
    true_edge->flags &= ~EDGE_TRUE_VALUE;
--- 1804,1810 ----
    last2 = last = get_last_insn ();
  
    extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
!   set_curr_insn_location (gimple_location (stmt));
  
    /* These flags have no purpose in RTL land.  */
    true_edge->flags &= ~EDGE_TRUE_VALUE;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1821,1833 ****
        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;
        false_edge->flags |= EDGE_FALLTHRU;
        maybe_cleanup_end_of_block (false_edge, last);
        return NULL;
--- 1817,1824 ----
        jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
  		true_edge->probability);
        maybe_dump_rtl_for_gimple_stmt (stmt, last);
!       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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1837,1849 ****
        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;
        true_edge->flags |= EDGE_FALLTHRU;
        maybe_cleanup_end_of_block (true_edge, last);
        return NULL;
--- 1828,1835 ----
        jumpifnot_1 (code, op0, op1, label_rtx_for_bb (false_edge->dest),
  		   false_edge->probability);
        maybe_dump_rtl_for_gimple_stmt (stmt, last);
!       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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1852,1864 ****
    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;
    emit_jump (label_rtx_for_bb (false_edge->dest));
  
    BB_END (bb) = last;
--- 1838,1845 ----
    jumpif_1 (code, op0, op1, label_rtx_for_bb (true_edge->dest),
  	    true_edge->probability);
    last = get_last_insn ();
!   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;
*************** expand_gimple_cond (basic_block bb, gimp
*** 1883,1895 ****
  
    maybe_dump_rtl_for_gimple_stmt (stmt, last2);
  
!   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;
  
    return new_bb;
  }
--- 1864,1874 ----
  
    maybe_dump_rtl_for_gimple_stmt (stmt, last2);
  
!   if (!IS_UNKNOWN_LOCATION (true_edge->goto_locus))
      {
!       set_curr_insn_location (true_edge->goto_locus);
!       true_edge->goto_locus = curr_insn_location ();
      }
  
    return new_bb;
  }
*************** expand_call_stmt (gimple stmt)
*** 1989,1995 ****
      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))
--- 1968,1973 ----
*************** expand_gimple_stmt_1 (gimple stmt)
*** 2024,2031 ****
  {
    tree op0;
  
!   set_curr_insn_source_location (gimple_location (stmt));
!   set_curr_insn_block (gimple_block (stmt));
  
    switch (gimple_code (stmt))
      {
--- 2002,2008 ----
  {
    tree op0;
  
!   set_curr_insn_location (gimple_location (stmt));
  
    switch (gimple_code (stmt))
      {
*************** expand_gimple_basic_block (basic_block b
*** 3769,3776 ****
  	  tree op;
  	  gimple def;
  
! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();
  
  	  /* Look for SSA names that have their last use here (TERed
  	     names always have only one real use).  */
--- 3746,3752 ----
  	  tree op;
  	  gimple def;
  
! 	  location_t sloc = curr_insn_location ();
  
  	  /* Look for SSA names that have their last use here (TERed
  	     names always have only one real use).  */
*************** expand_gimple_basic_block (basic_block b
*** 3803,3810 ****
  		    rtx val;
  		    enum machine_mode mode;
  
! 		    set_curr_insn_source_location (gimple_location (def));
! 		    set_curr_insn_block (gimple_block (def));
  
  		    DECL_ARTIFICIAL (vexpr) = 1;
  		    TREE_TYPE (vexpr) = TREE_TYPE (value);
--- 3779,3785 ----
  		    rtx val;
  		    enum machine_mode mode;
  
! 		    set_curr_insn_location (gimple_location (def));
  
  		    DECL_ARTIFICIAL (vexpr) = 1;
  		    TREE_TYPE (vexpr) = TREE_TYPE (value);
*************** expand_gimple_basic_block (basic_block b
*** 3831,3838 ****
  		      }
  		  }
  	      }
! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}
  
        currently_expanding_gimple_stmt = stmt;
--- 3806,3812 ----
  		      }
  		  }
  	      }
! 	  set_curr_insn_location (sloc);
  	}
  
        currently_expanding_gimple_stmt = stmt;
*************** expand_gimple_basic_block (basic_block b
*** 3847,3854 ****
  	}
        else if (gimple_debug_bind_p (stmt))
  	{
! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();
  	  gimple_stmt_iterator nsi = gsi;
  
  	  for (;;)
--- 3821,3827 ----
  	}
        else if (gimple_debug_bind_p (stmt))
  	{
! 	  location_t sloc = curr_insn_location ();
  	  gimple_stmt_iterator nsi = gsi;
  
  	  for (;;)
*************** expand_gimple_basic_block (basic_block b
*** 3870,3877 ****
  
  	      last = get_last_insn ();
  
! 	      set_curr_insn_source_location (gimple_location (stmt));
! 	      set_curr_insn_block (gimple_block (stmt));
  
  	      if (DECL_P (var))
  		mode = DECL_MODE (var);
--- 3843,3849 ----
  
  	      last = get_last_insn ();
  
! 	      set_curr_insn_location (gimple_location (stmt));
  
  	      if (DECL_P (var))
  		mode = DECL_MODE (var);
*************** expand_gimple_basic_block (basic_block b
*** 3909,3921 ****
  		break;
  	    }
  
! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}
        else if (gimple_debug_source_bind_p (stmt))
  	{
! 	  location_t sloc = get_curr_insn_source_location ();
! 	  tree sblock = get_curr_insn_block ();
  	  tree var = gimple_debug_source_bind_get_var (stmt);
  	  tree value = gimple_debug_source_bind_get_value (stmt);
  	  rtx val;
--- 3881,3891 ----
  		break;
  	    }
  
! 	  set_curr_insn_location (sloc);
  	}
        else if (gimple_debug_source_bind_p (stmt))
  	{
! 	  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;
*************** expand_gimple_basic_block (basic_block b
*** 3923,3930 ****
  
  	  last = get_last_insn ();
  
! 	  set_curr_insn_source_location (gimple_location (stmt));
! 	  set_curr_insn_block (gimple_block (stmt));
  
  	  mode = DECL_MODE (var);
  
--- 3893,3899 ----
  
  	  last = get_last_insn ();
  
! 	  set_curr_insn_location (gimple_location (stmt));
  
  	  mode = DECL_MODE (var);
  
*************** expand_gimple_basic_block (basic_block b
*** 3942,3949 ****
  	      PAT_VAR_LOCATION_LOC (val) = (rtx)value;
  	    }
  
! 	  set_curr_insn_source_location (sloc);
! 	  set_curr_insn_block (sblock);
  	}
        else
  	{
--- 3911,3917 ----
  	      PAT_VAR_LOCATION_LOC (val) = (rtx)value;
  	    }
  
! 	  set_curr_insn_location (sloc);
  	}
        else
  	{
*************** expand_gimple_basic_block (basic_block b
*** 3984,3996 ****
    /* 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 ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb)
  	{
  	  emit_jump (label_rtx_for_bb (e->dest));
--- 3952,3959 ----
    /* Expand implicit goto and convert goto_locus.  */
    FOR_EACH_EDGE (e, ei, bb->succs)
      {
!       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));
*************** construct_exit_block (void)
*** 4110,4121 ****
  
    /* 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)
      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 ();
  
--- 4073,4081 ----
  
    /* Make sure the locus is set to the end of the function, so that
       epilogue line numbers and warnings are set properly.  */
!   if (!IS_UNKNOWN_LOCATION (cfun->function_end_locus))
      input_location = cfun->function_end_locus;
  
    /* Generate rtl for function exit.  */
    expand_function_end ();
  
*************** gimple_expand_cfg (void)
*** 4334,4353 ****
  
    rtl_profile_for_bb (ENTRY_BLOCK_PTR);
  
!   insn_locators_alloc ();
    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
           (DECL_SOURCE_LOCATION (current_function_decl));
        else
!        set_curr_insn_source_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 ();
  
  #ifdef INSN_SCHEDULING
    init_sched_attrs ();
--- 4294,4312 ----
  
    rtl_profile_for_bb (ENTRY_BLOCK_PTR);
  
!   insn_locations_init ();
    if (!DECL_IS_BUILTIN (current_function_decl))
      {
        /* Eventually, all FEs should explicitly set function_start_locus.  */
!       if (IS_UNKNOWN_LOCATION (cfun->function_start_locus))
!        set_curr_insn_location
           (DECL_SOURCE_LOCATION (current_function_decl));
        else
!        set_curr_insn_location (cfun->function_start_locus);
      }
    else
!     set_curr_insn_location (UNKNOWN_LOCATION);
!   prologue_location = curr_insn_location ();
  
  #ifdef INSN_SCHEDULING
    init_sched_attrs ();
*************** gimple_expand_cfg (void)
*** 4517,4524 ****
    free_histograms ();
  
    construct_exit_block ();
!   set_curr_insn_block (DECL_INITIAL (current_function_decl));
!   insn_locators_finalize ();
  
    /* Zap the tree EH table.  */
    set_eh_throw_stmt_table (cfun, NULL);
--- 4476,4482 ----
    free_histograms ();
  
    construct_exit_block ();
!   insn_locations_finalize ();
  
    /* Zap the tree EH table.  */
    set_eh_throw_stmt_table (cfun, NULL);
Index: gcc/cfgcleanup.c
===================================================================
*** gcc/cfgcleanup.c	(revision 190209)
--- gcc/cfgcleanup.c	(working copy)
*************** try_forward_edges (int mode, basic_block
*** 481,493 ****
  		  int new_locus = single_succ_edge (target)->goto_locus;
  		  int locus = goto_locus;
  
! 		  if (new_locus && locus && !locator_eq (new_locus, locus))
  		    new_target = NULL;
  		  else
  		    {
  		      rtx last;
  
! 		      if (new_locus)
  			locus = new_locus;
  
  		      last = BB_END (target);
--- 481,495 ----
  		  int new_locus = single_succ_edge (target)->goto_locus;
  		  int locus = goto_locus;
  
! 		  if (!IS_UNKNOWN_LOCATION (new_locus)
! 		      && !IS_UNKNOWN_LOCATION (locus)
! 		      && new_locus != locus)
  		    new_target = NULL;
  		  else
  		    {
  		      rtx last;
  
! 		      if (!IS_UNKNOWN_LOCATION (new_locus))
  			locus = new_locus;
  
  		      last = BB_END (target);
*************** try_forward_edges (int mode, basic_block
*** 495,507 ****
  			last = prev_nondebug_insn (last);
  
  		      new_locus = last && INSN_P (last)
! 				  ? INSN_LOCATOR (last) : 0;
  
! 		      if (new_locus && locus && !locator_eq (new_locus, locus))
  			new_target = NULL;
  		      else
  			{
! 			  if (new_locus)
  			    locus = new_locus;
  
  			  goto_locus = locus;
--- 497,511 ----
  			last = prev_nondebug_insn (last);
  
  		      new_locus = last && INSN_P (last)
! 				  ? INSN_LOCATION (last) : 0;
  
! 		      if (!IS_UNKNOWN_LOCATION (new_locus)
! 			  && !IS_UNKNOWN_LOCATION (locus)
! 			  && new_locus != locus)
  			new_target = NULL;
  		      else
  			{
! 			  if (!IS_UNKNOWN_LOCATION (new_locus))
  			    locus = new_locus;
  
  			  goto_locus = locus;
Index: gcc/tree-ssa-live.c
===================================================================
*** gcc/tree-ssa-live.c	(revision 190209)
--- gcc/tree-ssa-live.c	(working copy)
*************** remove_unused_scope_block_p (tree scope)
*** 585,591 ****
     else
     /* Verfify that only blocks with source location set
        are entry points to the inlined functions.  */
!      gcc_assert (BLOCK_SOURCE_LOCATION (scope) == UNKNOWN_LOCATION);
  
     TREE_USED (scope) = !unused;
     return unused;
--- 585,591 ----
     else
     /* Verfify that only blocks with source location set
        are entry points to the inlined functions.  */
!      gcc_assert (IS_UNKNOWN_LOCATION (BLOCK_SOURCE_LOCATION (scope)));
  
     TREE_USED (scope) = !unused;
     return unused;
*************** dump_scope_block (FILE *file, int indent
*** 613,619 ****
    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)
      {
        expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (scope));
        fprintf (file, " %s:%i", s.file, s.line);
--- 613,619 ----
    fprintf (file, "\n%*s{ Scope block #%i%s%s",indent, "" , BLOCK_NUMBER (scope),
    	   TREE_USED (scope) ? "" : " (unused)",
  	   BLOCK_ABSTRACT (scope) ? " (abstract)": "");
!   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);
*************** remove_unused_locals (void)
*** 746,758 ****
            FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_ALL_USES)
              {
  	      tree arg = USE_FROM_PTR (arg_p);
  	      mark_all_vars_used (&arg);
              }
          }
  
        FOR_EACH_EDGE (e, ei, bb->succs)
  	if (e->goto_locus)
! 	  TREE_USED (e->goto_block) = true;
      }
  
    /* We do a two-pass approach about the out-of-scope clobbers.  We want
--- 746,763 ----
            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 (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 190209)
--- gcc/lto/lto.c	(working copy)
*************** lto_fixup_prevailing_decls (tree t)
*** 1603,1609 ****
    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));
      }
--- 1603,1608 ----
Index: gcc/tree-streamer-out.c
===================================================================
*** gcc/tree-streamer-out.c	(revision 190209)
--- gcc/tree-streamer-out.c	(working copy)
*************** write_ts_decl_minimal_tree_pointers (str
*** 471,477 ****
  {
    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));
  }
  
  
--- 471,477 ----
  {
    stream_write_tree (ob, DECL_NAME (expr), ref_p);
    stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
!   lto_output_location (ob, LOCATION_LOCUS (DECL_SOURCE_LOCATION (expr)));
  }
  
  
*************** write_ts_exp_tree_pointers (struct outpu
*** 668,674 ****
    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));
    stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
  }
  
--- 668,674 ----
    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, LOCATION_LOCUS (EXPR_LOCATION (expr)));
    stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
  }
  
Index: gcc/rtl.c
===================================================================
*** gcc/rtl.c	(revision 190209)
--- gcc/rtl.c	(working copy)
*************** rtx_equal_p_cb (const_rtx x, const_rtx y
*** 440,446 ****
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && locator_eq (XINT (x, i), XINT (y, i)))
  		break;
  #endif
  	      return 0;
--- 440,446 ----
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && XINT (x, i) == XINT (y, i))
  		break;
  #endif
  	      return 0;
*************** rtx_equal_p (const_rtx x, const_rtx y)
*** 579,585 ****
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && locator_eq (XINT (x, i), XINT (y, i)))
  		break;
  #endif
  	      return 0;
--- 579,585 ----
  #ifndef GENERATOR_FILE
  	      if (((code == ASM_OPERANDS && i == 6)
  		   || (code == ASM_INPUT && i == 1))
! 		  && XINT (x, i) == XINT (y, i))
  		break;
  #endif
  	      return 0;
Index: gcc/rtl.h
===================================================================
*** gcc/rtl.h	(revision 190209)
--- gcc/rtl.h	(working copy)
*************** extern void rtl_check_failed_flag (const
*** 747,752 ****
--- 747,753 ----
  #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)
*************** extern void rtl_check_failed_flag (const
*** 810,822 ****
  /* The body of an insn.  */
  #define PATTERN(INSN)	XEXP (INSN, 4)
  
! #define INSN_LOCATOR(INSN) XINT (INSN, 5)
  /* 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 ()))
  
  /* Code number of instruction, from when it was recognized.
     -1 means this instruction has not been recognized yet.  */
--- 811,823 ----
  /* The body of an insn.  */
  #define PATTERN(INSN)	XEXP (INSN, 4)
  
! #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) ? \
! 			 INSN_LOCATION (X) : UNKNOWN_LOCATION)
  
  /* Code number of instruction, from when it was recognized.
     -1 means this instruction has not been recognized yet.  */
*************** extern rtx prev_cc0_setter (rtx);
*** 1815,1826 ****
  /* 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);
  
  /* In jump.c */
  extern enum rtx_code reverse_condition (enum rtx_code);
--- 1816,1823 ----
  /* In emit-rtl.c  */
  extern int insn_line (const_rtx);
  extern const char * insn_file (const_rtx);
  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);
*************** extern const struct rtl_hooks general_rt
*** 2657,2670 ****
  /* 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 bool optimize_insn_for_size_p (void);
  extern bool optimize_insn_for_speed_p (void);
  
--- 2654,2663 ----
  /* Keep this for the nonce.  */
  #define gen_lowpart rtl_hooks.gen_lowpart
  
! 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 190209)
--- gcc/tree-inline.c	(working copy)
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 799,808 ****
        /* 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);
--- 799,804 ----
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 840,852 ****
  	{
  	  /* 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.  */
  	  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,
--- 836,844 ----
  	{
  	  /* Variable substitution need not be simple.  In particular,
  	     the MEM_REF substitution above.  Make sure that
! 	     TREE_CONSTANT and friends are up-to-date.  */
  	  int invariant = is_gimple_min_invariant (*tp);
  	  walk_tree (&TREE_OPERAND (*tp, 0), remap_gimple_op_r, data, NULL);
  	  recompute_tree_invariant_for_addr_expr (*tp);
  
  	  /* If this used to be invariant, but is not any longer,
*************** remap_gimple_op_r (tree *tp, int *walk_s
*** 858,863 ****
--- 850,871 ----
  	}
      }
  
+   /* 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;
  }
*************** copy_tree_body_r (tree *tp, int *walk_su
*** 1075,1085 ****
  	      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;
  	}
  
        if (TREE_CODE (*tp) != OMP_CLAUSE)
--- 1083,1092 ----
  	      tree *n;
  	      n = (tree *) pointer_map_contains (id->decl_map,
  						 TREE_BLOCK (*tp));
  	      if (n)
  		new_block = *n;
  	    }
! 	  TREE_SET_BLOCK (*tp, new_block);
  	}
  
        if (TREE_CODE (*tp) != OMP_CLAUSE)
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 1949,1954 ****
--- 1956,1962 ----
  	      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
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 1960,1968 ****
  
  	      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.  */
--- 1968,1974 ----
*************** copy_phis_for_bb (basic_block bb, copy_b
*** 1975,1982 ****
  		  gsi_insert_seq_on_edge (new_edge, stmts);
  		  inserted = true;
  		}
  	      add_phi_arg (new_phi, new_arg, new_edge,
! 			   gimple_phi_arg_location_from_edge (phi, old_edge));
  	    }
  	}
      }
--- 1981,1999 ----
  		  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,
! 			   COMBINE_LOCATION_DATA (locus, block));
  	    }
  	}
      }
*************** expand_call_inline (basic_block bb, gimp
*** 3847,3853 ****
    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);
  
    /* Local declarations will be replaced by their equivalents in this
       map.  */
--- 3864,3871 ----
    id->block = make_node (BLOCK);
    BLOCK_ABSTRACT_ORIGIN (id->block) = fn;
    BLOCK_SOURCE_LOCATION (id->block) = input_location;
!   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 190209)
--- gcc/tree-streamer-in.c	(working copy)
*************** lto_input_ts_exp_tree_pointers (struct l
*** 776,782 ****
  
    loc = lto_input_location (ib, data_in);
    SET_EXPR_LOCATION (expr, loc);
!   TREE_BLOCK (expr) = stream_read_tree (ib, data_in);
  }
  
  
--- 776,782 ----
  
    loc = lto_input_location (ib, data_in);
    SET_EXPR_LOCATION (expr, loc);
!   TREE_SET_BLOCK (expr, stream_read_tree (ib, data_in));
  }
  
  
Index: gcc/combine.c
===================================================================
*** gcc/combine.c	(revision 190209)
--- gcc/combine.c	(working copy)
*************** try_combine (rtx i3, rtx i2, rtx i1, rtx
*** 2741,2747 ****
  
  	  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);
  
  	  SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
  	  SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
--- 2741,2747 ----
  
  	  i1 = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
  			     BLOCK_FOR_INSN (i2), XVECEXP (PATTERN (i2), 0, 1),
! 			     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 190209)
--- gcc/tree-outof-ssa.c	(working copy)
*************** set_location_for_edge (edge e)
*** 108,115 ****
  {
    if (e->goto_locus)
      {
!       set_curr_insn_source_location (e->goto_locus);
!       set_curr_insn_block (e->goto_block);
      }
    else
      {
--- 108,114 ----
  {
    if (e->goto_locus)
      {
!       set_curr_insn_location (e->goto_locus);
      }
    else
      {
*************** set_location_for_edge (edge e)
*** 125,132 ****
  		continue;
  	      if (gimple_has_location (stmt) || gimple_block (stmt))
  		{
! 		  set_curr_insn_source_location (gimple_location (stmt));
! 		  set_curr_insn_block (gimple_block (stmt));
  		  return;
  		}
  	    }
--- 124,130 ----
  		continue;
  	      if (gimple_has_location (stmt) || gimple_block (stmt))
  		{
! 		  set_curr_insn_location (gimple_location (stmt));
  		  return;
  		}
  	    }
*************** insert_partition_copy_on_edge (edge e, i
*** 191,197 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);
  
    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (SA.partition_to_pseudo[dest],
--- 189,195 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_location (locus);
  
    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (SA.partition_to_pseudo[dest],
*************** insert_value_copy_on_edge (edge e, int d
*** 228,234 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);
  
    start_sequence ();
  
--- 226,232 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_location (locus);
  
    start_sequence ();
  
*************** insert_rtx_to_part_on_edge (edge e, int 
*** 284,290 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_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
--- 282,288 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (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
*************** insert_part_to_rtx_on_edge (edge e, rtx 
*** 320,326 ****
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (locus)
!     set_curr_insn_source_location (locus);
  
    var = partition_to_var (SA.map, src);
    seq = emit_partition_copy (dest,
--- 318,324 ----
    set_location_for_edge (e);
    /* If a locus is provided, override the default.  */
    if (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 190209)
--- gcc/basic-block.h	(working copy)
*************** struct GTY(()) edge_def {
*** 47,54 ****
    /* Auxiliary info specific to a pass.  */
    PTR GTY ((skip (""))) aux;
  
!   /* Location of any goto implicit in the edge and associated BLOCK.  */
!   tree goto_block;
    location_t goto_locus;
  
    /* The index number corresponding to this edge in the edge vector
--- 47,53 ----
    /* Auxiliary info specific to a pass.  */
    PTR GTY ((skip (""))) aux;
  
!   /* 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 190209)
--- gcc/gimple.h	(working copy)
*************** struct GTY(()) gimple_statement_base {
*** 210,219 ****
       and the prev pointer being the last.  */
    gimple next;
    gimple GTY((skip)) prev;
- 
-   /* [ WORD 6 ]
-      Lexical block holding this statement.  */
-   tree block;
  };
  
  
--- 210,215 ----
*************** gimple_bb (const_gimple g)
*** 1198,1204 ****
  static inline tree
  gimple_block (const_gimple g)
  {
!   return g->gsbase.block;
  }
  
  
--- 1194,1200 ----
  static inline tree
  gimple_block (const_gimple g)
  {
!   return LOCATION_BLOCK (g->gsbase.location);
  }
  
  
*************** gimple_block (const_gimple g)
*** 1207,1213 ****
  static inline void
  gimple_set_block (gimple g, tree block)
  {
!   g->gsbase.block = block;
  }
  
  
--- 1203,1209 ----
  static inline void
  gimple_set_block (gimple g, tree block)
  {
!   g->gsbase.location = COMBINE_LOCATION_DATA (g->gsbase.location, block);
  }
  
  
*************** gimple_set_location (gimple g, location_
*** 1242,1248 ****
  static inline bool
  gimple_has_location (const_gimple g)
  {
!   return gimple_location (g) != UNKNOWN_LOCATION;
  }
  
  
--- 1238,1244 ----
  static inline bool
  gimple_has_location (const_gimple g)
  {
!   return !IS_UNKNOWN_LOCATION (gimple_location (g));
  }
  
  
Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c	(revision 190209)
--- gcc/tree-cfg.c	(working copy)
*************** make_cond_expr_edges (basic_block bb)
*** 809,823 ****
    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.  */
--- 809,819 ----
*************** make_goto_expr_edges (basic_block bb)
*** 1027,1034 ****
        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;
      }
--- 1023,1028 ----
*************** gimple_can_merge_blocks_p (basic_block a
*** 1504,1510 ****
  
    /* When not optimizing, don't merge if we'd lose goto_locus.  */
    if (!optimize
!       && single_succ_edge (a)->goto_locus != UNKNOWN_LOCATION)
      {
        location_t goto_locus = single_succ_edge (a)->goto_locus;
        gimple_stmt_iterator prev, next;
--- 1498,1504 ----
  
    /* When not optimizing, don't merge if we'd lose goto_locus.  */
    if (!optimize
!       && single_succ_edge (a)->goto_locus)
      {
        location_t goto_locus = single_succ_edge (a)->goto_locus;
        gimple_stmt_iterator prev, next;
*************** move_stmt_op (tree *tp, int *walk_subtre
*** 5993,6001 ****
    tree t = *tp;
  
    if (EXPR_P (t))
!     /* We should never have TREE_BLOCK set on non-statements.  */
!     gcc_assert (!TREE_BLOCK (t));
! 
    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
      {
        if (TREE_CODE (t) == SSA_NAME)
--- 5987,5993 ----
    tree t = *tp;
  
    if (EXPR_P (t))
!     ;
    else if (DECL_P (t) || TREE_CODE (t) == SSA_NAME)
      {
        if (TREE_CODE (t) == SSA_NAME)
*************** move_block_to_fn (struct function *dest_
*** 6295,6306 ****
      }
  
    FOR_EACH_EDGE (e, ei, bb->succs)
!     if (e->goto_locus)
        {
! 	tree block = e->goto_block;
  	if (d->orig_block == NULL_TREE
  	    || block == d->orig_block)
! 	  e->goto_block = d->new_block;
  #ifdef ENABLE_CHECKING
  	else if (block != d->new_block)
  	  {
--- 6287,6298 ----
      }
  
    FOR_EACH_EDGE (e, ei, bb->succs)
!     if (!IS_UNKNOWN_LOCATION (e->goto_locus))
        {
! 	tree block = LOCATION_BLOCK (e->goto_locus);
  	if (d->orig_block == NULL_TREE
  	    || block == d->orig_block)
! 	  e->goto_locus = COMBINE_LOCATION_DATA (e->goto_locus, d->new_block);
  #ifdef ENABLE_CHECKING
  	else if (block != d->new_block)
  	  {
Index: gcc/config/alpha/alpha.c
===================================================================
*** gcc/config/alpha/alpha.c	(revision 190209)
--- gcc/config/alpha/alpha.c	(working copy)
*************** alpha_output_mi_thunk_osf (FILE *file, t
*** 8362,8368 ****
       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);
--- 8362,8367 ----
Index: gcc/config/sparc/sparc.c
===================================================================
*** gcc/config/sparc/sparc.c	(revision 190209)
--- gcc/config/sparc/sparc.c	(working copy)
*************** sparc_output_mi_thunk (FILE *file, tree 
*** 10654,10660 ****
       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);
--- 10654,10659 ----
Index: gcc/config/i386/i386.c
===================================================================
*** gcc/config/i386/i386.c	(revision 190209)
--- gcc/config/i386/i386.c	(working copy)
*************** x86_output_mi_thunk (FILE *file,
*** 33227,33233 ****
    /* 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);
--- 33227,33232 ----
Index: gcc/config/tilegx/tilegx.c
===================================================================
*** gcc/config/tilegx/tilegx.c	(revision 190209)
--- gcc/config/tilegx/tilegx.c	(working copy)
*************** tilegx_output_mi_thunk (FILE *file, tree
*** 4804,4810 ****
       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);
--- 4804,4809 ----
Index: gcc/config/sh/sh.c
===================================================================
*** gcc/config/sh/sh.c	(revision 190209)
--- gcc/config/sh/sh.c	(working copy)
*************** sh_output_mi_thunk (FILE *file, tree thu
*** 11991,11997 ****
       the insns emitted.  Note that use_thunk calls
       assemble_start_function and assemble_end_function.  */
  
-   insn_locators_alloc ();
    insns = get_insns ();
  
    if (optimize > 0)
--- 11991,11996 ----
Index: gcc/config/ia64/ia64.c
===================================================================
*** gcc/config/ia64/ia64.c	(revision 190209)
--- gcc/config/ia64/ia64.c	(working copy)
*************** ia64_output_mi_thunk (FILE *file, tree t
*** 10848,10854 ****
       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);
--- 10848,10853 ----
Index: gcc/config/rs6000/rs6000.c
===================================================================
*** gcc/config/rs6000/rs6000.c	(revision 190209)
--- gcc/config/rs6000/rs6000.c	(working copy)
*************** rs6000_output_mi_thunk (FILE *file, tree
*** 21689,21695 ****
       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);
--- 21689,21694 ----
Index: gcc/config/score/score.c
===================================================================
*** gcc/config/score/score.c	(revision 190209)
--- gcc/config/score/score.c	(working copy)
*************** score_output_mi_thunk (FILE *file, tree 
*** 505,511 ****
    /* 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);
--- 505,510 ----
Index: gcc/config/tilepro/tilepro.c
===================================================================
*** gcc/config/tilepro/tilepro.c	(revision 190209)
--- gcc/config/tilepro/tilepro.c	(working copy)
*************** tilepro_asm_output_mi_thunk (FILE *file,
*** 4407,4413 ****
       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);
--- 4407,4412 ----
Index: gcc/config/mips/mips.c
===================================================================
*** gcc/config/mips/mips.c	(revision 190209)
--- gcc/config/mips/mips.c	(working copy)
*************** mips_output_mi_thunk (FILE *file, tree t
*** 15746,15752 ****
    /* 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);
--- 15746,15751 ----
Index: gcc/cfgrtl.c
===================================================================
*** gcc/cfgrtl.c	(revision 190209)
--- gcc/cfgrtl.c	(working copy)
*************** rtl_split_block (basic_block bb, void *i
*** 720,738 ****
  static bool
  unique_locus_on_edge_between_p (basic_block a, basic_block b)
  {
!   const int goto_locus = EDGE_SUCC (a, 0)->goto_locus;
    rtx insn, end;
  
!   if (!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))
      insn = PREV_INSN (insn);
  
!   if (insn != end && locator_eq (INSN_LOCATOR (insn), goto_locus))
      return false;
  
    /* Then scan block B forward.  */
--- 720,738 ----
  static bool
  unique_locus_on_edge_between_p (basic_block a, basic_block b)
  {
!   const location_t goto_locus = EDGE_SUCC (a, 0)->goto_locus;
    rtx insn, end;
  
!   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_HAS_LOCATION (insn)))
      insn = PREV_INSN (insn);
  
!   if (insn != end && INSN_LOCATION (insn) == goto_locus)
      return false;
  
    /* Then scan block B forward.  */
*************** unique_locus_on_edge_between_p (basic_bl
*** 743,750 ****
        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))
  	return false;
      }
  
--- 743,750 ----
        while (insn != end && !NONDEBUG_INSN_P (insn))
  	insn = NEXT_INSN (insn);
  
!       if (insn != end && INSN_HAS_LOCATION (insn)
! 	  && INSN_LOCATION (insn) == goto_locus)
  	return false;
      }
  
*************** emit_nop_for_unique_locus_between (basic
*** 761,767 ****
      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;
  }
  
  /* Blocks A and B are to be merged into a single block A.  The insns
--- 761,767 ----
      return;
  
    BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
!   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
*************** force_nonfallthru_and_redirect (edge e, 
*** 1478,1484 ****
    else
      jump_block = e->src;
  
!   if (e->goto_locus && e->goto_block == NULL)
      loc = e->goto_locus;
    else
      loc = 0;
--- 1478,1484 ----
    else
      jump_block = e->src;
  
!   if (!IS_UNKNOWN_LOCATION (e->goto_locus))
      loc = e->goto_locus;
    else
      loc = 0;
*************** fixup_reorder_chain (void)
*** 3336,3342 ****
          edge_iterator ei;
  
          FOR_EACH_EDGE (e, ei, bb->succs)
! 	  if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
  	    {
  	      edge e2;
  	      edge_iterator ei2;
--- 3336,3343 ----
          edge_iterator ei;
  
          FOR_EACH_EDGE (e, ei, bb->succs)
! 	  if (!IS_UNKNOWN_LOCATION (e->goto_locus)
! 	      && !(e->flags & EDGE_ABNORMAL))
  	    {
  	      edge e2;
  	      edge_iterator ei2;
*************** fixup_reorder_chain (void)
*** 3346,3360 ****
  	      insn = BB_END (e->src);
  	      end = PREV_INSN (BB_HEAD (e->src));
  	      while (insn != end
! 		     && (!NONDEBUG_INSN_P (insn) || INSN_LOCATOR (insn) == 0))
  		insn = PREV_INSN (insn);
  	      if (insn != end
! 		  && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
  		continue;
  	      if (simplejump_p (BB_END (e->src))
! 		  && INSN_LOCATOR (BB_END (e->src)) == 0)
  		{
! 		  INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
  		  continue;
  		}
  	      dest = e->dest;
--- 3347,3361 ----
  	      insn = BB_END (e->src);
  	      end = PREV_INSN (BB_HEAD (e->src));
  	      while (insn != end
! 		     && (!NONDEBUG_INSN_P (insn) || !INSN_HAS_LOCATION (insn)))
  		insn = PREV_INSN (insn);
  	      if (insn != end
! 		  && INSN_LOCATION (insn) == e->goto_locus)
  		continue;
  	      if (simplejump_p (BB_END (e->src))
! 		  && !INSN_HAS_LOCATION (BB_END (e->src)))
  		{
! 		  INSN_LOCATION (BB_END (e->src)) = e->goto_locus;
  		  continue;
  		}
  	      dest = e->dest;
*************** fixup_reorder_chain (void)
*** 3370,3393 ****
  		  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))
  		    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;
  
  	      /* 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
  		    && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
! 		    && locator_eq (e->goto_locus, e2->goto_locus))
  		  redirect_edge_and_branch (e2, nb);
  		else
  		  ei_next (&ei2);
--- 3371,3394 ----
  		  end = NEXT_INSN (BB_END (dest));
  		  while (insn != end && !NONDEBUG_INSN_P (insn))
  		    insn = NEXT_INSN (insn);
! 		  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_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 (!IS_UNKNOWN_LOCATION (e2->goto_locus)
  		    && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
! 		    && e->goto_locus == e2->goto_locus)
  		  redirect_edge_and_branch (e2, nb);
  		else
  		  ei_next (&ei2);
*************** cfg_layout_merge_blocks (basic_block a, 
*** 4087,4093 ****
      }
  
    /* If B was a forwarder block, propagate the locus on the edge.  */
!   if (forwarder_p && !EDGE_SUCC (b, 0)->goto_locus)
      EDGE_SUCC (b, 0)->goto_locus = EDGE_SUCC (a, 0)->goto_locus;
  
    if (dump_file)
--- 4088,4094 ----
      }
  
    /* If B was a forwarder block, propagate the locus on the edge.  */
!   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 190209)
--- gcc/stmt.c	(working copy)
*************** emit_case_nodes (rtx index, case_node_pt
*** 2397,2403 ****
  		 then emit the code for one side at a time.  */
  
  	      tree test_label
! 		= build_decl (CURR_INSN_LOCATION,
  			      LABEL_DECL, NULL_TREE, NULL_TREE);
  
  	      /* See if the value is on the right.  */
--- 2397,2403 ----
  		 then emit the code for one side at a time.  */
  
  	      tree test_label
! 		= build_decl (curr_insn_location (),
  			      LABEL_DECL, NULL_TREE, NULL_TREE);
  
  	      /* See if the value is on the right.  */
*************** emit_case_nodes (rtx index, case_node_pt
*** 2521,2527 ****
  	      /* Right hand node requires testing.
  		 Branch to a label where we will handle it later.  */
  
! 	      test_label = build_decl (CURR_INSN_LOCATION,
  				       LABEL_DECL, NULL_TREE, NULL_TREE);
  	      emit_cmp_and_jump_insns (index,
  				       convert_modes
--- 2521,2527 ----
  	      /* Right hand node requires testing.
  		 Branch to a label where we will handle it later.  */
  
! 	      test_label = build_decl (curr_insn_location (),
  				       LABEL_DECL, NULL_TREE, NULL_TREE);
  	      emit_cmp_and_jump_insns (index,
  				       convert_modes
Index: libcpp/line-map.c
===================================================================
*** libcpp/line-map.c	(revision 190209)
--- libcpp/line-map.c	(working copy)
*************** along with this program; see the file CO
*** 25,30 ****
--- 25,31 ----
  #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 *,
*************** static source_location linemap_macro_loc
*** 50,55 ****
--- 51,185 ----
  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
*************** linemap_position_for_line_and_column (st
*** 509,514 ****
--- 639,646 ----
  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);
*************** linemap_ordinary_map_lookup (struct line
*** 525,530 ****
--- 657,665 ----
    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;
  
*************** linemap_macro_map_lookup (struct line_ma
*** 570,575 ****
--- 705,713 ----
    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)
*************** linemap_macro_map_loc_to_def_point (cons
*** 648,653 ****
--- 786,794 ----
  {
    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);
*************** linemap_macro_map_loc_unwind_toward_spel
*** 672,677 ****
--- 813,821 ----
  {
    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);
*************** linemap_get_expansion_line (struct line_
*** 696,701 ****
--- 840,848 ----
  {
    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;
  
*************** linemap_get_expansion_filename (struct l
*** 720,725 ****
--- 867,875 ----
  {
    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;
  
*************** linemap_location_in_system_header_p (str
*** 754,759 ****
--- 904,912 ----
  {
    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;
  
*************** bool
*** 793,798 ****
--- 946,954 ----
  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)));
*************** linemap_macro_loc_to_spelling_point (str
*** 933,938 ****
--- 1089,1097 ----
  {
    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)
*************** linemap_macro_loc_to_def_point (struct l
*** 967,972 ****
--- 1126,1134 ----
  {
    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)
*************** linemap_macro_loc_to_exp_point (struct l
*** 1005,1010 ****
--- 1167,1175 ----
  {
    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)
*************** linemap_resolve_location (struct line_ma
*** 1074,1079 ****
--- 1239,1247 ----
  			  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
*************** linemap_unwind_toward_expansion (struct 
*** 1121,1126 ****
--- 1289,1297 ----
    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);
*************** linemap_unwind_to_first_non_reserved_loc
*** 1157,1162 ****
--- 1328,1336 ----
    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;
*************** linemap_expand_location (struct line_map
*** 1198,1203 ****
--- 1372,1382 ----
    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.
*************** linemap_dump_location (struct line_maps 
*** 1290,1295 ****
--- 1469,1477 ----
    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;
  
Index: libcpp/include/line-map.h
===================================================================
*** libcpp/include/line-map.h	(revision 190209)
--- libcpp/include/line-map.h	(working copy)
*************** struct GTY(()) line_map_ordinary {
*** 89,95 ****
  
  /* This is the highest possible source location encoded within an
     ordinary or macro map.  */
! #define MAX_SOURCE_LOCATION 0xFFFFFFFF
  
  struct cpp_hashnode;
  
--- 89,95 ----
  
  /* This is the highest possible source location encoded within an
     ordinary or macro map.  */
! #define MAX_SOURCE_LOCATION 0x7FFFFFFF
  
  struct cpp_hashnode;
  
*************** struct GTY(()) line_maps {
*** 408,413 ****
--- 408,423 ----
  #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 *);
  
*************** typedef struct
*** 594,599 ****
--- 604,611 ----
  
    int column;
  
+   void *data;
+ 
    /* In a system header?. */
    bool sysp;
  } expanded_location;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-07 14:56                               ` Dehao Chen
@ 2012-09-07 17:29                                 ` Diego Novillo
  2012-09-08 22:26                                   ` Dehao Chen
  2012-09-13 16:49                                 ` Tom Tromey
  1 sibling, 1 reply; 93+ messages in thread
From: Diego Novillo @ 2012-09-07 17:29 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Richard Guenther, Dodji Seketeli, gcc-patches, Jakub Jelinek,
	Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

On 2012-09-07 10:55 , Dehao Chen wrote:

> gcc/ChangeLog:
> 2012-08-01  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.
> 	* dewarf2out.c (add_src_coords_attributes): Likewise.

s/dewarf2out/dwarf2out/

> 	* 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-08-01  Dehao Chen  <dehao@google.com>
>
> 	* lto/lto.c (lto_fixup_prevailing_decls): Remove tree.exp.block field.
>
> libcpp/ChangeLog:
> 2012-08-01  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.
>

> ===================================================================
> *** gcc/final.c	(revision 190209)
> --- gcc/final.c	(working copy)
> *************** reemit_insn_block_notes (void)
> *** 1605,1611 ****
>   					     insn_scope (XVECEXP (body, 0, i)));
>   	}
>         if (! this_block)
> ! 	continue;
>
>         if (this_block != cur_block)
>   	{
> --- 1605,1611 ----
>   					     insn_scope (XVECEXP (body, 0, i)));
>   	}
>         if (! this_block)
> ! 	this_block = DECL_INITIAL (cfun->decl);
>

So, this will default to the start of the function when all else fails?

> --- 5900,5965 ----
>   	    gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
>   }
>
> ! 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;
>
> ! /* Allocate insn location datastructure.  */
>   void
> ! insn_locations_init (void)
>   {
> !   prologue_location = epilogue_location = 0;
>     curr_location = UNKNOWN_LOCATION;
>     last_location = UNKNOWN_LOCATION;
>   }
>
>   /* At the end of emit stage, clear current location.  */
>   void
> ! insn_locations_finalize (void)
>   {
> !   epilogue_location = curr_location;
> !   curr_location = UNKNOWN_LOCATION;
>   }
>
>   /* Set current location.  */
>   void
> ! set_curr_insn_location (location_t location)
>   {
>     curr_location = location;
>   }
>
>   /* Get current location.  */
>   location_t
> ! curr_insn_location (void)
>   {
>     return curr_location;
>   }
>
>   /* Return lexical scope block insn belongs to.  */
>   tree
>   insn_scope (const_rtx insn)
>   {
> !   return LOCATION_BLOCK (INSN_LOCATION (insn));
>   }
>
>   /* Return line number of the statement that produced this insn.  */
>   int
>   insn_line (const_rtx insn)
>   {
> !   return LOCATION_LINE (INSN_LOCATION (insn));
>   }
>
>   /* Return source file of the statement that produced this insn.  */
>   const char *
>   insn_file (const_rtx insn)
>   {
> !   return LOCATION_FILE (INSN_LOCATION (insn));
>   }
>
>   /* 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.  */

I like this!


The patch looks fine to me.  Your changes to the backends seem innocuous 
enough, but please be on the lookout for reported build failures.


Diego.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-07 17:29                                 ` Diego Novillo
@ 2012-09-08 22:26                                   ` Dehao Chen
  2012-09-10 10:01                                     ` Richard Guenther
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-09-08 22:26 UTC (permalink / raw)
  To: Diego Novillo
  Cc: Richard Guenther, Dodji Seketeli, gcc-patches, Jakub Jelinek,
	Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

[-- Attachment #1: Type: text/plain, Size: 9733 bytes --]

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));
   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)

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.

[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 94478 bytes --]

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;
 \f
 /* 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 ();
 }
 \f
 /* 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;
-}
-\f
-
-/* 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);
-}
-\f
-
 /* 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;
 

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-08 22:26                                   ` Dehao Chen
@ 2012-09-10 10:01                                     ` Richard Guenther
  2012-09-10 15:28                                       ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-09-10 10:01 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Diego Novillo, Dodji Seketeli, gcc-patches, Jakub Jelinek,
	Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-10 10:01                                     ` Richard Guenther
@ 2012-09-10 15:28                                       ` Dehao Chen
  2012-09-10 16:42                                         ` Jan Hubicka
  2012-09-11  8:51                                         ` Richard Guenther
  0 siblings, 2 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-10 15:28 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Diego Novillo, Dodji Seketeli, gcc-patches, Jakub Jelinek,
	Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-10 15:28                                       ` Dehao Chen
@ 2012-09-10 16:42                                         ` Jan Hubicka
  2012-09-10 17:32                                           ` Dehao Chen
  2012-09-13  7:10                                           ` Dehao Chen
  2012-09-11  8:51                                         ` Richard Guenther
  1 sibling, 2 replies; 93+ messages in thread
From: Jan Hubicka @ 2012-09-10 16:42 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Richard Guenther, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-10 16:42                                         ` Jan Hubicka
@ 2012-09-10 17:32                                           ` Dehao Chen
  2012-09-13  7:10                                           ` Dehao Chen
  1 sibling, 0 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-10 17:32 UTC (permalink / raw)
  To: Jan Hubicka
  Cc: Richard Guenther, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-10 15:28                                       ` Dehao Chen
  2012-09-10 16:42                                         ` Jan Hubicka
@ 2012-09-11  8:51                                         ` Richard Guenther
  2012-09-11 13:30                                           ` Michael Matz
  1 sibling, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-09-11  8:51 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Diego Novillo, Dodji Seketeli, gcc-patches, Jakub Jelinek,
	Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson, Michael Matz

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-11  8:51                                         ` Richard Guenther
@ 2012-09-11 13:30                                           ` Michael Matz
  2012-09-11 14:09                                             ` Richard Guenther
  0 siblings, 1 reply; 93+ messages in thread
From: Michael Matz @ 2012-09-11 13:30 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Dehao Chen, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-11 13:30                                           ` Michael Matz
@ 2012-09-11 14:09                                             ` Richard Guenther
       [not found]                                               ` <CAO2gOZV8SP-sOVEJBEsvF+M3yiKwtw7yWarfhZ1xeCVYjE_7KA@mail.gmail.com>
  0 siblings, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-09-11 14:09 UTC (permalink / raw)
  To: Michael Matz
  Cc: Dehao Chen, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
       [not found]                                               ` <CAO2gOZV8SP-sOVEJBEsvF+M3yiKwtw7yWarfhZ1xeCVYjE_7KA@mail.gmail.com>
@ 2012-09-11 15:33                                                 ` Michael Matz
  2012-09-11 16:00                                                   ` Dehao Chen
  2012-09-12  9:08                                                   ` Richard Guenther
  0 siblings, 2 replies; 93+ messages in thread
From: Michael Matz @ 2012-09-11 15:33 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Richard Guenther, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-11 15:33                                                 ` Michael Matz
@ 2012-09-11 16:00                                                   ` Dehao Chen
  2012-09-12  5:06                                                     ` Dehao Chen
  2012-09-12  9:08                                                   ` Richard Guenther
  1 sibling, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-09-11 16:00 UTC (permalink / raw)
  To: Michael Matz
  Cc: Richard Guenther, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-11 16:00                                                   ` Dehao Chen
@ 2012-09-12  5:06                                                     ` Dehao Chen
  2012-09-12  5:18                                                       ` Xinliang David Li
  2012-09-12  9:14                                                       ` Richard Guenther
  0 siblings, 2 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-12  5:06 UTC (permalink / raw)
  To: Michael Matz
  Cc: Richard Guenther, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12  5:06                                                     ` Dehao Chen
@ 2012-09-12  5:18                                                       ` Xinliang David Li
  2012-09-12  9:14                                                       ` Richard Guenther
  1 sibling, 0 replies; 93+ messages in thread
From: Xinliang David Li @ 2012-09-12  5:18 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Michael Matz, Richard Guenther, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-11 15:33                                                 ` Michael Matz
  2012-09-11 16:00                                                   ` Dehao Chen
@ 2012-09-12  9:08                                                   ` Richard Guenther
  2012-09-12 12:14                                                     ` Michael Matz
  1 sibling, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-09-12  9:08 UTC (permalink / raw)
  To: Michael Matz
  Cc: Dehao Chen, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12  5:06                                                     ` Dehao Chen
  2012-09-12  5:18                                                       ` Xinliang David Li
@ 2012-09-12  9:14                                                       ` Richard Guenther
  2012-09-12 16:39                                                         ` Xinliang David Li
  1 sibling, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-09-12  9:14 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Michael Matz, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12  9:08                                                   ` Richard Guenther
@ 2012-09-12 12:14                                                     ` Michael Matz
  2012-09-12 13:23                                                       ` Richard Guenther
  0 siblings, 1 reply; 93+ messages in thread
From: Michael Matz @ 2012-09-12 12:14 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Dehao Chen, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 12:14                                                     ` Michael Matz
@ 2012-09-12 13:23                                                       ` Richard Guenther
  2012-09-12 13:24                                                         ` Michael Matz
  0 siblings, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-09-12 13:23 UTC (permalink / raw)
  To: Michael Matz
  Cc: Dehao Chen, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 13:23                                                       ` Richard Guenther
@ 2012-09-12 13:24                                                         ` Michael Matz
  2012-09-12 14:18                                                           ` Michael Matz
  0 siblings, 1 reply; 93+ messages in thread
From: Michael Matz @ 2012-09-12 13:24 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Dehao Chen, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 13:24                                                         ` Michael Matz
@ 2012-09-12 14:18                                                           ` Michael Matz
  2012-09-12 14:37                                                             ` Martin Jambor
  2012-09-19  9:40                                                             ` Martin Jambor
  0 siblings, 2 replies; 93+ messages in thread
From: Michael Matz @ 2012-09-12 14:18 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Dehao Chen, Diego Novillo, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson, Martin Jambor

Hi,

On Wed, 12 Sep 2012, Michael Matz wrote:

> > 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.

ipa-prop creates the problem.  Its tree mapping can contain expressions, 
expressions can have locations, locations now have blocks.  The tree maps 
are stored as part of jump functions, and hence as part of node summaries.  
Node summaries are global, hence blocks, and therefore block vars can be 
placed in the global blob.

That's not supposed to happen.  The patch below fixes this instance of the 
problem and makes the testcase work with Dehaos patch with the 
LTO_NO_PREVAIL call added back in.


Ciao,
Michael.
------------
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 190803)
+++ lto-cgraph.c	(working copy)
@@ -1373,6 +1373,7 @@ output_node_opt_summary (struct output_b
          mechanism to store function local declarations into summaries.  */
       gcc_assert (parm);
       streamer_write_uhwi (ob, parm_num);
+      gcc_assert (IS_UNKNOWN_LOCATION (EXPR_LOCATION (map->new_tree)));
       stream_write_tree (ob, map->new_tree, true);
       bp = bitpack_create (ob->main_stream);
       bp_pack_value (&bp, map->replace_p, 1);
Index: ipa-prop.c
===================================================================
--- ipa-prop.c	(revision 190803)
+++ ipa-prop.c	(working copy)
@@ -1378,7 +1378,11 @@ ipa_compute_jump_functions_for_edge (str
       tree arg = gimple_call_arg (call, n);
 
       if (is_gimple_ip_invariant (arg))
-	ipa_set_jf_constant (jfunc, arg);
+	{
+	  arg = unshare_expr (arg);
+	  SET_EXPR_LOCATION (arg, UNKNOWN_LOCATION);
+	  ipa_set_jf_constant (jfunc, arg);
+	}
       else if (!is_gimple_reg_type (TREE_TYPE (arg))
 	       && TREE_CODE (arg) == PARM_DECL)
 	{
@@ -3154,6 +3158,7 @@ ipa_write_jump_function (struct output_b
       stream_write_tree (ob, jump_func->value.known_type.component_type, true);
       break;
     case IPA_JF_CONST:
+      gcc_assert (IS_UNKNOWN_LOCATION (EXPR_LOCATION (jump_func->value.constant)));
       stream_write_tree (ob, jump_func->value.constant, true);
       break;
     case IPA_JF_PASS_THROUGH:

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 14:18                                                           ` Michael Matz
@ 2012-09-12 14:37                                                             ` Martin Jambor
  2012-09-12 14:47                                                               ` Richard Guenther
  2012-09-13 10:05                                                               ` Jan Hubicka
  2012-09-19  9:40                                                             ` Martin Jambor
  1 sibling, 2 replies; 93+ messages in thread
From: Martin Jambor @ 2012-09-12 14:37 UTC (permalink / raw)
  To: Michael Matz
  Cc: Richard Guenther, Dehao Chen, Diego Novillo, Dodji Seketeli,
	gcc-patches, Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey,
	Jason Merrill, Richard Henderson

Hi,

On Wed, Sep 12, 2012 at 04:17:45PM +0200, Michael Matz wrote:
> Hi,
> 
> On Wed, 12 Sep 2012, Michael Matz wrote:
> 
> > > 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.
> 
> ipa-prop creates the problem.  Its tree mapping can contain expressions, 
> expressions can have locations, locations now have blocks.  The tree maps 
> are stored as part of jump functions, and hence as part of node summaries.  
> Node summaries are global, hence blocks, and therefore block vars can be 
> placed in the global blob.
> 
> That's not supposed to happen.  The patch below fixes this instance of the 
> problem and makes the testcase work with Dehaos patch with the 
> LTO_NO_PREVAIL call added back in.
> 
> 
> Ciao,
> Michael.
> ------------
> Index: lto-cgraph.c
> ===================================================================
> --- lto-cgraph.c	(revision 190803)
> +++ lto-cgraph.c	(working copy)
> @@ -1373,6 +1373,7 @@ output_node_opt_summary (struct output_b
>           mechanism to store function local declarations into summaries.  */
>        gcc_assert (parm);
>        streamer_write_uhwi (ob, parm_num);
> +      gcc_assert (IS_UNKNOWN_LOCATION (EXPR_LOCATION (map->new_tree)));
>        stream_write_tree (ob, map->new_tree, true);
>        bp = bitpack_create (ob->main_stream);
>        bp_pack_value (&bp, map->replace_p, 1);
> Index: ipa-prop.c
> ===================================================================
> --- ipa-prop.c	(revision 190803)
> +++ ipa-prop.c	(working copy)
> @@ -1378,7 +1378,11 @@ ipa_compute_jump_functions_for_edge (str
>        tree arg = gimple_call_arg (call, n);
>  
>        if (is_gimple_ip_invariant (arg))
> -	ipa_set_jf_constant (jfunc, arg);
> +	{
> +	  arg = unshare_expr (arg);
> +	  SET_EXPR_LOCATION (arg, UNKNOWN_LOCATION);
> +	  ipa_set_jf_constant (jfunc, arg);
> +	}
>        else if (!is_gimple_reg_type (TREE_TYPE (arg))
>  	       && TREE_CODE (arg) == PARM_DECL)

Perhaps it would be better if ipa_set_jf_constant did that, just in
case we ever add another caller?  Note that arithmetic functions also
have their second operand tree stored in them and so perhaps
ipa_set_jf_arith_pass_through should do the same.

And I it is also necessary to do the same thing at the end of
determine_known_aggregate_parts, i.e. before assignment to
item->value.  I can post a separate patch if necessary.

I wasn't following this thread but I hope that streaming types does
not cause this problem.  If they do, there are quite a few in various
jump functions and indirect call graph edges.

Thanks,

Martin


>  	{
> @@ -3154,6 +3158,7 @@ ipa_write_jump_function (struct output_b
>        stream_write_tree (ob, jump_func->value.known_type.component_type, true);
>        break;
>      case IPA_JF_CONST:
> +      gcc_assert (IS_UNKNOWN_LOCATION (EXPR_LOCATION (jump_func->value.constant)));
>        stream_write_tree (ob, jump_func->value.constant, true);
>        break;
>      case IPA_JF_PASS_THROUGH:

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 14:37                                                             ` Martin Jambor
@ 2012-09-12 14:47                                                               ` Richard Guenther
  2012-09-12 15:11                                                                 ` Martin Jambor
  2012-09-13 10:05                                                               ` Jan Hubicka
  1 sibling, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-09-12 14:47 UTC (permalink / raw)
  To: Michael Matz, Richard Guenther, Dehao Chen, Diego Novillo,
	Dodji Seketeli, gcc-patches, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey, Jason Merrill, Richard Henderson

On Wed, Sep 12, 2012 at 4:37 PM, Martin Jambor <mjambor@suse.cz> wrote:
> Hi,
>
> On Wed, Sep 12, 2012 at 04:17:45PM +0200, Michael Matz wrote:
>> Hi,
>>
>> On Wed, 12 Sep 2012, Michael Matz wrote:
>>
>> > > 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.
>>
>> ipa-prop creates the problem.  Its tree mapping can contain expressions,
>> expressions can have locations, locations now have blocks.  The tree maps
>> are stored as part of jump functions, and hence as part of node summaries.
>> Node summaries are global, hence blocks, and therefore block vars can be
>> placed in the global blob.
>>
>> That's not supposed to happen.  The patch below fixes this instance of the
>> problem and makes the testcase work with Dehaos patch with the
>> LTO_NO_PREVAIL call added back in.
>>
>>
>> Ciao,
>> Michael.
>> ------------
>> Index: lto-cgraph.c
>> ===================================================================
>> --- lto-cgraph.c      (revision 190803)
>> +++ lto-cgraph.c      (working copy)
>> @@ -1373,6 +1373,7 @@ output_node_opt_summary (struct output_b
>>           mechanism to store function local declarations into summaries.  */
>>        gcc_assert (parm);
>>        streamer_write_uhwi (ob, parm_num);
>> +      gcc_assert (IS_UNKNOWN_LOCATION (EXPR_LOCATION (map->new_tree)));
>>        stream_write_tree (ob, map->new_tree, true);
>>        bp = bitpack_create (ob->main_stream);
>>        bp_pack_value (&bp, map->replace_p, 1);
>> Index: ipa-prop.c
>> ===================================================================
>> --- ipa-prop.c        (revision 190803)
>> +++ ipa-prop.c        (working copy)
>> @@ -1378,7 +1378,11 @@ ipa_compute_jump_functions_for_edge (str
>>        tree arg = gimple_call_arg (call, n);
>>
>>        if (is_gimple_ip_invariant (arg))
>> -     ipa_set_jf_constant (jfunc, arg);
>> +     {
>> +       arg = unshare_expr (arg);
>> +       SET_EXPR_LOCATION (arg, UNKNOWN_LOCATION);
>> +       ipa_set_jf_constant (jfunc, arg);
>> +     }
>>        else if (!is_gimple_reg_type (TREE_TYPE (arg))
>>              && TREE_CODE (arg) == PARM_DECL)
>
> Perhaps it would be better if ipa_set_jf_constant did that, just in
> case we ever add another caller?  Note that arithmetic functions also
> have their second operand tree stored in them and so perhaps
> ipa_set_jf_arith_pass_through should do the same.
>
> And I it is also necessary to do the same thing at the end of
> determine_known_aggregate_parts, i.e. before assignment to
> item->value.  I can post a separate patch if necessary.
>
> I wasn't following this thread but I hope that streaming types does
> not cause this problem.  If they do, there are quite a few in various
> jump functions and indirect call graph edges.

Well, or if jump functions would not use trees ...

Richard.

> Thanks,
>
> Martin
>
>
>>       {
>> @@ -3154,6 +3158,7 @@ ipa_write_jump_function (struct output_b
>>        stream_write_tree (ob, jump_func->value.known_type.component_type, true);
>>        break;
>>      case IPA_JF_CONST:
>> +      gcc_assert (IS_UNKNOWN_LOCATION (EXPR_LOCATION (jump_func->value.constant)));
>>        stream_write_tree (ob, jump_func->value.constant, true);
>>        break;
>>      case IPA_JF_PASS_THROUGH:

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 14:47                                                               ` Richard Guenther
@ 2012-09-12 15:11                                                                 ` Martin Jambor
  0 siblings, 0 replies; 93+ messages in thread
From: Martin Jambor @ 2012-09-12 15:11 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Michael Matz, Dehao Chen, Diego Novillo, Dodji Seketeli,
	gcc-patches, Jakub Jelinek, Jan Hubicka, David Li, Tom Tromey,
	Jason Merrill, Richard Henderson

Hi,

On Wed, Sep 12, 2012 at 04:47:11PM +0200, Richard Guenther wrote:
> On Wed, Sep 12, 2012 at 4:37 PM, Martin Jambor <mjambor@suse.cz> wrote:
> > On Wed, Sep 12, 2012 at 04:17:45PM +0200, Michael Matz wrote:
> >> On Wed, 12 Sep 2012, Michael Matz wrote:
> >>
> >> > > 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.
> >>
> >> ipa-prop creates the problem.  Its tree mapping can contain expressions,
> >> expressions can have locations, locations now have blocks.  The tree maps
> >> are stored as part of jump functions, and hence as part of node summaries.
> >> Node summaries are global, hence blocks, and therefore block vars can be
> >> placed in the global blob.
> >>
> >> That's not supposed to happen.  The patch below fixes this instance of the
> >> problem and makes the testcase work with Dehaos patch with the
> >> LTO_NO_PREVAIL call added back in.
> >>
> >>
> >> Ciao,
> >> Michael.
> >> ------------
> >> Index: lto-cgraph.c
> >> ===================================================================
> >> --- lto-cgraph.c      (revision 190803)
> >> +++ lto-cgraph.c      (working copy)
> >> @@ -1373,6 +1373,7 @@ output_node_opt_summary (struct output_b
> >>           mechanism to store function local declarations into summaries.  */
> >>        gcc_assert (parm);
> >>        streamer_write_uhwi (ob, parm_num);
> >> +      gcc_assert (IS_UNKNOWN_LOCATION (EXPR_LOCATION (map->new_tree)));
> >>        stream_write_tree (ob, map->new_tree, true);
> >>        bp = bitpack_create (ob->main_stream);
> >>        bp_pack_value (&bp, map->replace_p, 1);
> >> Index: ipa-prop.c
> >> ===================================================================
> >> --- ipa-prop.c        (revision 190803)
> >> +++ ipa-prop.c        (working copy)
> >> @@ -1378,7 +1378,11 @@ ipa_compute_jump_functions_for_edge (str
> >>        tree arg = gimple_call_arg (call, n);
> >>
> >>        if (is_gimple_ip_invariant (arg))
> >> -     ipa_set_jf_constant (jfunc, arg);
> >> +     {
> >> +       arg = unshare_expr (arg);
> >> +       SET_EXPR_LOCATION (arg, UNKNOWN_LOCATION);
> >> +       ipa_set_jf_constant (jfunc, arg);
> >> +     }
> >>        else if (!is_gimple_reg_type (TREE_TYPE (arg))
> >>              && TREE_CODE (arg) == PARM_DECL)
> >
> > Perhaps it would be better if ipa_set_jf_constant did that, just in
> > case we ever add another caller?  Note that arithmetic functions also
> > have their second operand tree stored in them and so perhaps
> > ipa_set_jf_arith_pass_through should do the same.
> >
> > And I it is also necessary to do the same thing at the end of
> > determine_known_aggregate_parts, i.e. before assignment to
> > item->value.  I can post a separate patch if necessary.
> >
> > I wasn't following this thread but I hope that streaming types does
> > not cause this problem.  If they do, there are quite a few in various
> > jump functions and indirect call graph edges.
> 
> Well, or if jump functions would not use trees ...
> 

Eventually, yes, but it is not a short-term goal.  At least I'd like
to replace the type-based devirtualization with pointer tracking
first, which will avoid the need to store (hopefully) all types and I
will have a better idea how to represent the jump functions in a
different way.  I will still need access to VMT initializers to keep
indirect inlining, indirect call inlining hints and IPA-CP
devirtualization working, though.

But as I said, this is all a long-term plan.

Martin

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12  9:14                                                       ` Richard Guenther
@ 2012-09-12 16:39                                                         ` Xinliang David Li
  2012-09-12 17:05                                                           ` Dehao Chen
  2012-09-13 12:03                                                           ` Richard Guenther
  0 siblings, 2 replies; 93+ messages in thread
From: Xinliang David Li @ 2012-09-12 16:39 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Dehao Chen, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 16:39                                                         ` Xinliang David Li
@ 2012-09-12 17:05                                                           ` Dehao Chen
  2012-09-12 17:19                                                             ` Xinliang David Li
  2012-09-12 17:20                                                             ` Dehao Chen
  2012-09-13 12:03                                                           ` Richard Guenther
  1 sibling, 2 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-12 17:05 UTC (permalink / raw)
  To: Xinliang David Li
  Cc: Richard Guenther, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 17:05                                                           ` Dehao Chen
@ 2012-09-12 17:19                                                             ` Xinliang David Li
  2012-09-12 20:44                                                               ` Dehao Chen
  2012-09-12 17:20                                                             ` Dehao Chen
  1 sibling, 1 reply; 93+ messages in thread
From: Xinliang David Li @ 2012-09-12 17:19 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Richard Guenther, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 17:05                                                           ` Dehao Chen
  2012-09-12 17:19                                                             ` Xinliang David Li
@ 2012-09-12 17:20                                                             ` Dehao Chen
  2012-09-13  7:07                                                               ` Dehao Chen
  2012-09-13 12:00                                                               ` Richard Guenther
  1 sibling, 2 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-12 17:20 UTC (permalink / raw)
  To: Xinliang David Li
  Cc: Richard Guenther, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

There is another bug in the patch (not covered by unittests,
discovered through spec benchmarks).

When we remove unused locals, we do not mark the block as used for
debug stmt, but gimple-streamer-out will still stream out blocks for
debug stmt. There can be 2 fixes:

1.
--- a/gcc/gimple-streamer-out.c
+++ b/gcc/gimple-streamer-out.c
@@ -77,7 +77,8 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
   lto_output_location (ob, LOCATION_LOCUS (gimple_location (stmt)));

   /* Emit the lexical block holding STMT.  */
-  stream_write_tree (ob, gimple_block (stmt), true);
+  if (!is_gimple_debug (stmt))
+    stream_write_tree (ob, gimple_block (stmt), true);

   /* Emit the operands.  */
   switch (gimple_code (stmt))

2.
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -726,9 +726,6 @@ remove_unused_locals (void)
          gimple stmt = gsi_stmt (gsi);
          tree b = gimple_block (stmt);

-         if (is_gimple_debug (stmt))
-           continue;
-
          if (gimple_clobber_p (stmt))
            {
              have_local_clobbers = true;

Either fix could work. Any suggests which one should we go?

Thanks,
Dehao

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.
> 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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 17:19                                                             ` Xinliang David Li
@ 2012-09-12 20:44                                                               ` Dehao Chen
  2012-09-12 20:59                                                                 ` Xinliang David Li
  2012-09-13 12:04                                                                 ` Richard Guenther
  0 siblings, 2 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-12 20:44 UTC (permalink / raw)
  To: Xinliang David Li
  Cc: Richard Guenther, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

[-- Attachment #1: Type: text/plain, Size: 6424 bytes --]

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.

[-- Attachment #2: mem.orig.txt --]
[-- Type: text/plain, Size: 3323 bytes --]

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

[-- Attachment #3: mem.block.txt --]
[-- Type: text/plain, Size: 3323 bytes --]

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

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 20:44                                                               ` Dehao Chen
@ 2012-09-12 20:59                                                                 ` Xinliang David Li
  2012-09-13 12:04                                                                 ` Richard Guenther
  1 sibling, 0 replies; 93+ messages in thread
From: Xinliang David Li @ 2012-09-12 20:59 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Richard Guenther, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 17:20                                                             ` Dehao Chen
@ 2012-09-13  7:07                                                               ` Dehao Chen
  2012-09-13 12:00                                                               ` Richard Guenther
  1 sibling, 0 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-13  7:07 UTC (permalink / raw)
  To: Xinliang David Li
  Cc: Richard Guenther, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

This bug is exposed by this patch.

On Thu, Sep 13, 2012 at 1:20 AM, Dehao Chen <dehao@google.com> wrote:
> There is another bug in the patch (not covered by unittests,
> discovered through spec benchmarks).
>
> When we remove unused locals, we do not mark the block as used for
> debug stmt, but gimple-streamer-out will still stream out blocks for
> debug stmt. There can be 2 fixes:
>
> 1.
> --- a/gcc/gimple-streamer-out.c
> +++ b/gcc/gimple-streamer-out.c
> @@ -77,7 +77,8 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
>    lto_output_location (ob, LOCATION_LOCUS (gimple_location (stmt)));
>
>    /* Emit the lexical block holding STMT.  */
> -  stream_write_tree (ob, gimple_block (stmt), true);
> +  if (!is_gimple_debug (stmt))
> +    stream_write_tree (ob, gimple_block (stmt), true);
>
>    /* Emit the operands.  */
>    switch (gimple_code (stmt))

The situation is actually more complicated. We need to remove the
block for all debug stmt as well as DECL_DEBUG_EXPR. Here's a new
patch, which passes all spec2006 benchmarks with LTO. Still testing it
on gcc testsuite. I'll send out an integrated patch tomorrow.

Thanks,
Dehao

diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c
index 22bcbca..b044f35 100644
--- a/gcc/gimple-streamer-out.c
+++ b/gcc/gimple-streamer-out.c
@@ -47,6 +47,27 @@ output_phi (struct output_block *ob, gimple phi)
     }
 }

+static tree
+clear_gimple_op_block_r (tree *tp, int *walk_subtrees, void *data)
+{
+  if (EXPR_P (*tp))
+    {
+      TREE_SET_BLOCK (*tp, NULL);
+    }
+  return NULL_TREE;
+}
+
+static void
+clear_block_for_debug_stmt (gimple stmt)
+{
+  gcc_assert (is_gimple_debug (stmt));
+  if (gimple_debug_source_bind_p (stmt))
+    walk_tree (gimple_debug_source_bind_get_value_ptr (stmt),
+              clear_gimple_op_block_r, NULL, NULL);
+  else
+    walk_tree (gimple_debug_bind_get_value_ptr (stmt),
+              clear_gimple_op_block_r, NULL, NULL);
+}

 /* Emit statement STMT on the main stream of output block OB.  */

@@ -77,7 +98,13 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
   lto_output_location (ob, LOCATION_LOCUS (gimple_location (stmt)));

   /* Emit the lexical block holding STMT.  */
-  stream_write_tree (ob, gimple_block (stmt), true);
+  if (!is_gimple_debug (stmt))
+    stream_write_tree (ob, gimple_block (stmt), true);
+  else
+    {
+      clear_block_for_debug_stmt (stmt);
+      stream_write_tree (ob, NULL, true);
+    }

   /* Emit the operands.  */
   switch (gimple_code (stmt))

diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index ab86b1e..fa89519 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -474,6 +474,15 @@ write_ts_decl_minimal_tree_pointers (struct
output_block *ob, tree expr,
   lto_output_location (ob, LOCATION_LOCUS (DECL_SOURCE_LOCATION (expr)));
 }

+static tree
+clear_gimple_op_block_r (tree *tp, int *walk_subtrees, void *data)
+{
+  if (EXPR_P (*tp))
+    {
+      TREE_SET_BLOCK (*tp, NULL);
+    }
+  return NULL_TREE;
+}

 /* Write all pointer fields in the TS_DECL_COMMON structure of EXPR to
    output block OB.  If REF_P is true, write a reference to EXPR's
@@ -504,7 +513,11 @@ write_ts_decl_common_tree_pointers (struct
output_block *ob, tree expr,
     stream_write_tree (ob, DECL_VALUE_EXPR (expr), ref_p);

   if (TREE_CODE (expr) == VAR_DECL)
-    stream_write_tree (ob, DECL_DEBUG_EXPR (expr), ref_p);
+    {
+      tree debug_expr = DECL_DEBUG_EXPR (expr);
+      walk_tree (&debug_expr, clear_gimple_op_block_r, NULL, NULL);
+      stream_write_tree (ob, debug_expr, ref_p);
+    }
 }




>
> 2.
> --- a/gcc/tree-ssa-live.c
> +++ b/gcc/tree-ssa-live.c
> @@ -726,9 +726,6 @@ remove_unused_locals (void)
>           gimple stmt = gsi_stmt (gsi);
>           tree b = gimple_block (stmt);
>
> -         if (is_gimple_debug (stmt))
> -           continue;
> -
>           if (gimple_clobber_p (stmt))
>             {
>               have_local_clobbers = true;

This will not work because some unittests will fail -fcompare-debug tests.

>
> Either fix could work. Any suggests which one should we go?
>
> Thanks,
> Dehao
>
> 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.
>> 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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-10 16:42                                         ` Jan Hubicka
  2012-09-10 17:32                                           ` Dehao Chen
@ 2012-09-13  7:10                                           ` Dehao Chen
  1 sibling, 0 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-13  7:10 UTC (permalink / raw)
  To: Jan Hubicka
  Cc: Richard Guenther, Diego Novillo, Dodji Seketeli, GCC Patches,
	Jakub Jelinek, David Li, Tom Tromey, Jason Merrill,
	Richard Henderson

I can reproduce the error. For large applications, the 32bit integer
will overflow (not enough to encode the locations). The following
patch can fix the problem. I'm still doing integration tests, and will
send out a integral patch tomorrow.

Thanks,
Dehao

diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 8091e9b..14703c8 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -538,12 +540,12 @@ linemap_line_start (struct line_maps *set,
linenum_type to_line,
   if (add_map)
     {
       int column_bits;
-      if (max_column_hint > 100000 || highest > 0xC0000000)
+      if (max_column_hint > 100000 || highest > 0x60000000)
        {
          /* If the column number is ridiculous or we've allocated a huge
             number of source_locations, give up on column numbers. */
          max_column_hint = 0;
-         if (highest >0xF0000000)
+         if (highest >0x70000000)
            return 0;
          column_bits = 0;
        }


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

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 14:37                                                             ` Martin Jambor
  2012-09-12 14:47                                                               ` Richard Guenther
@ 2012-09-13 10:05                                                               ` Jan Hubicka
  1 sibling, 0 replies; 93+ messages in thread
From: Jan Hubicka @ 2012-09-13 10:05 UTC (permalink / raw)
  To: Michael Matz, Richard Guenther, Dehao Chen, Diego Novillo,
	Dodji Seketeli, gcc-patches, Jakub Jelinek, Jan Hubicka,
	David Li, Tom Tromey, Jason Merrill, Richard Henderson

> Hi,
> 
> On Wed, Sep 12, 2012 at 04:17:45PM +0200, Michael Matz wrote:
> > Hi,
> > 
> > On Wed, 12 Sep 2012, Michael Matz wrote:
> > 
> > > > 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.
> > 
> > ipa-prop creates the problem.  Its tree mapping can contain expressions, 
> > expressions can have locations, locations now have blocks.  The tree maps 
> > are stored as part of jump functions, and hence as part of node summaries.  
> > Node summaries are global, hence blocks, and therefore block vars can be 
> > placed in the global blob.
> > 
> > That's not supposed to happen.  The patch below fixes this instance of the 
> > problem and makes the testcase work with Dehaos patch with the 
> > LTO_NO_PREVAIL call added back in.
> > 
> > 
> > Ciao,
> > Michael.
> > ------------
> > Index: lto-cgraph.c
> > ===================================================================
> > --- lto-cgraph.c	(revision 190803)
> > +++ lto-cgraph.c	(working copy)
> > @@ -1373,6 +1373,7 @@ output_node_opt_summary (struct output_b
> >           mechanism to store function local declarations into summaries.  */
> >        gcc_assert (parm);
> >        streamer_write_uhwi (ob, parm_num);
> > +      gcc_assert (IS_UNKNOWN_LOCATION (EXPR_LOCATION (map->new_tree)));
> >        stream_write_tree (ob, map->new_tree, true);
> >        bp = bitpack_create (ob->main_stream);
> >        bp_pack_value (&bp, map->replace_p, 1);
> > Index: ipa-prop.c
> > ===================================================================
> > --- ipa-prop.c	(revision 190803)
> > +++ ipa-prop.c	(working copy)
> > @@ -1378,7 +1378,11 @@ ipa_compute_jump_functions_for_edge (str
> >        tree arg = gimple_call_arg (call, n);
> >  
> >        if (is_gimple_ip_invariant (arg))
> > -	ipa_set_jf_constant (jfunc, arg);
> > +	{
> > +	  arg = unshare_expr (arg);
> > +	  SET_EXPR_LOCATION (arg, UNKNOWN_LOCATION);
> > +	  ipa_set_jf_constant (jfunc, arg);
> > +	}
> >        else if (!is_gimple_reg_type (TREE_TYPE (arg))
> >  	       && TREE_CODE (arg) == PARM_DECL)
> 
> Perhaps it would be better if ipa_set_jf_constant did that, just in
> case we ever add another caller?  Note that arithmetic functions also
> have their second operand tree stored in them and so perhaps
> ipa_set_jf_arith_pass_through should do the same.
> 
> And I it is also necessary to do the same thing at the end of
> determine_known_aggregate_parts, i.e. before assignment to
> item->value.  I can post a separate patch if necessary.

Yes, this seem resonable thing to do. Patchees for this are preapproved.
> 
> I wasn't following this thread but I hope that streaming types does
> not cause this problem.  If they do, there are quite a few in various
> jump functions and indirect call graph edges.

We probably ought to ban streaming in BLOCK_DECL and other beasts that are
not expected at WPA stage.

Concerning Richi's suggestion to move jump functions completely away from
trees, I am really not 100% sure how good idea it is in long term. As IPA
analysis are getting more accurate we will stream more and more expressions.  I
am not convinced it makes sense to reinvent way of representing them rather
than fixing what we have.

Honza

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 17:20                                                             ` Dehao Chen
  2012-09-13  7:07                                                               ` Dehao Chen
@ 2012-09-13 12:00                                                               ` Richard Guenther
  2012-09-13 13:33                                                                 ` Robert Dewar
  2012-09-13 19:28                                                                 ` Dehao Chen
  1 sibling, 2 replies; 93+ messages in thread
From: Richard Guenther @ 2012-09-13 12:00 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Xinliang David Li, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

On Wed, Sep 12, 2012 at 7:20 PM, Dehao Chen <dehao@google.com> wrote:
> There is another bug in the patch (not covered by unittests,
> discovered through spec benchmarks).
>
> When we remove unused locals, we do not mark the block as used for
> debug stmt, but gimple-streamer-out will still stream out blocks for
> debug stmt. There can be 2 fixes:

Because doing so would create code generation differences -g vs. -g0.

> 1.
> --- a/gcc/gimple-streamer-out.c
> +++ b/gcc/gimple-streamer-out.c
> @@ -77,7 +77,8 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
>    lto_output_location (ob, LOCATION_LOCUS (gimple_location (stmt)));
>
>    /* Emit the lexical block holding STMT.  */
> -  stream_write_tree (ob, gimple_block (stmt), true);
> +  if (!is_gimple_debug (stmt))
> +    stream_write_tree (ob, gimple_block (stmt), true);
>
>    /* Emit the operands.  */
>    switch (gimple_code (stmt))
>
> 2.
> --- a/gcc/tree-ssa-live.c
> +++ b/gcc/tree-ssa-live.c
> @@ -726,9 +726,6 @@ remove_unused_locals (void)
>           gimple stmt = gsi_stmt (gsi);
>           tree b = gimple_block (stmt);
>
> -         if (is_gimple_debug (stmt))
> -           continue;
> -
>           if (gimple_clobber_p (stmt))
>             {
>               have_local_clobbers = true;
>
> Either fix could work. Any suggests which one should we go?

The 2nd one will not work and is not acceptable.  The 1st one - well ...
what happens on trunk right now?  The debug stmt points to a
BLOCK that is possibly removed from the BLOCK tree?  In this case
I think the fix is 3. make sure remove_unused_scope_block_p will
clear BLOCKs from all stmts / expressions that have been removed.

Richard.

> Thanks,
> Dehao
>
> 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.
>> 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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 16:39                                                         ` Xinliang David Li
  2012-09-12 17:05                                                           ` Dehao Chen
@ 2012-09-13 12:03                                                           ` Richard Guenther
  2012-09-13 16:12                                                             ` Dehao Chen
  1 sibling, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-09-13 12:03 UTC (permalink / raw)
  To: Xinliang David Li
  Cc: Dehao Chen, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 20:44                                                               ` Dehao Chen
  2012-09-12 20:59                                                                 ` Xinliang David Li
@ 2012-09-13 12:04                                                                 ` Richard Guenther
  1 sibling, 0 replies; 93+ messages in thread
From: Richard Guenther @ 2012-09-13 12:04 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Xinliang David Li, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 12:00                                                               ` Richard Guenther
@ 2012-09-13 13:33                                                                 ` Robert Dewar
  2012-09-13 13:44                                                                   ` Jakub Jelinek
                                                                                     ` (2 more replies)
  2012-09-13 19:28                                                                 ` Dehao Chen
  1 sibling, 3 replies; 93+ messages in thread
From: Robert Dewar @ 2012-09-13 13:33 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Dehao Chen, Xinliang David Li, Michael Matz, Diego Novillo,
	Dodji Seketeli, GCC Patches, Jakub Jelinek, Jan Hubicka,
	Tom Tromey, Jason Merrill, Richard Henderson

On 9/13/2012 8:00 AM, Richard Guenther wrote:

> Because doing so would create code generation differences -g vs. -g0.

Sometimes I wonder whether the insistence on -g not changing code
generation is warranted. In practice, gdb for me is so weak in handling
-O1 or -O2, that if I want to debug something I have to recompile
with -O0 -g, which causes quite a bit of code generation change :-)

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 13:33                                                                 ` Robert Dewar
@ 2012-09-13 13:44                                                                   ` Jakub Jelinek
  2012-09-13 13:52                                                                     ` Robert Dewar
  2012-09-13 16:07                                                                   ` Xinliang David Li
  2012-09-13 16:46                                                                   ` Tom Tromey
  2 siblings, 1 reply; 93+ messages in thread
From: Jakub Jelinek @ 2012-09-13 13:44 UTC (permalink / raw)
  To: Robert Dewar
  Cc: Richard Guenther, Dehao Chen, Xinliang David Li, Michael Matz,
	Diego Novillo, Dodji Seketeli, GCC Patches, Jan Hubicka,
	Tom Tromey, Jason Merrill, Richard Henderson

On Thu, Sep 13, 2012 at 09:33:20AM -0400, Robert Dewar wrote:
> On 9/13/2012 8:00 AM, Richard Guenther wrote:
> 
> >Because doing so would create code generation differences -g vs. -g0.
> 
> Sometimes I wonder whether the insistence on -g not changing code
> generation is warranted. In practice, gdb for me is so weak in handling

It is.  IMHO the most important reason is not that somebody would build
first with just -O2 and then later on to debug the code would build it again
with -g -O2 and hope the code is the same, but by making sure -g vs. -g0
doesn't change generate code we ensure -g doesn't pessimize the generated
code, and really many people compile even production code with -g -O2
or similar.  The debug info is then either stripped, or stripped into
separate files/not shipped or only optionally shipped with the product.

	Jakub

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 13:44                                                                   ` Jakub Jelinek
@ 2012-09-13 13:52                                                                     ` Robert Dewar
  2012-09-13 17:37                                                                       ` Mike Stump
  0 siblings, 1 reply; 93+ messages in thread
From: Robert Dewar @ 2012-09-13 13:52 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Richard Guenther, Dehao Chen, Xinliang David Li, Michael Matz,
	Diego Novillo, Dodji Seketeli, GCC Patches, Jan Hubicka,
	Tom Tromey, Jason Merrill, Richard Henderson

On 9/13/2012 9:38 AM, Jakub Jelinek wrote:
> On Thu, Sep 13, 2012 at 09:33:20AM -0400, Robert Dewar wrote:
>> On 9/13/2012 8:00 AM, Richard Guenther wrote:
>>
>>> Because doing so would create code generation differences -g vs. -g0.
>>
>> Sometimes I wonder whether the insistence on -g not changing code
>> generation is warranted. In practice, gdb for me is so weak in handling
>
> It is.  IMHO the most important reason is not that somebody would build
> first with just -O2 and then later on to debug the code would build it again
> with -g -O2 and hope the code is the same, but by making sure -g vs. -g0
> doesn't change generate code we ensure -g doesn't pessimize the generated
> code, and really many people compile even production code with -g -O2
> or similar.  The debug info is then either stripped, or stripped into
> separate files/not shipped or only optionally shipped with the product.
>
> 	Jakub
>
Sure, it is obvious that you don't want -g to affect -O1 or -O2 code,
but I think if you have -Og (if and when we have that), it would not
be a bad thing for -g to affect that. I can even imagine that what
-Og means is -O1 if you don't have -g, and something good for
debugging if you do have -g.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 13:33                                                                 ` Robert Dewar
  2012-09-13 13:44                                                                   ` Jakub Jelinek
@ 2012-09-13 16:07                                                                   ` Xinliang David Li
  2012-09-13 16:29                                                                     ` Robert Dewar
  2012-09-13 16:46                                                                   ` Tom Tromey
  2 siblings, 1 reply; 93+ messages in thread
From: Xinliang David Li @ 2012-09-13 16:07 UTC (permalink / raw)
  To: Robert Dewar
  Cc: Richard Guenther, Dehao Chen, Michael Matz, Diego Novillo,
	Dodji Seketeli, GCC Patches, Jakub Jelinek, Jan Hubicka,
	Tom Tromey, Jason Merrill, Richard Henderson

It is very important to make sure -g does not affect code gen ---
people do release build with -g with optimization, and strip the
binary before sending it to production machines ..

David

On Thu, Sep 13, 2012 at 6:33 AM, Robert Dewar <dewar@adacore.com> wrote:
> On 9/13/2012 8:00 AM, Richard Guenther wrote:
>
>> Because doing so would create code generation differences -g vs. -g0.
>
>
> Sometimes I wonder whether the insistence on -g not changing code
> generation is warranted. In practice, gdb for me is so weak in handling
> -O1 or -O2, that if I want to debug something I have to recompile
> with -O0 -g, which causes quite a bit of code generation change :-)
>

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 12:03                                                           ` Richard Guenther
@ 2012-09-13 16:12                                                             ` Dehao Chen
  0 siblings, 0 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-13 16:12 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Xinliang David Li, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 16:07                                                                   ` Xinliang David Li
@ 2012-09-13 16:29                                                                     ` Robert Dewar
  0 siblings, 0 replies; 93+ messages in thread
From: Robert Dewar @ 2012-09-13 16:29 UTC (permalink / raw)
  To: Xinliang David Li
  Cc: Richard Guenther, Dehao Chen, Michael Matz, Diego Novillo,
	Dodji Seketeli, GCC Patches, Jakub Jelinek, Jan Hubicka,
	Tom Tromey, Jason Merrill, Richard Henderson

On 9/13/2012 12:07 PM, Xinliang David Li wrote:
> It is very important to make sure -g does not affect code gen ---
> people do release build with -g with optimization, and strip the
> binary before sending it to production machines ..

Yes, of course, and for sure -g cannot affect optimized code, see
my follow on message.
>
> David
>
> On Thu, Sep 13, 2012 at 6:33 AM, Robert Dewar <dewar@adacore.com> wrote:
>> On 9/13/2012 8:00 AM, Richard Guenther wrote:
>>
>>> Because doing so would create code generation differences -g vs. -g0.
>>
>>
>> Sometimes I wonder whether the insistence on -g not changing code
>> generation is warranted. In practice, gdb for me is so weak in handling
>> -O1 or -O2, that if I want to debug something I have to recompile
>> with -O0 -g, which causes quite a bit of code generation change :-)
>>

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 13:33                                                                 ` Robert Dewar
  2012-09-13 13:44                                                                   ` Jakub Jelinek
  2012-09-13 16:07                                                                   ` Xinliang David Li
@ 2012-09-13 16:46                                                                   ` Tom Tromey
  2012-09-13 16:51                                                                     ` Robert Dewar
  2 siblings, 1 reply; 93+ messages in thread
From: Tom Tromey @ 2012-09-13 16:46 UTC (permalink / raw)
  To: Robert Dewar
  Cc: Richard Guenther, Dehao Chen, Xinliang David Li, Michael Matz,
	Diego Novillo, Dodji Seketeli, GCC Patches, Jakub Jelinek,
	Jan Hubicka, Jason Merrill, Richard Henderson

>>>>> "Robert" == Robert Dewar <dewar@adacore.com> writes:

Robert> Sometimes I wonder whether the insistence on -g not changing code
Robert> generation is warranted. In practice, gdb for me is so weak in handling
Robert> -O1 or -O2, that if I want to debug something I have to recompile
Robert> with -O0 -g, which causes quite a bit of code generation change :-)

If those are gdb bugs, please file them.

Tom

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-07 14:56                               ` Dehao Chen
  2012-09-07 17:29                                 ` Diego Novillo
@ 2012-09-13 16:49                                 ` Tom Tromey
  2012-09-14  2:47                                   ` Dehao Chen
  1 sibling, 1 reply; 93+ messages in thread
From: Tom Tromey @ 2012-09-13 16:49 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Diego Novillo, Richard Guenther, Dodji Seketeli, gcc-patches,
	Jakub Jelinek, Jan Hubicka, David Li, Jason Merrill,
	Richard Henderson

>>>>> "Dehao" == Dehao Chen <dehao@google.com> writes:

Dehao> + static htab_t location_adhoc_data_htab;
Dehao> + static source_location curr_adhoc_loc;
Dehao> + static struct location_adhoc_data *location_adhoc_data;
Dehao> + static unsigned int allocated_location_adhoc_data;

libcpp was written to allow multiple preprocessor objects to be created
and used in one process.  I think introducing globals like this breaks
this part of the design.  It seems to me they should instead be fields
of cpp_reader or line_maps.

Tom

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 16:46                                                                   ` Tom Tromey
@ 2012-09-13 16:51                                                                     ` Robert Dewar
  2012-09-13 17:45                                                                       ` Mike Stump
  0 siblings, 1 reply; 93+ messages in thread
From: Robert Dewar @ 2012-09-13 16:51 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Richard Guenther, Dehao Chen, Xinliang David Li, Michael Matz,
	Diego Novillo, Dodji Seketeli, GCC Patches, Jakub Jelinek,
	Jan Hubicka, Jason Merrill, Richard Henderson

On 9/13/2012 12:46 PM, Tom Tromey wrote:
>>>>>> "Robert" == Robert Dewar <dewar@adacore.com> writes:
>
> Robert> Sometimes I wonder whether the insistence on -g not changing code
> Robert> generation is warranted. In practice, gdb for me is so weak in handling
> Robert> -O1 or -O2, that if I want to debug something I have to recompile
> Robert> with -O0 -g, which causes quite a bit of code generation change :-)
>
> If those are gdb bugs, please file them.

Well I think everyone knows about the failings of gdb in -O1 mode, they
have been much discussed, and they are not really gdb bugs, more an 
issue of it being basically hard to debug optimized code. Things used
to be a LOT better, I routinely debugged code at -O1, but then the
compiler got better at optimization, and things deteriorated so much
at -O1 that now I don't even attempt it.
>
> Tom
>

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 13:52                                                                     ` Robert Dewar
@ 2012-09-13 17:37                                                                       ` Mike Stump
  2012-09-14  6:49                                                                         ` Richard Guenther
  0 siblings, 1 reply; 93+ messages in thread
From: Mike Stump @ 2012-09-13 17:37 UTC (permalink / raw)
  To: Robert Dewar
  Cc: Jakub Jelinek, Richard Guenther, Dehao Chen, Xinliang David Li,
	Michael Matz, Diego Novillo, Dodji Seketeli, GCC Patches,
	Jan Hubicka, Tom Tromey, Jason Merrill, Richard Henderson

On Sep 13, 2012, at 6:52 AM, Robert Dewar <dewar@adacore.com> wrote:
> Sure, it is obvious that you don't want -g to affect -O1 or -O2 code,
> but I think if you have -Og (if and when we have that), it would not
> be a bad thing for -g to affect that.

No, instead think of -Og as affecting the -g output itself.  If it does, then there is nothing for -g to affect when used with -Og.  So, I agree, -g -Og can have any impact on code-gen that we want, I just dis-agree that -Og should be any different; I just don't see the need.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 16:51                                                                     ` Robert Dewar
@ 2012-09-13 17:45                                                                       ` Mike Stump
  0 siblings, 0 replies; 93+ messages in thread
From: Mike Stump @ 2012-09-13 17:45 UTC (permalink / raw)
  To: Robert Dewar
  Cc: Tom Tromey, Richard Guenther, Dehao Chen, Xinliang David Li,
	Michael Matz, Diego Novillo, Dodji Seketeli, GCC Patches,
	Jakub Jelinek, Jan Hubicka, Jason Merrill, Richard Henderson

On Sep 13, 2012, at 9:51 AM, Robert Dewar <dewar@adacore.com> wrote:
> I routinely debugged code at -O1, but then the
> compiler got better at optimization, and things deteriorated so much
> at -O1 that now I don't even attempt it.

An example of a non-feature for me would be the reordering of instructions by scheduling when there is no benefit, only reorder, if there is a non-zero benefit.  This causes the jumpy debug experience, and needlessly so in some cases.  This is also an example that gdb can't fix.  The fix would be to compute costs as tuple and have the second part of the cost be the original instruction ordering.  Then, the scheduler actively works to preserve order, unless the upper case of the cost indicates there is a win to be had.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 12:00                                                               ` Richard Guenther
  2012-09-13 13:33                                                                 ` Robert Dewar
@ 2012-09-13 19:28                                                                 ` Dehao Chen
  1 sibling, 0 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-13 19:28 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Xinliang David Li, Michael Matz, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, Tom Tromey,
	Jason Merrill, Richard Henderson

On Thu, Sep 13, 2012 at 8:00 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Sep 12, 2012 at 7:20 PM, Dehao Chen <dehao@google.com> wrote:
>> There is another bug in the patch (not covered by unittests,
>> discovered through spec benchmarks).
>>
>> When we remove unused locals, we do not mark the block as used for
>> debug stmt, but gimple-streamer-out will still stream out blocks for
>> debug stmt. There can be 2 fixes:
>
> Because doing so would create code generation differences -g vs. -g0.
>
>> 1.
>> --- a/gcc/gimple-streamer-out.c
>> +++ b/gcc/gimple-streamer-out.c
>> @@ -77,7 +77,8 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
>>    lto_output_location (ob, LOCATION_LOCUS (gimple_location (stmt)));
>>
>>    /* Emit the lexical block holding STMT.  */
>> -  stream_write_tree (ob, gimple_block (stmt), true);
>> +  if (!is_gimple_debug (stmt))
>> +    stream_write_tree (ob, gimple_block (stmt), true);
>>
>>    /* Emit the operands.  */
>>    switch (gimple_code (stmt))
>>
>> 2.
>> --- a/gcc/tree-ssa-live.c
>> +++ b/gcc/tree-ssa-live.c
>> @@ -726,9 +726,6 @@ remove_unused_locals (void)
>>           gimple stmt = gsi_stmt (gsi);
>>           tree b = gimple_block (stmt);
>>
>> -         if (is_gimple_debug (stmt))
>> -           continue;
>> -
>>           if (gimple_clobber_p (stmt))
>>             {
>>               have_local_clobbers = true;
>>
>> Either fix could work. Any suggests which one should we go?
>
> The 2nd one will not work and is not acceptable.  The 1st one - well ...
> what happens on trunk right now?  The debug stmt points to a
> BLOCK that is possibly removed from the BLOCK tree?  In this case
> I think the fix is 3. make sure remove_unused_scope_block_p will
> clear BLOCKs from all stmts / expressions that have been removed.
>

Thanks, updated the patch for this issue. Only attached the diff here,
will send out the whole patch with updated ChangeLog later.
Bootstrapped and passed all gcc regression tests. And also passed
SPEC2006 with LTO.

Dehao

diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index 1381693..af09806 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -612,6 +612,47 @@ mark_all_vars_used (tree *expr_p)
   walk_tree (expr_p, mark_all_vars_used_1, NULL, NULL);
 }

+/* Helper function for clear_unused_block_pointer, called via walk_tree.  */
+
+static tree
+clear_unused_block_pointer_1 (tree *tp, int *, void *)
+{
+  if (EXPR_P (*tp) && TREE_BLOCK (*tp)
+      && !TREE_USED (TREE_BLOCK (*tp)))
+    TREE_SET_BLOCK (*tp, NULL);
+  if (TREE_CODE (*tp) == VAR_DECL && DECL_DEBUG_EXPR_IS_FROM (*tp))
+    {
+      tree debug_expr = DECL_DEBUG_EXPR (*tp);
+      walk_tree (&debug_expr, clear_unused_block_pointer_1, NULL, NULL);
+    }
+  return NULL_TREE;
+}
+
+/* Set all block pointer in debug stmt to NULL if the block is unused,
+   so that they will not be streamed out.  */
+
+static void
+clear_unused_block_pointer ()
+{
+  basic_block bb;
+  gimple_stmt_iterator gsi;
+  FOR_EACH_BB (bb)
+    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+      {
+       unsigned i;
+       tree b;
+       gimple stmt = gsi_stmt (gsi);
+
+       if (!is_gimple_debug (stmt))
+         continue;
+       b = gimple_block (stmt);
+       if (b && !TREE_USED (b))
+         gimple_set_block (stmt, NULL);
+       for (i = 0; i < gimple_num_ops (stmt); i++)
+         walk_tree (gimple_op_ptr (stmt, i), clear_unused_block_pointer_1,
+                    NULL, NULL);
+      }
+}

 /* Dump scope blocks starting at SCOPE to FILE.  INDENT is the
    indentation level and FLAGS is as in print_generic_expr.  */
@@ -841,6 +882,7 @@ remove_unused_locals (void)
     VEC_truncate (tree, cfun->local_decls, dstidx);

   remove_unused_scope_block_p (DECL_INITIAL (current_function_decl));
+  clear_unused_block_pointer ();

   BITMAP_FREE (usedvars);



> Richard.
>
>> Thanks,
>> Dehao
>>
>> 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.
>>> 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.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 16:49                                 ` Tom Tromey
@ 2012-09-14  2:47                                   ` Dehao Chen
  2012-09-14  3:04                                     ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-09-14  2:47 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Diego Novillo, Richard Guenther, Dodji Seketeli, GCC Patches,
	Jakub Jelinek, Jan Hubicka, David Li, Jason Merrill,
	Richard Henderson

On Fri, Sep 14, 2012 at 12:49 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Dehao" == Dehao Chen <dehao@google.com> writes:
>
> Dehao> + static htab_t location_adhoc_data_htab;
> Dehao> + static source_location curr_adhoc_loc;
> Dehao> + static struct location_adhoc_data *location_adhoc_data;
> Dehao> + static unsigned int allocated_location_adhoc_data;
>
> libcpp was written to allow multiple preprocessor objects to be created
> and used in one process.  I think introducing globals like this breaks
> this part of the design.  It seems to me they should instead be fields
> of cpp_reader or line_maps.

Okay. I've moved these into line_maps. Will send out the whole patch soon...

Thanks,
Dehao

>
> Tom

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-14  2:47                                   ` Dehao Chen
@ 2012-09-14  3:04                                     ` Dehao Chen
  2012-09-19  8:48                                       ` Jan Hubicka
  2012-09-19 22:58                                       ` Michael Meissner
  0 siblings, 2 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-14  3:04 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Diego Novillo, Richard Guenther, Dodji Seketeli, GCC Patches,
	Jakub Jelinek, Jan Hubicka, David Li, Jason Merrill,
	Richard Henderson

[-- Attachment #1: Type: text/plain, Size: 7831 bytes --]

Hi,

I've integrated all the reviews from this thread (Thank you guys for
helping refine this patch).

Now the patch can pass all gcc testsuite as well as all spec2006
benchmarks (with LTO). Concerning memory consumption, for extreme
benchmarks like tramp3d, this patch incurs around 2% peak memory
overhead (mostly from the extra blocks that have been set NULL in the
original implementation.)

Attached is the new patch. Honza, could you help me try this on
Mozzila lto to see if the error is gone?

Thanks,
Dehao

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.
	* lto-cgraph.c (output_node_opt_summary): 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.
	* ipa-prop.c (ipa_set_jf_constant): Likewise.
	(ipa_write_jump_function): 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.

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

	* include/line-map.h (MAX_SOURCE_LOCATION): New value.
	(location_adhoc_data_fini): New.
	(get_combined_adhoc_loc): New.
	(get_data_from_adhoc_loc): New.
	(get_location_from_adhoc_loc): New.
	(location_adhoc_data_map): New.
	(COMBINE_LOCATION_DATA): New.
	(IS_ADHOC_LOC): New.
	(expanded_location): New field.
	(line_maps): New field.
	* line-map.c (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_init): Initialize location_adhoc_data.
	(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.
	(linemap_line_start): Likewise.

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

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

[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 99975 bytes --]

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,33 @@ 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))
+    {
+      if (b)
+	t->exp.locus = COMBINE_LOCATION_DATA (line_table, t->exp.locus, b);
+      else
+	t->exp.locus = LOCATION_LOCUS (t->exp.locus);
+    }
+  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 (line_table, LOC) : (LOC))
+#define LOCATION_BLOCK(LOC) \
+  ((tree) ((IS_ADHOC_LOC (LOC)) ? get_data_from_adhoc_loc (line_table, (LOC)) \
+  : NULL))
+#define IS_UNKNOWN_LOCATION(LOC) \
+  ((IS_ADHOC_LOC (LOC)) ? get_location_from_adhoc_loc (line_table, 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)
@@ -1946,6 +1946,7 @@ toplev_main (int argc, char **argv)
   invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
 
   finalize_plugins ();
+  location_adhoc_data_fini (line_table);
   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/lto-cgraph.c
===================================================================
--- gcc/lto-cgraph.c	(revision 191083)
+++ gcc/lto-cgraph.c	(working copy)
@@ -1373,6 +1373,7 @@ output_node_opt_summary (struct output_block *ob,
          mechanism to store function local declarations into summaries.  */
       gcc_assert (parm);
       streamer_write_uhwi (ob, parm_num);
+      gcc_assert (IS_UNKNOWN_LOCATION (EXPR_LOCATION (map->new_tree)));
       stream_write_tree (ob, map->new_tree, true);
       bp = bitpack_create (ob->main_stream);
       bp_pack_value (&bp, map->replace_p, 1);
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/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/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/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;
 \f
 /* 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 ();
 }
 \f
 /* 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;
-}
-\f
-
-/* 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);
-}
-\f
-
 /* 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;
@@ -612,7 +612,48 @@ mark_all_vars_used (tree *expr_p)
   walk_tree (expr_p, mark_all_vars_used_1, NULL, NULL);
 }
 
+/* Helper function for clear_unused_block_pointer, called via walk_tree.  */
 
+static tree
+clear_unused_block_pointer_1 (tree *tp, int *, void *)
+{
+  if (EXPR_P (*tp) && TREE_BLOCK (*tp)
+      && !TREE_USED (TREE_BLOCK (*tp)))
+    TREE_SET_BLOCK (*tp, NULL);
+  if (TREE_CODE (*tp) == VAR_DECL && DECL_DEBUG_EXPR_IS_FROM (*tp))
+    {
+      tree debug_expr = DECL_DEBUG_EXPR (*tp);
+      walk_tree (&debug_expr, clear_unused_block_pointer_1, NULL, NULL);
+    }
+  return NULL_TREE;
+}
+
+/* Set all block pointer in debug stmt to NULL if the block is unused,
+   so that they will not be streamed out.  */
+
+static void
+clear_unused_block_pointer ()
+{
+  basic_block bb;
+  gimple_stmt_iterator gsi;
+  FOR_EACH_BB (bb)
+    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+      {
+	unsigned i;
+	tree b;
+	gimple stmt = gsi_stmt (gsi);
+
+	if (!is_gimple_debug (stmt))
+	  continue;
+	b = gimple_block (stmt);
+	if (b && !TREE_USED (b))
+	  gimple_set_block (stmt, NULL);
+	for (i = 0; i < gimple_num_ops (stmt); i++)
+	  walk_tree (gimple_op_ptr (stmt, i), clear_unused_block_pointer_1,
+		     NULL, NULL);
+      }
+}
+
 /* Dump scope blocks starting at SCOPE to FILE.  INDENT is the
    indentation level and FLAGS is as in print_generic_expr.  */
 
@@ -625,7 +666,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 +799,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
@@ -836,6 +882,7 @@ remove_unused_locals (void)
     VEC_truncate (tree, cfun->local_decls, dstidx);
 
   remove_unused_scope_block_p (DECL_INITIAL (current_function_decl));
+  clear_unused_block_pointer ();
 
   BITMAP_FREE (usedvars);
 
Index: gcc/lto/lto.c
===================================================================
--- gcc/lto/lto.c	(revision 191083)
+++ gcc/lto/lto.c	(working copy)
@@ -1616,7 +1616,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/ipa-prop.c
===================================================================
--- gcc/ipa-prop.c	(revision 191083)
+++ gcc/ipa-prop.c	(working copy)
@@ -303,6 +303,9 @@ ipa_set_jf_known_type (struct ipa_jump_func *jfunc
 static void
 ipa_set_jf_constant (struct ipa_jump_func *jfunc, tree constant)
 {
+  constant = unshare_expr (constant);
+  if (constant && EXPR_P (constant))
+    SET_EXPR_LOCATION (constant, UNKNOWN_LOCATION);
   jfunc->type = IPA_JF_CONST;
   jfunc->value.constant = constant;
 }
@@ -3154,6 +3157,8 @@ ipa_write_jump_function (struct output_block *ob,
       stream_write_tree (ob, jump_func->value.known_type.component_type, true);
       break;
     case IPA_JF_CONST:
+      gcc_assert (
+	  IS_UNKNOWN_LOCATION (EXPR_LOCATION (jump_func->value.constant)));
       stream_write_tree (ob, jump_func->value.constant, true);
       break;
     case IPA_JF_PASS_THROUGH:
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,20 @@ copy_phis_for_bb (basic_block bb, copy_body_data *
 		  gsi_insert_seq_on_edge (new_edge, stmts);
 		  inserted = true;
 		}
-	      add_phi_arg (new_phi, new_arg, new_edge,
-			   gimple_phi_arg_location_from_edge (phi, old_edge));
+	      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, block ?
+		  COMBINE_LOCATION_DATA (line_table, locus, block) :
+		  LOCATION_LOCUS (locus));
 	    }
 	}
     }
@@ -3874,7 +3892,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/gimple.c
===================================================================
--- gcc/gimple.c	(revision 191083)
+++ gcc/gimple.c	(working copy)
@@ -855,10 +855,7 @@ gimple_build_debug_bind_stat (tree var, tree value
   gimple_debug_bind_set_var (p, var);
   gimple_debug_bind_set_value (p, value);
   if (stmt)
-    {
-      gimple_set_block (p, gimple_block (stmt));
-      gimple_set_location (p, gimple_location (stmt));
-    }
+    gimple_set_location (p, gimple_location (stmt));
 
   return p;
 }
@@ -879,10 +876,7 @@ gimple_build_debug_source_bind_stat (tree var, tre
   gimple_debug_source_bind_set_var (p, var);
   gimple_debug_source_bind_set_value (p, value);
   if (stmt)
-    {
-      gimple_set_block (p, gimple_block (stmt));
-      gimple_set_location (p, gimple_location (stmt));
-    }
+    gimple_set_location (p, gimple_location (stmt));
 
   return p;
 }
@@ -3006,7 +3000,6 @@ gimple_call_copy_skip_args (gimple stmt, bitmap ar
   gimple_set_vuse (new_stmt, gimple_vuse (stmt));
   gimple_set_vdef (new_stmt, gimple_vdef (stmt));
 
-  gimple_set_block (new_stmt, gimple_block (stmt));
   if (gimple_has_location (stmt))
     gimple_set_location (new_stmt, gimple_location (stmt));
   gimple_call_copy_flags (new_stmt, stmt);
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,11 @@ gimple_block (const_gimple g)
 static inline void
 gimple_set_block (gimple g, tree block)
 {
-  g->gsbase.block = block;
+  if (block)
+    g->gsbase.location =
+	COMBINE_LOCATION_DATA (line_table, g->gsbase.location, block);
+  else
+    g->gsbase.location = LOCATION_LOCUS (g->gsbase.location);
 }
 
 
@@ -1241,7 +1241,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;
     }
@@ -5980,9 +5974,10 @@ 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));
-
+    {
+      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)
@@ -6282,12 +6277,14 @@ 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 = d->new_block ?
+	      COMBINE_LOCATION_DATA (line_table, e->goto_locus, d->new_block) :
+	      LOCATION_LOCUS (e->goto_locus);
 #ifdef ENABLE_CHECKING
 	else if (block != d->new_block)
 	  {
@@ -7861,13 +7858,14 @@ extern void gt_ggc_mx (basic_block&);
 void
 gt_ggc_mx (edge_def *e)
 {
+  tree block = LOCATION_BLOCK (e->goto_locus);
   gt_ggc_mx (e->src);
   gt_ggc_mx (e->dest);
   if (current_ir_type () == IR_GIMPLE)
     gt_ggc_mx (e->insns.g);
   else
     gt_ggc_mx (e->insns.r);
-  gt_ggc_mx (e->goto_block);
+  gt_ggc_mx (block);
 }
 
 /* PCH support for edge_def.  */
@@ -7880,23 +7878,25 @@ extern void gt_pch_nx (basic_block&);
 void
 gt_pch_nx (edge_def *e)
 {
+  tree block = LOCATION_BLOCK (e->goto_locus);
   gt_pch_nx (e->src);
   gt_pch_nx (e->dest);
   if (current_ir_type () == IR_GIMPLE)
     gt_pch_nx (e->insns.g);
   else
     gt_pch_nx (e->insns.r);
-  gt_pch_nx (e->goto_block);
+  gt_pch_nx (block);
 }
 
 void
 gt_pch_nx (edge_def *e, gt_pointer_operator op, void *cookie)
 {
+  tree block = LOCATION_BLOCK (e->goto_locus);
   op (&(e->src), cookie);
   op (&(e->dest), cookie);
   if (current_ir_type () == IR_GIMPLE)
     op (&(e->insns.g), cookie);
   else
     op (&(e->insns.r), cookie);
-  op (&(e->goto_block), cookie);
+  op (&(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;
 
@@ -259,6 +259,31 @@ struct GTY(()) maps_info {
   unsigned int cache;
 };
 
+/* Data structure to associate an arbitrary data to a source location.  */
+struct location_adhoc_data {
+  source_location locus;
+  void *data;
+};
+
+struct htab;
+
+/* 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.  */
+
+struct location_adhoc_data_map {
+  struct htab *htab;
+  source_location curr_loc;
+  struct location_adhoc_data *data;
+  unsigned int allocated;
+};
+
 /* A set of chronological line_map structures.  */
 struct GTY(()) line_maps {
   
@@ -289,6 +314,8 @@ struct GTY(()) line_maps {
   /* The allocators' function used to know the actual size it
      allocated, for a certain allocation size requested.  */
   line_map_round_alloc_size_func round_alloc_size;
+
+  struct location_adhoc_data_map GTY((skip)) location_adhoc_data_map;
 };
 
 /* Returns the pointer to the memory region where information about
@@ -408,6 +435,17 @@ struct GTY(()) line_maps {
 #define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
   LINEMAPS_LAST_ALLOCATED_MAP (SET, true)
 
+extern void location_adhoc_data_fini (struct line_maps *);
+extern source_location get_combined_adhoc_loc (struct line_maps *,
+					       source_location, void *);
+extern void *get_data_from_adhoc_loc (struct line_maps *, source_location);
+extern source_location get_location_from_adhoc_loc (struct line_maps *,
+						    source_location);
+
+#define IS_ADHOC_LOC(LOC) (((LOC) & MAX_SOURCE_LOCATION) != (LOC))
+#define COMBINE_LOCATION_DATA(SET, LOC, BLOCK) \
+  get_combined_adhoc_loc ((SET), (LOC), (BLOCK))
+
 /* Initialize a line map set.  */
 extern void linemap_init (struct line_maps *);
 
@@ -594,6 +632,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,120 @@ static source_location linemap_macro_loc_to_exp_po
 extern unsigned num_expanded_macros_counter;
 extern unsigned num_macro_tokens_counter;
 
+/* 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) += *((long long *) data);
+  return 1;
+}
+
+/* Combine LOCUS and DATA to a combined adhoc loc.  */
+
+source_location
+get_combined_adhoc_loc (struct line_maps *set,
+			source_location locus, void *data)
+{
+  struct location_adhoc_data lb;
+  struct location_adhoc_data **slot;
+
+  linemap_assert (data);
+
+  if (IS_ADHOC_LOC (locus))
+    locus =
+	set->location_adhoc_data_map.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 (set->location_adhoc_data_map.htab, &lb, INSERT);
+  if (*slot == NULL)
+    {
+      if (set->location_adhoc_data_map.curr_loc >=
+	  set->location_adhoc_data_map.allocated)
+	{
+	  char *orig_data = (char *) set->location_adhoc_data_map.data;
+	  long long offset;
+	  set->location_adhoc_data_map.allocated *= 2;
+	  set->location_adhoc_data_map.data =
+	      XRESIZEVEC (struct location_adhoc_data,
+			  set->location_adhoc_data_map.data,
+			  set->location_adhoc_data_map.allocated);
+	  offset = (char *) (set->location_adhoc_data_map.data) - orig_data;
+	  htab_traverse (set->location_adhoc_data_map.htab,
+			 location_adhoc_data_update, &offset);
+	}
+      *slot = set->location_adhoc_data_map.data
+	      + set->location_adhoc_data_map.curr_loc;
+      set->location_adhoc_data_map.data[
+	  set->location_adhoc_data_map.curr_loc++] = lb;
+    }
+  return ((*slot) - set->location_adhoc_data_map.data) | 0x80000000;
+}
+
+/* Return the data for the adhoc loc.  */
+
+void *
+get_data_from_adhoc_loc (struct line_maps *set, source_location loc)
+{
+  linemap_assert (IS_ADHOC_LOC (loc));
+  return set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].data;
+}
+
+/* Return the location for the adhoc loc.  */
+
+source_location
+get_location_from_adhoc_loc (struct line_maps *set, source_location loc)
+{
+  linemap_assert (IS_ADHOC_LOC (loc));
+  return set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
+}
+
+/* Initialize the location_adhoc_data structure.  */
+
+static void
+location_adhoc_data_init (struct line_maps *set)
+{
+  set->location_adhoc_data_map.htab =
+      htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL);
+  set->location_adhoc_data_map.curr_loc = 0;
+  set->location_adhoc_data_map.allocated = 100;
+  set->location_adhoc_data_map.data = XNEWVEC (struct location_adhoc_data, 100);
+}
+
+/* Finalize the location_adhoc_data structure.  */
+void
+location_adhoc_data_fini (struct line_maps *set)
+{
+  set->location_adhoc_data_map.allocated = 0;
+  XDELETEVEC (set->location_adhoc_data_map.data);
+  htab_delete (set->location_adhoc_data_map.htab);
+}
+
 /* Initialize a line map set.  */
 
 void
@@ -58,6 +173,7 @@ linemap_init (struct line_maps *set)
   memset (set, 0, sizeof (struct line_maps));
   set->highest_location = RESERVED_LOCATION_COUNT - 1;
   set->highest_line = RESERVED_LOCATION_COUNT - 1;
+  location_adhoc_data_init (set);
 }
 
 /* Check for and warn about line_maps entered but not exited.  */
@@ -408,12 +524,12 @@ linemap_line_start (struct line_maps *set, linenum
   if (add_map)
     {
       int column_bits;
-      if (max_column_hint > 100000 || highest > 0xC0000000)
+      if (max_column_hint > 100000 || highest > 0x60000000)
 	{
 	  /* If the column number is ridiculous or we've allocated a huge
 	     number of source_locations, give up on column numbers. */
 	  max_column_hint = 0;
-	  if (highest >0xF0000000)
+	  if (highest >0x70000000)
 	    return 0;
 	  column_bits = 0;
 	}
@@ -509,6 +625,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 = set->location_adhoc_data_map.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 +643,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 = set->location_adhoc_data_map.data[line & MAX_SOURCE_LOCATION].locus;
+
   if (set ==  NULL || line < RESERVED_LOCATION_COUNT)
     return NULL;
 
@@ -570,6 +691,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 = set->location_adhoc_data_map.data[line & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
 
   if (set ==  NULL)
@@ -696,6 +820,10 @@ linemap_get_expansion_line (struct line_maps *set,
 {
   const struct line_map *map = NULL;
 
+  if (IS_ADHOC_LOC (location))
+    location = set->location_adhoc_data_map.data[
+	location & MAX_SOURCE_LOCATION].locus;
+
   if (location < RESERVED_LOCATION_COUNT)
     return 0;
 
@@ -720,6 +848,10 @@ linemap_get_expansion_filename (struct line_maps *
 {
   const struct line_map *map = NULL;
 
+  if (IS_ADHOC_LOC (location))
+    location = set->location_adhoc_data_map.data[
+	location & MAX_SOURCE_LOCATION].locus;
+
   if (location < RESERVED_LOCATION_COUNT)
     return NULL;
 
@@ -754,6 +886,10 @@ linemap_location_in_system_header_p (struct line_m
 {
   const struct line_map *map = NULL;
 
+  if (IS_ADHOC_LOC (location))
+    location = set->location_adhoc_data_map.data[
+	location & MAX_SOURCE_LOCATION].locus;
+
   if (location < RESERVED_LOCATION_COUNT)
     return false;
 
@@ -793,6 +929,10 @@ bool
 linemap_location_from_macro_expansion_p (struct line_maps *set,
 					 source_location location)
 {
+  if (IS_ADHOC_LOC (location))
+    location = set->location_adhoc_data_map.data[
+	location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (location <= MAX_SOURCE_LOCATION
 		  && (set->highest_location
 		      < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
@@ -933,6 +1073,10 @@ linemap_macro_loc_to_spelling_point (struct line_m
 {
   struct line_map *map;
 
+  if (IS_ADHOC_LOC (location))
+    location = set->location_adhoc_data_map.data[
+	location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
 
   while (true)
@@ -967,6 +1111,10 @@ linemap_macro_loc_to_def_point (struct line_maps *
 {
   struct line_map *map;
 
+  if (IS_ADHOC_LOC (location))
+    location = set->location_adhoc_data_map.data[
+	location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
 
   while (true)
@@ -1005,6 +1153,10 @@ linemap_macro_loc_to_exp_point (struct line_maps *
 {
   struct line_map *map;
 
+  if (IS_ADHOC_LOC (location))
+    location = set->location_adhoc_data_map.data[
+	location & MAX_SOURCE_LOCATION].locus;
+
   linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
 
   while (true)
@@ -1074,6 +1226,9 @@ linemap_resolve_location (struct line_maps *set,
 			  enum location_resolution_kind lrk,
 			  const struct line_map **map)
 {
+  if (IS_ADHOC_LOC (loc))
+    loc = set->location_adhoc_data_map.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 +1276,9 @@ linemap_unwind_toward_expansion (struct line_maps
   source_location resolved_location;
   const struct line_map *resolved_map;
 
+  if (IS_ADHOC_LOC (loc))
+    loc = set->location_adhoc_data_map.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 +1315,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 = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
+
   map0 = linemap_lookup (set, loc);
   if (!linemap_macro_expansion_map_p (map0))
     return loc;
@@ -1198,6 +1359,12 @@ linemap_expand_location (struct line_maps *set,
   expanded_location xloc;
 
   memset (&xloc, 0, sizeof (xloc));
+  if (IS_ADHOC_LOC (loc))
+    {
+      loc = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
+      xloc.data = set->location_adhoc_data_map.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 +1457,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 = set->location_adhoc_data_map.data[loc & MAX_SOURCE_LOCATION].locus;
+
   if (loc == 0)
     return;
 

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-13 17:37                                                                       ` Mike Stump
@ 2012-09-14  6:49                                                                         ` Richard Guenther
  2012-09-14  8:59                                                                           ` Eric Botcazou
  0 siblings, 1 reply; 93+ messages in thread
From: Richard Guenther @ 2012-09-14  6:49 UTC (permalink / raw)
  To: Mike Stump
  Cc: Robert Dewar, Jakub Jelinek, Dehao Chen, Xinliang David Li,
	Michael Matz, Diego Novillo, Dodji Seketeli, GCC Patches,
	Jan Hubicka, Tom Tromey, Jason Merrill, Richard Henderson

On Thu, Sep 13, 2012 at 7:37 PM, Mike Stump <mikestump@comcast.net> wrote:
> On Sep 13, 2012, at 6:52 AM, Robert Dewar <dewar@adacore.com> wrote:
>> Sure, it is obvious that you don't want -g to affect -O1 or -O2 code,
>> but I think if you have -Og (if and when we have that), it would not
>> be a bad thing for -g to affect that.
>
> No, instead think of -Og as affecting the -g output itself.  If it does, then there is nothing for -g to affect when used with -Og.  So, I agree, -g -Og can have any impact on code-gen that we want, I just dis-agree that -Og should be any different; I just don't see the need.

I think it's going to make GCC harder to maintain if we drop the -g0
vs. -g no-code-difference requirement for just some optimization
levels.

Richard.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-14  6:49                                                                         ` Richard Guenther
@ 2012-09-14  8:59                                                                           ` Eric Botcazou
  2012-09-14 10:30                                                                             ` Diego Novillo
  0 siblings, 1 reply; 93+ messages in thread
From: Eric Botcazou @ 2012-09-14  8:59 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Tom Tromey, gcc-patches, Mike Stump, Robert Dewar, Jakub Jelinek,
	Dehao Chen, Xinliang David Li, Michael Matz, Diego Novillo,
	Dodji Seketeli, Jan Hubicka, Jason Merrill, Richard Henderson

> I think it's going to make GCC harder to maintain if we drop the -g0
> vs. -g no-code-difference requirement for just some optimization
> levels.

Seconded, this is surely going to open yet another can of worms.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-14  8:59                                                                           ` Eric Botcazou
@ 2012-09-14 10:30                                                                             ` Diego Novillo
  0 siblings, 0 replies; 93+ messages in thread
From: Diego Novillo @ 2012-09-14 10:30 UTC (permalink / raw)
  To: Eric Botcazou
  Cc: Richard Guenther, Tom Tromey, gcc-patches, Mike Stump,
	Robert Dewar, Jakub Jelinek, Dehao Chen, Xinliang David Li,
	Michael Matz, Dodji Seketeli, Jan Hubicka, Jason Merrill,
	Richard Henderson

On 2012-09-14 04:59 , Eric Botcazou wrote:
>> I think it's going to make GCC harder to maintain if we drop the -g0
>> vs. -g no-code-difference requirement for just some optimization
>> levels.
>
> Seconded, this is surely going to open yet another can of worms.

Agreed.


Diego.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-14  3:04                                     ` Dehao Chen
@ 2012-09-19  8:48                                       ` Jan Hubicka
  2012-09-19  9:22                                         ` Richard Guenther
  2012-09-19 22:58                                       ` Michael Meissner
  1 sibling, 1 reply; 93+ messages in thread
From: Jan Hubicka @ 2012-09-19  8:48 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Tom Tromey, Diego Novillo, Richard Guenther, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, David Li, Jason Merrill,
	Richard Henderson

> Hi,
> 
> I've integrated all the reviews from this thread (Thank you guys for
> helping refine this patch).
> 
> Now the patch can pass all gcc testsuite as well as all spec2006
> benchmarks (with LTO). Concerning memory consumption, for extreme
> benchmarks like tramp3d, this patch incurs around 2% peak memory
> overhead (mostly from the extra blocks that have been set NULL in the
> original implementation.)
> 
> Attached is the new patch. Honza, could you help me try this on
> Mozzila lto to see if the error is gone?
Hi,
I tested the last version you posed and it works fine. (i.e. no ICE)
I also observed no real differences in memory use.
linemap lookup seems to be bottleneck on streaming out stage of WPA.
I wonder if we can't stream location better into LTO objects, by perhaps
using same encoding as we do in memory (i.e. streaming out locators and
separate table)

Honza

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-19  8:48                                       ` Jan Hubicka
@ 2012-09-19  9:22                                         ` Richard Guenther
  0 siblings, 0 replies; 93+ messages in thread
From: Richard Guenther @ 2012-09-19  9:22 UTC (permalink / raw)
  To: Jan Hubicka
  Cc: Dehao Chen, Tom Tromey, Diego Novillo, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, David Li, Jason Merrill,
	Richard Henderson

On Wed, Sep 19, 2012 at 10:48 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> Hi,
>>
>> I've integrated all the reviews from this thread (Thank you guys for
>> helping refine this patch).
>>
>> Now the patch can pass all gcc testsuite as well as all spec2006
>> benchmarks (with LTO). Concerning memory consumption, for extreme
>> benchmarks like tramp3d, this patch incurs around 2% peak memory
>> overhead (mostly from the extra blocks that have been set NULL in the
>> original implementation.)
>>
>> Attached is the new patch. Honza, could you help me try this on
>> Mozzila lto to see if the error is gone?
> Hi,
> I tested the last version you posed and it works fine. (i.e. no ICE)
> I also observed no real differences in memory use.
> linemap lookup seems to be bottleneck on streaming out stage of WPA.
> I wonder if we can't stream location better into LTO objects, by perhaps
> using same encoding as we do in memory (i.e. streaming out locators and
> separate table)

Yes, I think we should consider streaming locations separately so that we
can read them in in one chunk and sort them to be able to assign most
compact location_t's to them.

Dehao, the patch is ok for trunk - please be on the watch to address possible
fallout.

Thanks,
Richard.

> Honza

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-12 14:18                                                           ` Michael Matz
  2012-09-12 14:37                                                             ` Martin Jambor
@ 2012-09-19  9:40                                                             ` Martin Jambor
  2012-09-19 14:00                                                               ` Michael Matz
  1 sibling, 1 reply; 93+ messages in thread
From: Martin Jambor @ 2012-09-19  9:40 UTC (permalink / raw)
  To: GCC Patches
  Cc: Richard Guenther, Dehao Chen, Jan Hubicka, David Li, Michael Matz

Hi,

On Wed, Sep 12, 2012 at 04:17:45PM +0200, Michael Matz wrote:
> Hi,
> 
> On Wed, 12 Sep 2012, Michael Matz wrote:
> 
> > > 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.
> 
> ipa-prop creates the problem.  Its tree mapping can contain expressions, 
> expressions can have locations, locations now have blocks.  The tree maps 
> are stored as part of jump functions, and hence as part of node summaries.  
> Node summaries are global, hence blocks, and therefore block vars can be 
> placed in the global blob.
> 
> That's not supposed to happen.  The patch below fixes this instance of the 
> problem and makes the testcase work with Dehaos patch with the 
> LTO_NO_PREVAIL call added back in.
> 

The following patch implements the unsharing and location pruning at
all required places in a way that passes bootstrap and testing on an
x86_64-linux.  Honza pre-approved it on IRC so unless there are any
objections within a few hours I'm going to commit it.

(The patch does not introduce any of the asserts Michael's patch had
because, as far as I my grep told me, IS_UNKNOWN_LOCATION is not in
trunk yet and I suppose the pre-approval does not cover introducing
things like that.)

Thanks,

Martin


2012-09-18  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.c (prune_expression_for_jf): New function.
	(ipa_set_jf_constant): Use it.
	(ipa_set_jf_arith_pass_through): Likewise.
	(determine_known_aggregate_parts): Likewise.

Index: src/gcc/ipa-prop.c
===================================================================
--- src.orig/gcc/ipa-prop.c
+++ src/gcc/ipa-prop.c
@@ -287,6 +287,19 @@ ipa_print_all_jump_functions (FILE *f)
     }
 }
 
+/* Return the expression tree EXPR unshared and with location stripped off.  */
+
+static tree
+prune_expression_for_jf (tree exp)
+{
+  if (EXPR_P (exp))
+    {
+      exp = unshare_expr (exp);
+      SET_EXPR_LOCATION (exp, UNKNOWN_LOCATION);
+    }
+  return exp;
+}
+
 /* Set JFUNC to be a known type jump function.  */
 
 static void
@@ -305,7 +318,7 @@ static void
 ipa_set_jf_constant (struct ipa_jump_func *jfunc, tree constant)
 {
   jfunc->type = IPA_JF_CONST;
-  jfunc->value.constant = constant;
+  jfunc->value.constant = prune_expression_for_jf (constant);
 }
 
 /* Set JFUNC to be a simple pass-through jump function.  */
@@ -327,7 +340,7 @@ ipa_set_jf_arith_pass_through (struct ip
 			       tree operand, enum tree_code operation)
 {
   jfunc->type = IPA_JF_PASS_THROUGH;
-  jfunc->value.pass_through.operand = operand;
+  jfunc->value.pass_through.operand = prune_expression_for_jf (operand);
   jfunc->value.pass_through.formal_id = formal_id;
   jfunc->value.pass_through.operation = operation;
   jfunc->value.pass_through.agg_preserved = false;
@@ -1344,7 +1357,7 @@ determine_known_aggregate_parts (gimple
 	    {
 	      struct ipa_agg_jf_item item;
 	      item.offset = list->offset - arg_offset;
-	      item.value = list->constant;
+	      item.value = prune_expression_for_jf (list->constant);
 	      VEC_quick_push (ipa_agg_jf_item_t, jfunc->agg.items, item);
 	    }
 	  list = list->next;

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-19  9:40                                                             ` Martin Jambor
@ 2012-09-19 14:00                                                               ` Michael Matz
  2012-09-19 20:15                                                                 ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Michael Matz @ 2012-09-19 14:00 UTC (permalink / raw)
  To: Martin Jambor
  Cc: GCC Patches, Richard Guenther, Dehao Chen, Jan Hubicka, David Li

Hi,
On Wed, 19 Sep 2012, Martin Jambor wrote:

> (The patch does not introduce any of the asserts Michael's patch had 
> because, as far as I my grep told me, IS_UNKNOWN_LOCATION is not in 
> trunk yet and I suppose the pre-approval does not cover introducing 
> things like that.)

Dehaos patch contains it.  For current trunk it would simply be an 
equality test with UNKNOWN_LOCATION.  If have no opinion if the asserts 
should be there or not.


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-19 14:00                                                               ` Michael Matz
@ 2012-09-19 20:15                                                                 ` Dehao Chen
  2012-09-20 13:20                                                                   ` Paolo Carlini
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-09-19 20:15 UTC (permalink / raw)
  To: Michael Matz
  Cc: Martin Jambor, GCC Patches, Richard Guenther, Jan Hubicka, David Li

This patch was commited as r191494.

Thank all for the reviews and helping test.
Dehao

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-14  3:04                                     ` Dehao Chen
  2012-09-19  8:48                                       ` Jan Hubicka
@ 2012-09-19 22:58                                       ` Michael Meissner
  2012-09-20  0:51                                         ` Dehao Chen
  1 sibling, 1 reply; 93+ messages in thread
From: Michael Meissner @ 2012-09-19 22:58 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Tom Tromey, Diego Novillo, Richard Guenther, Dodji Seketeli,
	GCC Patches, Jakub Jelinek, Jan Hubicka, David Li, Jason Merrill,
	Richard Henderson

On Fri, Sep 14, 2012 at 11:03:34AM +0800, Dehao Chen wrote:
> Hi,
> 
> I've integrated all the reviews from this thread (Thank you guys for
> helping refine this patch).
> 
> Now the patch can pass all gcc testsuite as well as all spec2006
> benchmarks (with LTO). Concerning memory consumption, for extreme
> benchmarks like tramp3d, this patch incurs around 2% peak memory
> overhead (mostly from the extra blocks that have been set NULL in the
> original implementation.)
> 
> Attached is the new patch. Honza, could you help me try this on
> Mozzila lto to see if the error is gone?

The current patch that was checked in breaks powerpc, because you did not
change INSN_LOCATOR to INSN_LOCATION in rs6000_final_prescan_insn in rs6000.c.
I also see INSN_LOCATOR in the arm, bfin, c6x, mep, mips, picochip, s390, sh,
and spu ports.

-- 
Michael Meissner, IBM
5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA
meissner@linux.vnet.ibm.com	fax +1 (978) 399-6899

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-19 22:58                                       ` Michael Meissner
@ 2012-09-20  0:51                                         ` Dehao Chen
  2012-09-20  1:04                                           ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-09-20  0:51 UTC (permalink / raw)
  To: Michael Meissner, Dehao Chen, Tom Tromey, Diego Novillo,
	Richard Guenther, Dodji Seketeli, GCC Patches, Jakub Jelinek,
	Jan Hubicka, David Li, Jason Merrill, Richard Henderson

Thanks for reporting. I'll fix them now.

Dehao

On Thu, Sep 20, 2012 at 6:29 AM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> On Fri, Sep 14, 2012 at 11:03:34AM +0800, Dehao Chen wrote:
>> Hi,
>>
>> I've integrated all the reviews from this thread (Thank you guys for
>> helping refine this patch).
>>
>> Now the patch can pass all gcc testsuite as well as all spec2006
>> benchmarks (with LTO). Concerning memory consumption, for extreme
>> benchmarks like tramp3d, this patch incurs around 2% peak memory
>> overhead (mostly from the extra blocks that have been set NULL in the
>> original implementation.)
>>
>> Attached is the new patch. Honza, could you help me try this on
>> Mozzila lto to see if the error is gone?
>
> The current patch that was checked in breaks powerpc, because you did not
> change INSN_LOCATOR to INSN_LOCATION in rs6000_final_prescan_insn in rs6000.c.
> I also see INSN_LOCATOR in the arm, bfin, c6x, mep, mips, picochip, s390, sh,
> and spu ports.
>
> --
> Michael Meissner, IBM
> 5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA
> meissner@linux.vnet.ibm.com     fax +1 (978) 399-6899
>

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20  0:51                                         ` Dehao Chen
@ 2012-09-20  1:04                                           ` Dehao Chen
  0 siblings, 0 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-20  1:04 UTC (permalink / raw)
  To: Michael Meissner, Dehao Chen, Tom Tromey, Diego Novillo,
	Richard Guenther, Dodji Seketeli, GCC Patches, Jakub Jelinek,
	Jan Hubicka, David Li, Jason Merrill, Richard Henderson

[-- Attachment #1: Type: text/plain, Size: 962 bytes --]

The patch to fix this problem is attached. As I don't have machines
other than x86, I cannot test it. But this patch seemed
straightforward. I'll check it in in a couple of hours if no objection
is received.

Thanks,
Dehao

gcc/ChangeLog:

2012-09-19  Dehao Chen  <dehao@google.com>

	* config/s390/s390.c (s390_chunkify_start): Replacing INSN_LOCATOR.
	* config/spu/spu.c (emit_nop_for_insn): Likewise.
	(pad_bb): Likewise.
	(spu_emit_branch_hint): Likewise.
	(insert_hbrp_for_ilb_runout): Likewise.
	* config/mep/mep.c (mep_make_bundle): Likewise.
	(mep_bundle_insns): Likewise.
	* config/sh/sh.c (gen_block_redirect): Likewise.
	* config/c6x/c6x.c (gen_one_bundle): Likewise.
	* config/rs6000/rs6000.c (rs6000_final_prescan_insn): Likewise.
	* config/picochip/picochip.c (picochip_reorg): Likewise.
	* config/arm/arm.c (require_pic_register): Likewise.
	* config/mips/mips.c (mips16_gp_pseudo_reg): Likewise.
	* config/bfin/bfin.c (gen_one_bundle): Likewise.

[-- Attachment #2: patch1.txt --]
[-- Type: text/plain, Size: 10490 bytes --]

Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	(revision 191494)
+++ gcc/config/s390/s390.c	(working copy)
@@ -6869,7 +6869,7 @@ s390_chunkify_start (void)
 		prev = prev_nonnote_insn (prev);
 	      if (prev)
 		jump = emit_jump_insn_after_setloc (gen_jump (label), insn,
-						    INSN_LOCATOR (prev));
+						    INSN_LOCATION (prev));
 	      else
 		jump = emit_jump_insn_after_noloc (gen_jump (label), insn);
 	      barrier = emit_barrier_after (jump);
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	(revision 191494)
+++ gcc/config/spu/spu.c	(working copy)
@@ -1998,7 +1998,7 @@ emit_nop_for_insn (rtx insn)
   else
     new_insn = emit_insn_after (gen_lnop (), insn);
   recog_memoized (new_insn);
-  INSN_LOCATOR (new_insn) = INSN_LOCATOR (insn);
+  INSN_LOCATION (new_insn) = INSN_LOCATION (insn);
 }
 
 /* Insert nops in basic blocks to meet dual issue alignment
@@ -2037,7 +2037,7 @@ pad_bb(void)
 		  prev_insn = emit_insn_before (gen_lnop (), insn);
 		  PUT_MODE (prev_insn, GET_MODE (insn));
 		  PUT_MODE (insn, TImode);
-		  INSN_LOCATOR (prev_insn) = INSN_LOCATOR (insn);
+		  INSN_LOCATION (prev_insn) = INSN_LOCATION (insn);
 		  length += 4;
 		}
 	    }
@@ -2106,7 +2106,7 @@ spu_emit_branch_hint (rtx before, rtx branch, rtx
 
   hint = emit_insn_before (gen_hbr (branch_label, target), before);
   recog_memoized (hint);
-  INSN_LOCATOR (hint) = INSN_LOCATOR (branch);
+  INSN_LOCATION (hint) = INSN_LOCATION (branch);
   HINTED_P (branch) = 1;
 
   if (GET_CODE (target) == LABEL_REF)
@@ -2129,7 +2129,7 @@ spu_emit_branch_hint (rtx before, rtx branch, rtx
          which could make it too far for the branch offest to fit */
       insn = emit_insn_before (gen_blockage (), hint);
       recog_memoized (insn);
-      INSN_LOCATOR (insn) = INSN_LOCATOR (hint);
+      INSN_LOCATION (insn) = INSN_LOCATION (hint);
     }
   else if (distance <= 8 * 4)
     {
@@ -2141,20 +2141,20 @@ spu_emit_branch_hint (rtx before, rtx branch, rtx
 	  insn =
 	    emit_insn_after (gen_nopn_nv (gen_rtx_REG (SImode, 127)), hint);
 	  recog_memoized (insn);
-	  INSN_LOCATOR (insn) = INSN_LOCATOR (hint);
+	  INSN_LOCATION (insn) = INSN_LOCATION (hint);
 	}
 
       /* Make sure any nops inserted aren't scheduled before the hint. */
       insn = emit_insn_after (gen_blockage (), hint);
       recog_memoized (insn);
-      INSN_LOCATOR (insn) = INSN_LOCATOR (hint);
+      INSN_LOCATION (insn) = INSN_LOCATION (hint);
 
       /* Make sure any nops inserted aren't scheduled after the call. */
       if (CALL_P (branch) && distance < 8 * 4)
 	{
 	  insn = emit_insn_before (gen_blockage (), branch);
 	  recog_memoized (insn);
-	  INSN_LOCATOR (insn) = INSN_LOCATOR (branch);
+	  INSN_LOCATION (insn) = INSN_LOCATION (branch);
 	}
     }
 }
@@ -2340,7 +2340,7 @@ insert_hbrp_for_ilb_runout (rtx first)
 		insn =
 		  emit_insn_before (gen_iprefetch (GEN_INT (1)), before_4);
 		recog_memoized (insn);
-		INSN_LOCATOR (insn) = INSN_LOCATOR (before_4);
+		INSN_LOCATION (insn) = INSN_LOCATION (before_4);
 		INSN_ADDRESSES_NEW (insn,
 				    INSN_ADDRESSES (INSN_UID (before_4)));
 		PUT_MODE (insn, GET_MODE (before_4));
@@ -2349,7 +2349,7 @@ insert_hbrp_for_ilb_runout (rtx first)
 		  {
 		    insn = emit_insn_before (gen_lnop (), before_4);
 		    recog_memoized (insn);
-		    INSN_LOCATOR (insn) = INSN_LOCATOR (before_4);
+		    INSN_LOCATION (insn) = INSN_LOCATION (before_4);
 		    INSN_ADDRESSES_NEW (insn,
 					INSN_ADDRESSES (INSN_UID (before_4)));
 		    PUT_MODE (insn, TImode);
@@ -2361,7 +2361,7 @@ insert_hbrp_for_ilb_runout (rtx first)
 		insn =
 		  emit_insn_before (gen_iprefetch (GEN_INT (2)), before_16);
 		recog_memoized (insn);
-		INSN_LOCATOR (insn) = INSN_LOCATOR (before_16);
+		INSN_LOCATION (insn) = INSN_LOCATION (before_16);
 		INSN_ADDRESSES_NEW (insn,
 				    INSN_ADDRESSES (INSN_UID (before_16)));
 		PUT_MODE (insn, GET_MODE (before_16));
@@ -2370,7 +2370,7 @@ insert_hbrp_for_ilb_runout (rtx first)
 		  {
 		    insn = emit_insn_before (gen_lnop (), before_16);
 		    recog_memoized (insn);
-		    INSN_LOCATOR (insn) = INSN_LOCATOR (before_16);
+		    INSN_LOCATION (insn) = INSN_LOCATION (before_16);
 		    INSN_ADDRESSES_NEW (insn,
 					INSN_ADDRESSES (INSN_UID
 							(before_16)));
Index: gcc/config/mep/mep.c
===================================================================
--- gcc/config/mep/mep.c	(revision 191494)
+++ gcc/config/mep/mep.c	(working copy)
@@ -6814,9 +6814,9 @@ mep_make_bundle (rtx core, rtx cop)
   /* Derive a location for the bundle.  Individual instructions cannot
      have their own location because there can be no assembler labels
      between CORE and COP.  */
-  INSN_LOCATOR (insn) = INSN_LOCATOR (INSN_LOCATOR (core) ? core : cop);
-  INSN_LOCATOR (core) = 0;
-  INSN_LOCATOR (cop) = 0;
+  INSN_LOCATION (insn) = INSN_LOCATION (INSN_LOCATION (core) ? core : cop);
+  INSN_LOCATION (core) = 0;
+  INSN_LOCATION (cop) = 0;
 
   return insn;
 }
@@ -6913,7 +6913,7 @@ mep_bundle_insns (rtx insns)
 	     whenever the current line changes, set the location info
 	     for INSN to match FIRST.  */
 
-	  INSN_LOCATOR (insn) = INSN_LOCATOR (first);
+	  INSN_LOCATION (insn) = INSN_LOCATION (first);
 
 	  note = PREV_INSN (insn);
 	  while (note && note != first)
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	(revision 191494)
+++ gcc/config/sh/sh.c	(working copy)
@@ -5530,7 +5530,7 @@ gen_block_redirect (rtx jump, int addr, int need_b
 	 NOTE_INSN_BLOCK_END notes between the indirect_jump_scratch and
 	 the jump.  */
 
-      INSN_LOCATOR (insn) = INSN_LOCATOR (jump);
+      INSN_LOCATION (insn) = INSN_LOCATION (jump);
       INSN_CODE (insn) = CODE_FOR_indirect_jump_scratch;
       return insn;
     }
Index: gcc/config/c6x/c6x.c
===================================================================
--- gcc/config/c6x/c6x.c	(revision 191494)
+++ gcc/config/c6x/c6x.c	(working copy)
@@ -4595,7 +4595,7 @@ gen_one_bundle (rtx *slot, int n_filled, int real_
   bundle = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec_v (n_filled, slot));
   bundle = make_insn_raw (bundle);
   BLOCK_FOR_INSN (bundle) = BLOCK_FOR_INSN (slot[0]);
-  INSN_LOCATOR (bundle) = INSN_LOCATOR (slot[0]);
+  INSN_LOCATION (bundle) = INSN_LOCATION (slot[0]);
   PREV_INSN (bundle) = PREV_INSN (slot[real_first]);
 
   t = NULL_RTX;
@@ -4609,7 +4609,7 @@ gen_one_bundle (rtx *slot, int n_filled, int real_
 	NEXT_INSN (t) = insn;
       t = insn;
       if (i > 0)
-	INSN_LOCATOR (slot[i]) = INSN_LOCATOR (bundle);
+	INSN_LOCATION (slot[i]) = INSN_LOCATION (bundle);
     }
 
   NEXT_INSN (bundle) = NEXT_INSN (PREV_INSN (bundle));
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 191494)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -27351,7 +27351,7 @@ rs6000_final_prescan_insn (rtx insn, rtx *operand
     {
       const char *temp;
       int insn_code_number = recog_memoized (insn);
-      location_t location = locator_location (INSN_LOCATOR (insn));
+      location_t location = INSN_LOCATION (insn);
 
       /* Punt on insns we cannot recognize.  */
       if (insn_code_number < 0)
Index: gcc/config/picochip/picochip.c
===================================================================
--- gcc/config/picochip/picochip.c	(revision 191494)
+++ gcc/config/picochip/picochip.c	(working copy)
@@ -3298,16 +3298,16 @@ picochip_reorg (void)
               if (GET_MODE (insn) == TImode)
               {
                 vliw_start = insn;
-                vliw_insn_location = INSN_LOCATOR (insn);
+                vliw_insn_location = INSN_LOCATION (insn);
               }
               if (JUMP_P (insn) || CALL_P(insn))
               {
-                vliw_insn_location = INSN_LOCATOR (insn);
+                vliw_insn_location = INSN_LOCATION (insn);
                 for (insn1 = vliw_start; insn1 != insn ; insn1 = next_real_insn (insn1))
-                  INSN_LOCATOR (insn1) = vliw_insn_location;
+                  INSN_LOCATION (insn1) = vliw_insn_location;
               }
               /* Tag subsequent instructions with the same location. */
-              INSN_LOCATOR (insn) = vliw_insn_location;
+              INSN_LOCATION (insn) = vliw_insn_location;
 	    }
 	}
 
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	(revision 191494)
+++ gcc/config/arm/arm.c	(working copy)
@@ -5359,7 +5359,7 @@ require_pic_register (void)
 
 	      for (insn = seq; insn; insn = NEXT_INSN (insn))
 		if (INSN_P (insn))
-		  INSN_LOCATOR (insn) = prologue_locator;
+		  INSN_LOCATION (insn) = prologue_location;
 
 	      /* We can be called during expansion of PHI nodes, where
 	         we can't yet emit instructions directly in the final
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	(revision 191494)
+++ gcc/config/mips/mips.c	(working copy)
@@ -2628,7 +2628,7 @@ mips16_gp_pseudo_reg (void)
 
       insn = gen_load_const_gp (cfun->machine->mips16_gp_pseudo_rtx);
       insn = emit_insn_after (insn, scan);
-      INSN_LOCATOR (insn) = 0;
+      INSN_LOCATION (insn) = 0;
 
       pop_topmost_sequence ();
     }
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	(revision 191494)
+++ gcc/config/bfin/bfin.c	(working copy)
@@ -3918,12 +3918,12 @@ gen_one_bundle (rtx slot[3])
     }
 
   /* Avoid line number information being printed inside one bundle.  */
-  if (INSN_LOCATOR (slot[1])
-      && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
-    INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
-  if (INSN_LOCATOR (slot[2])
-      && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
-    INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
+  if (INSN_LOCATION (slot[1])
+      && INSN_LOCATION (slot[1]) != INSN_LOCATION (slot[0]))
+    INSN_LOCATION (slot[1]) = INSN_LOCATION (slot[0]);
+  if (INSN_LOCATION (slot[2])
+      && INSN_LOCATION (slot[2]) != INSN_LOCATION (slot[0]))
+    INSN_LOCATION (slot[2]) = INSN_LOCATION (slot[0]);
 
   /* Terminate them with "|| " instead of ";" in the output.  */
   PUT_MODE (slot[0], SImode);

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-19 20:15                                                                 ` Dehao Chen
@ 2012-09-20 13:20                                                                   ` Paolo Carlini
  2012-09-20 14:05                                                                     ` Paolo Carlini
  2012-09-20 15:45                                                                     ` Dehao Chen
  0 siblings, 2 replies; 93+ messages in thread
From: Paolo Carlini @ 2012-09-20 13:20 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Michael Matz, Martin Jambor, GCC Patches, Richard Guenther,
	Jan Hubicka, David Li

Hi,

On 09/19/2012 09:59 PM, Dehao Chen wrote:
> This patch was commited as r191494.
I'm afraid I can't help *much* with the debugging, but on my 
x86_64-linux machine and a very straightforward configuration 
(--enable-languages=c++ --disable-multilib) after r191494 I'm seeing the 
following libstdc++ regressions.

FAIL: 17_intro/headers/c++1998/all.cc (test for excess errors)
FAIL: 17_intro/headers/c++1998/all_c++200x_compatibility.cc (test for 
excess errors)
FAIL: 17_intro/headers/c++1998/all_pedantic_errors.cc (test for excess 
errors)
FAIL: 17_intro/headers/c++1998/stdc++.cc (test for excess errors)
FAIL: 17_intro/headers/c++1998/stdc++_multiple_inclusion.cc (test for 
excess errors)
FAIL: 17_intro/headers/c++200x/stdc++.cc (test for excess errors)
FAIL: 17_intro/headers/c++200x/stdc++_multiple_inclusion.cc (test for 
excess errors)

are all ICEs like the below. Apparently PCHs are required, I can't 
reproduce outside the testsuite, without the library PCHs.

Does it make any sense to you? Please let me know if I can somehow help.

Thanks,
Paolo.

///////////////////

In file included from 
/home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/basic_ios.h:39:0, 

                  from 
/home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/ios:45, 

                  from 
/home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/istream:40, 

                  from 
/home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/sstream:39, 

                  from 
/home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/complex:47, 

                  from 
/home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/x86_64-unknown-linux-gnu/bits/stdc++.h:67, 

                  from 
/home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/x86_64-unknown-linux-gnu/bits/stdtr1c++.h:29, 

                  from 
/scratch/Gcc/svn-dirs/trunk/libstdc++-v3/include/precompiled/extc++.h:30:
/home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/locale_facets.h: 
In member function 'virtual std::ctype<char>::char_type 
std::ctype<char>::do_widen(char) const':
/home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/locale_facets.h:1077:7: 
internal compiler error: Segmentation fault
        do_widen(char __c) const
        ^
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.


^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20 13:20                                                                   ` Paolo Carlini
@ 2012-09-20 14:05                                                                     ` Paolo Carlini
  2012-09-20 14:13                                                                       ` Martin Jambor
  2012-09-20 15:45                                                                     ` Dehao Chen
  1 sibling, 1 reply; 93+ messages in thread
From: Paolo Carlini @ 2012-09-20 14:05 UTC (permalink / raw)
  To: Paolo Carlini
  Cc: Dehao Chen, Michael Matz, Martin Jambor, GCC Patches,
	Richard Guenther, Jan Hubicka, David Li

On 09/20/2012 03:04 PM, Paolo Carlini wrote:
> are all ICEs like the below. Apparently PCHs are required, I can't 
> reproduce outside the testsuite, without the library PCHs.
Take this only as a vague hint: I'm seeing many pch-related regressions 
here, between r191490 and r191501:

     http://gcc.gnu.org/ml/gcc-testresults/2012-09/msg01906.html
     http://gcc.gnu.org/ml/gcc-testresults/2012-09/msg01924.html

Paolo.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20 14:05                                                                     ` Paolo Carlini
@ 2012-09-20 14:13                                                                       ` Martin Jambor
  2012-09-20 14:45                                                                         ` Paolo Carlini
  2012-09-20 14:47                                                                         ` Jan Hubicka
  0 siblings, 2 replies; 93+ messages in thread
From: Martin Jambor @ 2012-09-20 14:13 UTC (permalink / raw)
  To: Paolo Carlini
  Cc: Dehao Chen, Michael Matz, GCC Patches, Richard Guenther,
	Jan Hubicka, David Li

On Thu, Sep 20, 2012 at 03:26:29PM +0200, Paolo Carlini wrote:
> On 09/20/2012 03:04 PM, Paolo Carlini wrote:
> >are all ICEs like the below. Apparently PCHs are required, I can't
> >reproduce outside the testsuite, without the library PCHs.
> Take this only as a vague hint: I'm seeing many pch-related
> regressions here, between r191490 and r191501:

r191502 is the jump function expression unsharing and location pruning
patch of mine so if that revision fixes it, it's probably the same
problem.  (I'm still a bit surprised though, I thought the issue was
an LTO one.  But perhaps not.)

Martin

> 
>     http://gcc.gnu.org/ml/gcc-testresults/2012-09/msg01906.html
>     http://gcc.gnu.org/ml/gcc-testresults/2012-09/msg01924.html
> 
> Paolo.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20 14:13                                                                       ` Martin Jambor
@ 2012-09-20 14:45                                                                         ` Paolo Carlini
  2012-09-20 14:47                                                                         ` Jan Hubicka
  1 sibling, 0 replies; 93+ messages in thread
From: Paolo Carlini @ 2012-09-20 14:45 UTC (permalink / raw)
  To: Dehao Chen, Michael Matz, GCC Patches, Richard Guenther,
	Jan Hubicka, David Li

On 09/20/2012 04:05 PM, Martin Jambor wrote:
> On Thu, Sep 20, 2012 at 03:26:29PM +0200, Paolo Carlini wrote:
>> On 09/20/2012 03:04 PM, Paolo Carlini wrote:
>>> are all ICEs like the below. Apparently PCHs are required, I can't
>>> reproduce outside the testsuite, without the library PCHs.
>> Take this only as a vague hint: I'm seeing many pch-related
>> regressions here, between r191490 and r191501:
> r191502 is the jump function expression unsharing and location pruning
> patch of mine so if that revision fixes it, it's probably the same
> problem.  (I'm still a bit surprised though, I thought the issue was
> an LTO one.  But perhaps not.)
Note that the regressions are still there post r191502 (and that is 
consistent with what I'm seeing on my own machine):

     http://gcc.gnu.org/ml/gcc-testresults/2012-09/msg01954.html
     http://gcc.gnu.org/ml/gcc-testresults/2012-09/msg01962.html
     http://gcc.gnu.org/ml/gcc-testresults/2012-09/msg01970.html
     http://gcc.gnu.org/ml/gcc-testresults/2012-09/msg01976.html

Paolo.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20 14:13                                                                       ` Martin Jambor
  2012-09-20 14:45                                                                         ` Paolo Carlini
@ 2012-09-20 14:47                                                                         ` Jan Hubicka
  1 sibling, 0 replies; 93+ messages in thread
From: Jan Hubicka @ 2012-09-20 14:47 UTC (permalink / raw)
  To: Paolo Carlini, Dehao Chen, Michael Matz, GCC Patches,
	Richard Guenther, Jan Hubicka, David Li

> On Thu, Sep 20, 2012 at 03:26:29PM +0200, Paolo Carlini wrote:
> > On 09/20/2012 03:04 PM, Paolo Carlini wrote:
> > >are all ICEs like the below. Apparently PCHs are required, I can't
> > >reproduce outside the testsuite, without the library PCHs.
> > Take this only as a vague hint: I'm seeing many pch-related
> > regressions here, between r191490 and r191501:
> 
> r191502 is the jump function expression unsharing and location pruning
> patch of mine so if that revision fixes it, it's probably the same
> problem.  (I'm still a bit surprised though, I thought the issue was
> an LTO one.  But perhaps not.)

Jump functions never go to PCH and you did not change any GTY annotations, so I
would bet it is unrelated to that changes.

Honza

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20 13:20                                                                   ` Paolo Carlini
  2012-09-20 14:05                                                                     ` Paolo Carlini
@ 2012-09-20 15:45                                                                     ` Dehao Chen
  2012-09-20 21:51                                                                       ` Dehao Chen
  1 sibling, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-09-20 15:45 UTC (permalink / raw)
  To: Paolo Carlini
  Cc: Michael Matz, Martin Jambor, GCC Patches, Richard Guenther,
	Jan Hubicka, David Li

Hi, Paolo,

I'll look into the ICE problems now.

Thanks,
Dehao

On Thu, Sep 20, 2012 at 9:04 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Hi,
>
>
> On 09/19/2012 09:59 PM, Dehao Chen wrote:
>>
>> This patch was commited as r191494.
>
> I'm afraid I can't help *much* with the debugging, but on my x86_64-linux
> machine and a very straightforward configuration (--enable-languages=c++
> --disable-multilib) after r191494 I'm seeing the following libstdc++
> regressions.
>
> FAIL: 17_intro/headers/c++1998/all.cc (test for excess errors)
> FAIL: 17_intro/headers/c++1998/all_c++200x_compatibility.cc (test for excess
> errors)
> FAIL: 17_intro/headers/c++1998/all_pedantic_errors.cc (test for excess
> errors)
> FAIL: 17_intro/headers/c++1998/stdc++.cc (test for excess errors)
> FAIL: 17_intro/headers/c++1998/stdc++_multiple_inclusion.cc (test for excess
> errors)
> FAIL: 17_intro/headers/c++200x/stdc++.cc (test for excess errors)
> FAIL: 17_intro/headers/c++200x/stdc++_multiple_inclusion.cc (test for excess
> errors)
>
> are all ICEs like the below. Apparently PCHs are required, I can't reproduce
> outside the testsuite, without the library PCHs.
>
> Does it make any sense to you? Please let me know if I can somehow help.
>
> Thanks,
> Paolo.
>
> ///////////////////
>
> In file included from
> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/basic_ios.h:39:0,
>                  from
> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/ios:45,
>                  from
> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/istream:40,
>                  from
> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/sstream:39,
>                  from
> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/complex:47,
>                  from
> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/x86_64-unknown-linux-gnu/bits/stdc++.h:67,
>                  from
> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/x86_64-unknown-linux-gnu/bits/stdtr1c++.h:29,
>                  from
> /scratch/Gcc/svn-dirs/trunk/libstdc++-v3/include/precompiled/extc++.h:30:
> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/locale_facets.h:
> In member function 'virtual std::ctype<char>::char_type
> std::ctype<char>::do_widen(char) const':
> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/locale_facets.h:1077:7:
> internal compiler error: Segmentation fault
>        do_widen(char __c) const
>        ^
> Please submit a full bug report,
> with preprocessed source if appropriate.
> See <http://gcc.gnu.org/bugs.html> for instructions.
>
>

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20 15:45                                                                     ` Dehao Chen
@ 2012-09-20 21:51                                                                       ` Dehao Chen
  2012-09-20 22:04                                                                         ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-09-20 21:51 UTC (permalink / raw)
  To: Paolo Carlini
  Cc: Michael Matz, Martin Jambor, GCC Patches, Richard Guenther,
	Jan Hubicka, David Li

Sorry for breaking these tests.

This problem is very hard to reproduce. However, I had a patch to fix
another compile-time problem which may be related to this one.
http://gcc.gnu.org/ml/gcc-patches/2012-09/msg01491.html

After applying the patch, the PCH related bugs are not showing any
more on my machines.

Dehao

On Thu, Sep 20, 2012 at 10:59 PM, Dehao Chen <dehao@google.com> wrote:
> Hi, Paolo,
>
> I'll look into the ICE problems now.
>
> Thanks,
> Dehao
>
> On Thu, Sep 20, 2012 at 9:04 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
>> Hi,
>>
>>
>> On 09/19/2012 09:59 PM, Dehao Chen wrote:
>>>
>>> This patch was commited as r191494.
>>
>> I'm afraid I can't help *much* with the debugging, but on my x86_64-linux
>> machine and a very straightforward configuration (--enable-languages=c++
>> --disable-multilib) after r191494 I'm seeing the following libstdc++
>> regressions.
>>
>> FAIL: 17_intro/headers/c++1998/all.cc (test for excess errors)
>> FAIL: 17_intro/headers/c++1998/all_c++200x_compatibility.cc (test for excess
>> errors)
>> FAIL: 17_intro/headers/c++1998/all_pedantic_errors.cc (test for excess
>> errors)
>> FAIL: 17_intro/headers/c++1998/stdc++.cc (test for excess errors)
>> FAIL: 17_intro/headers/c++1998/stdc++_multiple_inclusion.cc (test for excess
>> errors)
>> FAIL: 17_intro/headers/c++200x/stdc++.cc (test for excess errors)
>> FAIL: 17_intro/headers/c++200x/stdc++_multiple_inclusion.cc (test for excess
>> errors)
>>
>> are all ICEs like the below. Apparently PCHs are required, I can't reproduce
>> outside the testsuite, without the library PCHs.
>>
>> Does it make any sense to you? Please let me know if I can somehow help.
>>
>> Thanks,
>> Paolo.
>>
>> ///////////////////
>>
>> In file included from
>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/basic_ios.h:39:0,
>>                  from
>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/ios:45,
>>                  from
>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/istream:40,
>>                  from
>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/sstream:39,
>>                  from
>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/complex:47,
>>                  from
>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/x86_64-unknown-linux-gnu/bits/stdc++.h:67,
>>                  from
>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/x86_64-unknown-linux-gnu/bits/stdtr1c++.h:29,
>>                  from
>> /scratch/Gcc/svn-dirs/trunk/libstdc++-v3/include/precompiled/extc++.h:30:
>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/locale_facets.h:
>> In member function 'virtual std::ctype<char>::char_type
>> std::ctype<char>::do_widen(char) const':
>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/locale_facets.h:1077:7:
>> internal compiler error: Segmentation fault
>>        do_widen(char __c) const
>>        ^
>> Please submit a full bug report,
>> with preprocessed source if appropriate.
>> See <http://gcc.gnu.org/bugs.html> for instructions.
>>
>>

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20 21:51                                                                       ` Dehao Chen
@ 2012-09-20 22:04                                                                         ` Dehao Chen
  2012-09-21  3:58                                                                           ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-09-20 22:04 UTC (permalink / raw)
  To: Paolo Carlini
  Cc: Michael Matz, Martin Jambor, GCC Patches, Richard Guenther,
	Jan Hubicka, David Li

The PCH related failures are caused by this patch. The patch I posted
earlier http://gcc.gnu.org/ml/gcc-patches/2012-09/msg01491.html solved
another problem, but not this one.

The issue here is: when reading PCH data, the line_table is also read
from PCH files. But the location_adhoc_data_map is not managed by GC,
thus is not read in from PCH file (only a pointer is read in).

To solve this problem, we'll need to move location_adhoc_data_map into
GC. I'll have another patch to solve this problem.

However, I still do not quite understand how muliple line_tables can
co-exist. E.g. foo() is from a.H, bar() is from b.H. When bar() is
inlined into foo(), both line_tables (a.H and b.H) should be used. But
I didn't find in GCC how this is handled...

Dehao

On Fri, Sep 21, 2012 at 4:17 AM, Dehao Chen <dehao@google.com> wrote:
> Sorry for breaking these tests.
>
> This problem is very hard to reproduce. However, I had a patch to fix
> another compile-time problem which may be related to this one.
> http://gcc.gnu.org/ml/gcc-patches/2012-09/msg01491.html
>
> After applying the patch, the PCH related bugs are not showing any
> more on my machines.
>
> Dehao
>
> On Thu, Sep 20, 2012 at 10:59 PM, Dehao Chen <dehao@google.com> wrote:
>> Hi, Paolo,
>>
>> I'll look into the ICE problems now.
>>
>> Thanks,
>> Dehao
>>
>> On Thu, Sep 20, 2012 at 9:04 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
>>> Hi,
>>>
>>>
>>> On 09/19/2012 09:59 PM, Dehao Chen wrote:
>>>>
>>>> This patch was commited as r191494.
>>>
>>> I'm afraid I can't help *much* with the debugging, but on my x86_64-linux
>>> machine and a very straightforward configuration (--enable-languages=c++
>>> --disable-multilib) after r191494 I'm seeing the following libstdc++
>>> regressions.
>>>
>>> FAIL: 17_intro/headers/c++1998/all.cc (test for excess errors)
>>> FAIL: 17_intro/headers/c++1998/all_c++200x_compatibility.cc (test for excess
>>> errors)
>>> FAIL: 17_intro/headers/c++1998/all_pedantic_errors.cc (test for excess
>>> errors)
>>> FAIL: 17_intro/headers/c++1998/stdc++.cc (test for excess errors)
>>> FAIL: 17_intro/headers/c++1998/stdc++_multiple_inclusion.cc (test for excess
>>> errors)
>>> FAIL: 17_intro/headers/c++200x/stdc++.cc (test for excess errors)
>>> FAIL: 17_intro/headers/c++200x/stdc++_multiple_inclusion.cc (test for excess
>>> errors)
>>>
>>> are all ICEs like the below. Apparently PCHs are required, I can't reproduce
>>> outside the testsuite, without the library PCHs.
>>>
>>> Does it make any sense to you? Please let me know if I can somehow help.
>>>
>>> Thanks,
>>> Paolo.
>>>
>>> ///////////////////
>>>
>>> In file included from
>>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/basic_ios.h:39:0,
>>>                  from
>>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/ios:45,
>>>                  from
>>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/istream:40,
>>>                  from
>>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/sstream:39,
>>>                  from
>>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/complex:47,
>>>                  from
>>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/x86_64-unknown-linux-gnu/bits/stdc++.h:67,
>>>                  from
>>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/x86_64-unknown-linux-gnu/bits/stdtr1c++.h:29,
>>>                  from
>>> /scratch/Gcc/svn-dirs/trunk/libstdc++-v3/include/precompiled/extc++.h:30:
>>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/locale_facets.h:
>>> In member function 'virtual std::ctype<char>::char_type
>>> std::ctype<char>::do_widen(char) const':
>>> /home/paolo/Gcc/svn-dirs/trunk-build/x86_64-unknown-linux-gnu/libstdc++-v3/include/bits/locale_facets.h:1077:7:
>>> internal compiler error: Segmentation fault
>>>        do_widen(char __c) const
>>>        ^
>>> Please submit a full bug report,
>>> with preprocessed source if appropriate.
>>> See <http://gcc.gnu.org/bugs.html> for instructions.
>>>
>>>

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20 22:04                                                                         ` Dehao Chen
@ 2012-09-21  3:58                                                                           ` Dehao Chen
  2012-09-21 13:44                                                                             ` Michael Matz
  2012-09-21 13:55                                                                             ` Markus Trippelsdorf
  0 siblings, 2 replies; 93+ messages in thread
From: Dehao Chen @ 2012-09-21  3:58 UTC (permalink / raw)
  To: Paolo Carlini
  Cc: Michael Matz, Martin Jambor, GCC Patches, Richard Guenther,
	Jan Hubicka, David Li, Ian Lance Taylor

Hi,

As expected, since this patch was checked in yesterday, there are 4
bugs exposed (1 fixed, 1 patch ready, 2 TBD):

1. http://gcc.gnu.org/ml/gcc-patches/2012-09/msg01413.html
Failed targets such as arm and mips. Fixed by r191510

2. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54649
Failed Go bootstrap (I didn't test --enable-language=go). The problem
is when we set the line number for stmts in the finally block
(tree-eh.c), we don't want to change its block info.
A fix was proposed: http://gcc.gnu.org/ml/gcc-patches/2012-09/msg01513.html

3. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54645
All PCH related tests fail intermittently. (They didn't manifest when
I was doing the test...)
The cause of the problem is: when reading PCH data, the line_table is
also read from PCH files. But the location_adhoc_data_map is not
managed by GC, thus is not read in from PCH file (only a pointer is
read in).
I'll try to provide a patch to resolve the problem by the end of Friday.

4. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54650
Failed one regression test in libgomp (I didn't know that there are
regression tests for libraries before...)
This error should be a bug exposed by this patch. I'll try to provide
a patch as soon as possible.

Thanks,
Dehao

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-21  3:58                                                                           ` Dehao Chen
@ 2012-09-21 13:44                                                                             ` Michael Matz
  2012-09-21 13:55                                                                             ` Markus Trippelsdorf
  1 sibling, 0 replies; 93+ messages in thread
From: Michael Matz @ 2012-09-21 13:44 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Paolo Carlini, Martin Jambor, GCC Patches, Richard Guenther,
	Jan Hubicka, David Li, Ian Lance Taylor

Hi,

On Thu, 20 Sep 2012, Dehao Chen wrote:

> 4. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54650 Failed one 
> regression test in libgomp (I didn't know that there are regression 
> tests for libraries before...) This error should be a bug exposed by 
> this patch. I'll try to provide a patch as soon as possible.

Always do a 'make check' from the toplevel build directory.  For looking 
at the results you may find contrib/test_summary afterwards useful.  
Compare it's output from a run with and without patch.  All new FAILs will 
have to be investigated, and with the above procedure you won't miss any.


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-21  3:58                                                                           ` Dehao Chen
  2012-09-21 13:44                                                                             ` Michael Matz
@ 2012-09-21 13:55                                                                             ` Markus Trippelsdorf
  1 sibling, 0 replies; 93+ messages in thread
From: Markus Trippelsdorf @ 2012-09-21 13:55 UTC (permalink / raw)
  To: Dehao Chen
  Cc: Paolo Carlini, Michael Matz, Martin Jambor, GCC Patches,
	Richard Guenther, Jan Hubicka, David Li, Ian Lance Taylor

On 2012.09.20 at 19:51 -0700, Dehao Chen wrote:
> As expected, since this patch was checked in yesterday, there are 4
> bugs exposed (1 fixed, 1 patch ready, 2 TBD):

It also causes: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54655

-- 
Markus

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-21  0:29     ` Dehao Chen
@ 2012-09-21 12:37       ` Dominique Dhumieres
  0 siblings, 0 replies; 93+ messages in thread
From: Dominique Dhumieres @ 2012-09-21 12:37 UTC (permalink / raw)
  To: dominiq, dehao; +Cc: gcc-patches

Hi Dehao,

You wrote:
> 4. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54650
> Failed one regression test in libgomp (I didn't know that there are
> regression tests for libraries before...)
> This error should be a bug exposed by this patch. I'll try to provide
> a patch as soon as possible.

See pr54650 for clarification: there are several libgomp.fortran failing
and not only one. When I saw them I was in rush and analyzed only one.
Sorry for the confusion.

Cherrs,

Dominique

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20 23:00   ` Dominique Dhumieres
@ 2012-09-21  0:29     ` Dehao Chen
  2012-09-21 12:37       ` Dominique Dhumieres
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-09-21  0:29 UTC (permalink / raw)
  To: Dominique Dhumieres; +Cc: GCC Patches

I can reproduce the problem now. After some investigation, this error
should be a bug exposed by this patch.

The root cause is, in expand_omp_taskreg, it calls
move_sese_region_to_fn with gimple_block(entry_stmt) as the root of
the block tree. However, there is an edge inside the region that has
the root's sibling as its goto_block. As a result, the block get
escaped when numbering the blocks.

This bug does not expose before because he goto_block was set NULL.
The block_location patch reserved the value for the goto_block, thus
exposed he problem.

I'll try to fix it in the next couple of days.

Thanks,
Dehao

On Fri, Sep 21, 2012 at 6:07 AM, Dominique Dhumieres <dominiq@lps.ens.fr> wrote:
>> This problem will be fixed by
>> http://gcc.gnu.org/ml/gcc-patches/2012-09/msg01491.html
>
> Sorry, but its not (see pr54645 c#3).
>
> Dominique

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20 22:07 ` Dehao Chen
@ 2012-09-20 23:00   ` Dominique Dhumieres
  2012-09-21  0:29     ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Dominique Dhumieres @ 2012-09-20 23:00 UTC (permalink / raw)
  To: dominiq, dehao; +Cc: gcc-patches

> This problem will be fixed by
> http://gcc.gnu.org/ml/gcc-patches/2012-09/msg01491.html

Sorry, but its not (see pr54645 c#3).

Dominique

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
  2012-09-20 10:59 Dominique Dhumieres
@ 2012-09-20 22:07 ` Dehao Chen
  2012-09-20 23:00   ` Dominique Dhumieres
  0 siblings, 1 reply; 93+ messages in thread
From: Dehao Chen @ 2012-09-20 22:07 UTC (permalink / raw)
  To: Dominique Dhumieres; +Cc: GCC Patches

On Thu, Sep 20, 2012 at 6:04 PM, Dominique Dhumieres <dominiq@lps.ens.fr> wrote:
> A lot of failures in the test suite have appeared between revisions
> 191485 and 191494 see http://gcc.gnu.org/ml/gcc-regression/2012-09/msg00327.html ).
> I have looked at the failure of libgomp.fortran/reduction1.f90:
>
> [macbook] f90/bug% gfc -O3 -g -fopenmp /opt/gcc/work/libgomp/testsuite/libgomp.fortran/reduction1.f90
> /opt/gcc/work/libgomp/testsuite/libgomp.fortran/reduction1.f90: In function 'MAIN__._omp_fn.0':
> /opt/gcc/work/libgomp/testsuite/libgomp.fortran/reduction1.f90:22:0: internal compiler error: in change_scope, at final.c:1543
>  !$omp & reduction (+:i, ia, r, ra, d, da, c, ca)
>
> The backtrace is
>
> #0  fancy_abort (file=0x100a7b376 "../../work/gcc/final.c", line=1543, function=0x100b418b3 "change_scope") at ../../work/gcc/diagnostic.c:1010
> #1  0x000000010045f9f9 in change_scope (orig_insn=<value optimized out>, s1=<value optimized out>, s2=<value optimized out>)
>     at ../../work/gcc/final.c:1543
> #2  0x0000000100463c40 in final_start_function (first=<value optimized out>, file=<value optimized out>, optimize_p=<value optimized out>)
>     at ../../work/gcc/final.c:1613
> #3  0x0000000100465761 in rest_of_handle_final () at ../../work/gcc/final.c:4291
> #4  0x00000001006486ea in execute_one_pass (pass=<value optimized out>) at ../../work/gcc/passes.c:2206
> #5  0x0000000100648afd in execute_pass_list (pass=<value optimized out>) at ../../work/gcc/passes.c:2261
> #6  0x0000000100648b0f in execute_pass_list (pass=<value optimized out>) at ../../work/gcc/passes.c:2262
> #7  0x0000000100648b0f in execute_pass_list (pass=<value optimized out>) at ../../work/gcc/passes.c:2262
> #8  0x0000000100365f4b in expand_function (node=<value optimized out>) at ../../work/gcc/cgraphunit.c:1609
> #9  0x00000001003680ba in compile () at ../../work/gcc/cgraphunit.c:1714
> #10 0x000000010036870f in finalize_compilation_unit () at ../../work/gcc/cgraphunit.c:2089
> #11 0x00000001005e0f27 in write_global_declarations () at ../../work/gcc/langhooks.c:323
> #12 0x00000001007047f1 in compile_file () at ../../work/gcc/toplev.c:560
> #13 0x000000010070663c in toplev_main (argc=<value optimized out>, argv=<value optimized out>) at ../../work/gcc/toplev.c:1863
> #14 0x0000000100000e14 in start ()
>
> Could you have a look to this problem?

This problem will be fixed by
http://gcc.gnu.org/ml/gcc-patches/2012-09/msg01491.html

Sorry for the inconvenience.
Dehao

>
> TIA
>
> Dominique

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH] Combine location with block using block_locations
@ 2012-09-20 10:59 Dominique Dhumieres
  2012-09-20 22:07 ` Dehao Chen
  0 siblings, 1 reply; 93+ messages in thread
From: Dominique Dhumieres @ 2012-09-20 10:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: dehao

A lot of failures in the test suite have appeared between revisions
191485 and 191494 see http://gcc.gnu.org/ml/gcc-regression/2012-09/msg00327.html ).
I have looked at the failure of libgomp.fortran/reduction1.f90:

[macbook] f90/bug% gfc -O3 -g -fopenmp /opt/gcc/work/libgomp/testsuite/libgomp.fortran/reduction1.f90
/opt/gcc/work/libgomp/testsuite/libgomp.fortran/reduction1.f90: In function 'MAIN__._omp_fn.0':
/opt/gcc/work/libgomp/testsuite/libgomp.fortran/reduction1.f90:22:0: internal compiler error: in change_scope, at final.c:1543
 !$omp & reduction (+:i, ia, r, ra, d, da, c, ca)

The backtrace is

#0  fancy_abort (file=0x100a7b376 "../../work/gcc/final.c", line=1543, function=0x100b418b3 "change_scope") at ../../work/gcc/diagnostic.c:1010
#1  0x000000010045f9f9 in change_scope (orig_insn=<value optimized out>, s1=<value optimized out>, s2=<value optimized out>)
    at ../../work/gcc/final.c:1543
#2  0x0000000100463c40 in final_start_function (first=<value optimized out>, file=<value optimized out>, optimize_p=<value optimized out>)
    at ../../work/gcc/final.c:1613
#3  0x0000000100465761 in rest_of_handle_final () at ../../work/gcc/final.c:4291
#4  0x00000001006486ea in execute_one_pass (pass=<value optimized out>) at ../../work/gcc/passes.c:2206
#5  0x0000000100648afd in execute_pass_list (pass=<value optimized out>) at ../../work/gcc/passes.c:2261
#6  0x0000000100648b0f in execute_pass_list (pass=<value optimized out>) at ../../work/gcc/passes.c:2262
#7  0x0000000100648b0f in execute_pass_list (pass=<value optimized out>) at ../../work/gcc/passes.c:2262
#8  0x0000000100365f4b in expand_function (node=<value optimized out>) at ../../work/gcc/cgraphunit.c:1609
#9  0x00000001003680ba in compile () at ../../work/gcc/cgraphunit.c:1714
#10 0x000000010036870f in finalize_compilation_unit () at ../../work/gcc/cgraphunit.c:2089
#11 0x00000001005e0f27 in write_global_declarations () at ../../work/gcc/langhooks.c:323
#12 0x00000001007047f1 in compile_file () at ../../work/gcc/toplev.c:560
#13 0x000000010070663c in toplev_main (argc=<value optimized out>, argv=<value optimized out>) at ../../work/gcc/toplev.c:1863
#14 0x0000000100000e14 in start ()

Could you have a look to this problem?

TIA

Dominique

^ permalink raw reply	[flat|nested] 93+ messages in thread

end of thread, other threads:[~2012-09-21 13:44 UTC | newest]

Thread overview: 93+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-01  5:36 [PATCH] Combine location with block using block_locations Dehao Chen
2012-08-01 18:07 ` Richard Guenther
2012-08-02  3:23   ` Dehao Chen
2012-08-02 10:06     ` Richard Guenther
2012-08-06 18:36       ` Dehao Chen
2012-08-07 15:16         ` Richard Guenther
2012-08-07 15:52           ` Dehao Chen
2012-08-13 18:35             ` Dodji Seketeli
2012-08-14  4:58               ` Dehao Chen
2012-08-14  7:56                 ` Dodji Seketeli
2012-08-14 17:13                   ` Dehao Chen
2012-08-20  1:19                     ` Dehao Chen
2012-08-21 13:25                       ` Richard Guenther
2012-08-21 23:54                         ` Dehao Chen
2012-09-04 20:47                           ` Dehao Chen
2012-09-06  9:46                           ` Richard Guenther
2012-09-07 11:08                             ` Diego Novillo
2012-09-07 14:56                               ` Dehao Chen
2012-09-07 17:29                                 ` Diego Novillo
2012-09-08 22:26                                   ` Dehao Chen
2012-09-10 10:01                                     ` Richard Guenther
2012-09-10 15:28                                       ` Dehao Chen
2012-09-10 16:42                                         ` Jan Hubicka
2012-09-10 17:32                                           ` Dehao Chen
2012-09-13  7:10                                           ` Dehao Chen
2012-09-11  8:51                                         ` Richard Guenther
2012-09-11 13:30                                           ` Michael Matz
2012-09-11 14:09                                             ` Richard Guenther
     [not found]                                               ` <CAO2gOZV8SP-sOVEJBEsvF+M3yiKwtw7yWarfhZ1xeCVYjE_7KA@mail.gmail.com>
2012-09-11 15:33                                                 ` Michael Matz
2012-09-11 16:00                                                   ` Dehao Chen
2012-09-12  5:06                                                     ` Dehao Chen
2012-09-12  5:18                                                       ` Xinliang David Li
2012-09-12  9:14                                                       ` Richard Guenther
2012-09-12 16:39                                                         ` Xinliang David Li
2012-09-12 17:05                                                           ` Dehao Chen
2012-09-12 17:19                                                             ` Xinliang David Li
2012-09-12 20:44                                                               ` Dehao Chen
2012-09-12 20:59                                                                 ` Xinliang David Li
2012-09-13 12:04                                                                 ` Richard Guenther
2012-09-12 17:20                                                             ` Dehao Chen
2012-09-13  7:07                                                               ` Dehao Chen
2012-09-13 12:00                                                               ` Richard Guenther
2012-09-13 13:33                                                                 ` Robert Dewar
2012-09-13 13:44                                                                   ` Jakub Jelinek
2012-09-13 13:52                                                                     ` Robert Dewar
2012-09-13 17:37                                                                       ` Mike Stump
2012-09-14  6:49                                                                         ` Richard Guenther
2012-09-14  8:59                                                                           ` Eric Botcazou
2012-09-14 10:30                                                                             ` Diego Novillo
2012-09-13 16:07                                                                   ` Xinliang David Li
2012-09-13 16:29                                                                     ` Robert Dewar
2012-09-13 16:46                                                                   ` Tom Tromey
2012-09-13 16:51                                                                     ` Robert Dewar
2012-09-13 17:45                                                                       ` Mike Stump
2012-09-13 19:28                                                                 ` Dehao Chen
2012-09-13 12:03                                                           ` Richard Guenther
2012-09-13 16:12                                                             ` Dehao Chen
2012-09-12  9:08                                                   ` Richard Guenther
2012-09-12 12:14                                                     ` Michael Matz
2012-09-12 13:23                                                       ` Richard Guenther
2012-09-12 13:24                                                         ` Michael Matz
2012-09-12 14:18                                                           ` Michael Matz
2012-09-12 14:37                                                             ` Martin Jambor
2012-09-12 14:47                                                               ` Richard Guenther
2012-09-12 15:11                                                                 ` Martin Jambor
2012-09-13 10:05                                                               ` Jan Hubicka
2012-09-19  9:40                                                             ` Martin Jambor
2012-09-19 14:00                                                               ` Michael Matz
2012-09-19 20:15                                                                 ` Dehao Chen
2012-09-20 13:20                                                                   ` Paolo Carlini
2012-09-20 14:05                                                                     ` Paolo Carlini
2012-09-20 14:13                                                                       ` Martin Jambor
2012-09-20 14:45                                                                         ` Paolo Carlini
2012-09-20 14:47                                                                         ` Jan Hubicka
2012-09-20 15:45                                                                     ` Dehao Chen
2012-09-20 21:51                                                                       ` Dehao Chen
2012-09-20 22:04                                                                         ` Dehao Chen
2012-09-21  3:58                                                                           ` Dehao Chen
2012-09-21 13:44                                                                             ` Michael Matz
2012-09-21 13:55                                                                             ` Markus Trippelsdorf
2012-09-13 16:49                                 ` Tom Tromey
2012-09-14  2:47                                   ` Dehao Chen
2012-09-14  3:04                                     ` Dehao Chen
2012-09-19  8:48                                       ` Jan Hubicka
2012-09-19  9:22                                         ` Richard Guenther
2012-09-19 22:58                                       ` Michael Meissner
2012-09-20  0:51                                         ` Dehao Chen
2012-09-20  1:04                                           ` Dehao Chen
2012-09-20 10:59 Dominique Dhumieres
2012-09-20 22:07 ` Dehao Chen
2012-09-20 23:00   ` Dominique Dhumieres
2012-09-21  0:29     ` Dehao Chen
2012-09-21 12:37       ` Dominique Dhumieres

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).