diff mbox

[GOOGLE] Back port discriminator patches to gcc-4_8

Message ID CAO2gOZXZUoy0sO2XTVdUz=PPJdPAMewX_q6kLz7DqQVYz024rw@mail.gmail.com
State New
Headers show

Commit Message

Dehao Chen May 15, 2013, 2:46 a.m. UTC
This patch ports r173196 from google-main and r190269 from google-4_7
to add discriminator support in google-4_8 branch.

Bootstrapped. It will fail gcc.dg/uninit-6-O0.c, which also fails in
google-4_7 branch.

OK to backport to google-4_8 branch?

Thanks,
Dehao

Comments

Diego Novillo May 15, 2013, 11:20 a.m. UTC | #1
On 2013-05-14 22:46 , Dehao Chen wrote:
> This patch ports r173196 from google-main and r190269 from google-4_7
> to add discriminator support in google-4_8 branch.
>
> Bootstrapped. It will fail gcc.dg/uninit-6-O0.c, which also fails in
> google-4_7 branch.
>
> OK to backport to google-4_8 branch?

If there is a new failure that you can explain, then you need to add the 
failing test to the manifest and make sure there are no regressions.  
Otherwise, you're going to anger the auto builders :)


Diego.
Cary Coutant May 15, 2013, 4:58 p.m. UTC | #2
> Bootstrapped. It will fail gcc.dg/uninit-6-O0.c, which also fails in
> google-4_7 branch.

It'd be nice to fix this -- what's the nature of the failure?

-cary
Dehao Chen May 15, 2013, 5:12 p.m. UTC | #3
The warning was attributed to the wrong lineno. Looks like
discriminator does not work well when it coexists with macros.

Dehao

On Wed, May 15, 2013 at 9:58 AM, Cary Coutant <ccoutant@google.com> wrote:
>> Bootstrapped. It will fail gcc.dg/uninit-6-O0.c, which also fails in
>> google-4_7 branch.
>
> It'd be nice to fix this -- what's the nature of the failure?
>
> -cary
Cary Coutant May 15, 2013, 10:44 p.m. UTC | #4
> The warning was attributed to the wrong lineno. Looks like
> discriminator does not work well when it coexists with macros.

I think warn_uninit in tree-ssa.c needs one of these:

  location = map_discriminator_location (location);

There may still be other places where calls to
linemap_resolve_location have been added since this patch was
originally developed.

-cary
Dehao Chen May 15, 2013, 10:48 p.m. UTC | #5
On Wed, May 15, 2013 at 3:44 PM, Cary Coutant <ccoutant@google.com> wrote:
>> The warning was attributed to the wrong lineno. Looks like
>> discriminator does not work well when it coexists with macros.
>
> I think warn_uninit in tree-ssa.c needs one of these:
>
>   location = map_discriminator_location (location);
>
> There may still be other places where calls to
> linemap_resolve_location have been added since this patch was
> originally developed.

Yeah, I've added location = map_discriminator_location (location); to
all possible places in the patch.

Dehao
>
> -cary
Cary Coutant May 15, 2013, 11:03 p.m. UTC | #6
>> I think warn_uninit in tree-ssa.c needs one of these:
>>
>>   location = map_discriminator_location (location);
>>
>> There may still be other places where calls to
>> linemap_resolve_location have been added since this patch was
>> originally developed.
>
> Yeah, I've added location = map_discriminator_location (location); to
> all possible places in the patch.

Oops, sorry, I took a quick look through the patch to see if
warn_uninit was covered, and missed it.

-cary
Cary Coutant May 17, 2013, 11:35 p.m. UTC | #7
> The warning was attributed to the wrong lineno. Looks like
> discriminator does not work well when it coexists with macros.

I think the problem is with same_line_p. It's using expand_location to
test whether two locations refer to the same line, but expand_location
always unwinds the macro stack so that it's looking at the line number
of the macro expansion point. That means that every token in the macro
expansion will appear to be at the same line, so the loop over the
basic_block will replace all of the locations with the new_locus that
we just allocated for the new discriminator. Thus, it's clobbering the
locus for the instructions at line 27 in the macro definition with the
new locus we create to put a discriminator at line 26, and the warning
that should appear for line 27 now says line 26.

Other comments on the patch...

In expand_location_1:

+  if (min_discriminator_location != UNKNOWN_LOCATION
+      && loc >= min_discriminator_location
+      && loc < min_discriminator_location + next_discriminator_location)

The last comparison should just be "loc < next_discriminator_location".

Likewise in has_discriminator.

In assign_discriminator:

+      location_t new_locus = location_with_discriminator (locus,
discriminator);
+      gimple_stmt_iterator gsi;
+
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+        {
+          gimple stmt = gsi_stmt (gsi);
+          if (same_line_p (locus, gimple_location (stmt)))
+            gimple_set_location (stmt, block ?
+                  COMBINE_LOCATION_DATA (line_table, new_locus, block) :
+                  LOCATION_LOCUS (new_locus));
+        }

I'm not convinced the COMBINE_LOCATION_DATA is needed here, since
location_with_discriminator has already done that. And when block ==
NULL, calling LOCATION_LOCUS is effectively a no-op, isn't it? It
seems this could simply be:

          gimple_set_location (stmt, new_locus);

Also, you need to add vec.o to OBJS-libcommon in Makefile.in, since
input.o now depends on it. Other binaries, like gcov, won't build
otherwise.

I'm still not happy with a straightforward port of the old patch,
though, since discriminator assignment might allocate locations that
overlap those used for macro definitions -- there's no checking to see
if we've run out of locations in that case. I guess this could be OK
for the google branch for now, but not for trunk. I'm looking at
alternatives using the adhoc mapping -- do you think it would work if
we extend the adhoc mapping to track both a "data" (i.e., the block
pointer) and a discriminator?

-cary
Dehao Chen May 18, 2013, 1 a.m. UTC | #8
On Fri, May 17, 2013 at 4:35 PM, Cary Coutant <ccoutant@google.com> wrote:
>> The warning was attributed to the wrong lineno. Looks like
>> discriminator does not work well when it coexists with macros.
>
> I think the problem is with same_line_p. It's using expand_location to
> test whether two locations refer to the same line, but expand_location
> always unwinds the macro stack so that it's looking at the line number
> of the macro expansion point. That means that every token in the macro
> expansion will appear to be at the same line, so the loop over the
> basic_block will replace all of the locations with the new_locus that
> we just allocated for the new discriminator. Thus, it's clobbering the
> locus for the instructions at line 27 in the macro definition with the
> new locus we create to put a discriminator at line 26, and the warning
> that should appear for line 27 now says line 26.

Sounds like instead of checking the macro-expansion location,
same_line_p should check the expanded macro location instead, so the
problem will be resolved?

>
> Other comments on the patch...
>
> In expand_location_1:
>
> +  if (min_discriminator_location != UNKNOWN_LOCATION
> +      && loc >= min_discriminator_location
> +      && loc < min_discriminator_location + next_discriminator_location)
>
> The last comparison should just be "loc < next_discriminator_location".
>
> Likewise in has_discriminator.

Acked, will update the patch.

>
> In assign_discriminator:
>
> +      location_t new_locus = location_with_discriminator (locus,
> discriminator);
> +      gimple_stmt_iterator gsi;
> +
> +      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> +        {
> +          gimple stmt = gsi_stmt (gsi);
> +          if (same_line_p (locus, gimple_location (stmt)))
> +            gimple_set_location (stmt, block ?
> +                  COMBINE_LOCATION_DATA (line_table, new_locus, block) :
> +                  LOCATION_LOCUS (new_locus));
> +        }
>
> I'm not convinced the COMBINE_LOCATION_DATA is needed here, since
> location_with_discriminator has already done that. And when block ==
> NULL, calling LOCATION_LOCUS is effectively a no-op, isn't it? It
> seems this could simply be:
>
>           gimple_set_location (stmt, new_locus);

But what if block != NULL?

>
> Also, you need to add vec.o to OBJS-libcommon in Makefile.in, since
> input.o now depends on it. Other binaries, like gcov, won't build
> otherwise.

Acked, will update the patch
>
> I'm still not happy with a straightforward port of the old patch,
> though, since discriminator assignment might allocate locations that
> overlap those used for macro definitions -- there's no checking to see
> if we've run out of locations in that case. I guess this could be OK
> for the google branch for now, but not for trunk. I'm looking at
> alternatives using the adhoc mapping -- do you think it would work if
> we extend the adhoc mapping to track both a "data" (i.e., the block
> pointer) and a discriminator?

Yeah, I think that works. The only concern is that it would increase
the memory because each locus_adhoc map entry need to have another bit
to store the extra info?

Thanks,
Dehao

>
> -cary
Cary Coutant May 20, 2013, 4:37 p.m. UTC | #9
>> I think the problem is with same_line_p. It's using expand_location to
>> test whether two locations refer to the same line, but expand_location
>> always unwinds the macro stack so that it's looking at the line number
>> of the macro expansion point. That means that every token in the macro
>> expansion will appear to be at the same line, so the loop over the
>> basic_block will replace all of the locations with the new_locus that
>> we just allocated for the new discriminator. Thus, it's clobbering the
>> locus for the instructions at line 27 in the macro definition with the
>> new locus we create to put a discriminator at line 26, and the warning
>> that should appear for line 27 now says line 26.
>
> Sounds like instead of checking the macro-expansion location,
> same_line_p should check the expanded macro location instead, so the
> problem will be resolved?

Yes, I changed same_line_p to call expand_location_to_spelling_point
instead, and the test runs as expected (one expected pass, one
expected failure).

>> In assign_discriminator:
>>
>> +      location_t new_locus = location_with_discriminator (locus,
>> discriminator);
>> +      gimple_stmt_iterator gsi;
>> +
>> +      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>> +        {
>> +          gimple stmt = gsi_stmt (gsi);
>> +          if (same_line_p (locus, gimple_location (stmt)))
>> +            gimple_set_location (stmt, block ?
>> +                  COMBINE_LOCATION_DATA (line_table, new_locus, block) :
>> +                  LOCATION_LOCUS (new_locus));
>> +        }
>>
>> I'm not convinced the COMBINE_LOCATION_DATA is needed here, since
>> location_with_discriminator has already done that. And when block ==
>> NULL, calling LOCATION_LOCUS is effectively a no-op, isn't it? It
>> seems this could simply be:
>>
>>           gimple_set_location (stmt, new_locus);
>
> But what if block != NULL?

If block != NULL, new_locus will already be the ad hoc location
created for that block, because location_with_discriminator does the
COMBINE_LOCATION_DATA.

>> I'm still not happy with a straightforward port of the old patch,
>> though, since discriminator assignment might allocate locations that
>> overlap those used for macro definitions -- there's no checking to see
>> if we've run out of locations in that case. I guess this could be OK
>> for the google branch for now, but not for trunk. I'm looking at
>> alternatives using the adhoc mapping -- do you think it would work if
>> we extend the adhoc mapping to track both a "data" (i.e., the block
>> pointer) and a discriminator?
>
> Yeah, I think that works. The only concern is that it would increase
> the memory because each locus_adhoc map entry need to have another bit
> to store the extra info?

Yes, that's true. I'll give it a try and measure it. Do you have a
rough feel for how many ad hoc locations get created, relative to
spelling locations?

-cary
Dehao Chen May 20, 2013, 5:43 p.m. UTC | #10
On Mon, May 20, 2013 at 9:37 AM, Cary Coutant <ccoutant@google.com> wrote:
>>> I think the problem is with same_line_p. It's using expand_location to
>>> test whether two locations refer to the same line, but expand_location
>>> always unwinds the macro stack so that it's looking at the line number
>>> of the macro expansion point. That means that every token in the macro
>>> expansion will appear to be at the same line, so the loop over the
>>> basic_block will replace all of the locations with the new_locus that
>>> we just allocated for the new discriminator. Thus, it's clobbering the
>>> locus for the instructions at line 27 in the macro definition with the
>>> new locus we create to put a discriminator at line 26, and the warning
>>> that should appear for line 27 now says line 26.
>>
>> Sounds like instead of checking the macro-expansion location,
>> same_line_p should check the expanded macro location instead, so the
>> problem will be resolved?
>
> Yes, I changed same_line_p to call expand_location_to_spelling_point
> instead, and the test runs as expected (one expected pass, one
> expected failure).

Cool. So shall we get this patch in gcc-4_8 first, and after you
change to encode discriminator in adhoc_locus map in trunk, we then
backport it to 4_8 again?

>
>>> In assign_discriminator:
>>>
>>> +      location_t new_locus = location_with_discriminator (locus,
>>> discriminator);
>>> +      gimple_stmt_iterator gsi;
>>> +
>>> +      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>>> +        {
>>> +          gimple stmt = gsi_stmt (gsi);
>>> +          if (same_line_p (locus, gimple_location (stmt)))
>>> +            gimple_set_location (stmt, block ?
>>> +                  COMBINE_LOCATION_DATA (line_table, new_locus, block) :
>>> +                  LOCATION_LOCUS (new_locus));
>>> +        }
>>>
>>> I'm not convinced the COMBINE_LOCATION_DATA is needed here, since
>>> location_with_discriminator has already done that. And when block ==
>>> NULL, calling LOCATION_LOCUS is effectively a no-op, isn't it? It
>>> seems this could simply be:
>>>
>>>           gimple_set_location (stmt, new_locus);
>>
>> But what if block != NULL?
>
> If block != NULL, new_locus will already be the ad hoc location
> created for that block, because location_with_discriminator does the
> COMBINE_LOCATION_DATA.

Sounds good. I'll updated the patch.
>
>>> I'm still not happy with a straightforward port of the old patch,
>>> though, since discriminator assignment might allocate locations that
>>> overlap those used for macro definitions -- there's no checking to see
>>> if we've run out of locations in that case. I guess this could be OK
>>> for the google branch for now, but not for trunk. I'm looking at
>>> alternatives using the adhoc mapping -- do you think it would work if
>>> we extend the adhoc mapping to track both a "data" (i.e., the block
>>> pointer) and a discriminator?
>>
>> Yeah, I think that works. The only concern is that it would increase
>> the memory because each locus_adhoc map entry need to have another bit
>> to store the extra info?
>
> Yes, that's true. I'll give it a try and measure it. Do you have a
> rough feel for how many ad hoc locations get created, relative to
> spelling locations?

I don't remember exactly. It might be large for C++ apps in which
templates/abstraction are heavily used.

Dehao

>
> -cary
Cary Coutant May 20, 2013, 5:48 p.m. UTC | #11
> Cool. So shall we get this patch in gcc-4_8 first, and after you
> change to encode discriminator in adhoc_locus map in trunk, we then
> backport it to 4_8 again?

Sure, sounds good.

-cary
Dehao Chen May 20, 2013, 10:39 p.m. UTC | #12
I've updated the patch. Bootstrapped and passed all regression test.

OK for google-4_8?

Thanks,
Dehao

On Mon, May 20, 2013 at 10:48 AM, Cary Coutant <ccoutant@google.com> wrote:
>> Cool. So shall we get this patch in gcc-4_8 first, and after you
>> change to encode discriminator in adhoc_locus map in trunk, we then
>> backport it to 4_8 again?
>
> Sure, sounds good.
>
> -cary
diff mbox

Patch

Index: gcc/gimple-pretty-print.c
===================================================================
--- gcc/gimple-pretty-print.c	(revision 198895)
+++ gcc/gimple-pretty-print.c	(working copy)
@@ -1859,7 +1859,9 @@  pp_gimple_stmt_1 (pretty_printer *buffer, gimple g
 
   if ((flags & TDF_LINENO) && gimple_has_location (gs))
     {
-      expanded_location xloc = expand_location (gimple_location (gs));
+      location_t loc = gimple_location (gs);
+      expanded_location xloc = expand_location (loc);
+      int discriminator = get_discriminator_from_locus (loc);
       pp_character (buffer, '[');
       if (xloc.file)
 	{
@@ -1869,6 +1871,11 @@  pp_gimple_stmt_1 (pretty_printer *buffer, gimple g
       pp_decimal_int (buffer, xloc.line);
       pp_string (buffer, ":");
       pp_decimal_int (buffer, xloc.column);
+      if (discriminator)
+	{
+	  pp_string (buffer, " discrim ");
+	  pp_decimal_int (buffer, discriminator);
+	}
       pp_string (buffer, "] ");
     }
 
@@ -2079,8 +2086,6 @@  dump_gimple_bb_header (FILE *outf, basic_block bb,
 			 indent, "", get_lineno (gsi_stmt (gsi)));
 		break;
 	      }
-	  if (bb->discriminator)
-	    fprintf (outf, ", discriminator %i", bb->discriminator);
 	  fputc ('\n', outf);
 	}
     }
Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c	(revision 198895)
+++ gcc/tree-cfg.c	(working copy)
@@ -26,6 +26,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 #include "basic-block.h"
 #include "flags.h"
+#include "input.h"
 #include "function.h"
 #include "ggc.h"
 #include "gimple-pretty-print.h"
@@ -746,22 +747,63 @@  same_line_p (location_t locus1, location_t locus2)
           && filename_cmp (from.file, to.file) == 0);
 }
 
-/* Assign a unique discriminator value to block BB if it begins at the same
-   LOCUS as its predecessor block.  */
+/* Assign a unique discriminator value to instructions in block BB that
+   have the same LOCUS as its predecessor block.  */
 
 static void
 assign_discriminator (location_t locus, basic_block bb)
 {
   gimple first_in_to_bb, last_in_to_bb;
+  int discriminator = 0;
+  tree block = LOCATION_BLOCK (locus);
+  locus = LOCATION_LOCUS (locus);
 
-  if (locus == 0 || bb->discriminator != 0)
+  if (locus == UNKNOWN_LOCATION)
     return;
 
+  if (has_discriminator (locus))
+    locus = map_discriminator_location (locus);
+
+  /* Check the locus of the first (non-label) instruction in the block.  */
   first_in_to_bb = first_non_label_stmt (bb);
-  last_in_to_bb = last_stmt (bb);
-  if ((first_in_to_bb && same_line_p (locus, gimple_location (first_in_to_bb)))
-      || (last_in_to_bb && same_line_p (locus, gimple_location (last_in_to_bb))))
-    bb->discriminator = next_discriminator_for_locus (locus);
+  if (first_in_to_bb)
+    {
+      location_t first_locus = gimple_location (first_in_to_bb);
+      if (! has_discriminator (first_locus)
+          && (same_line_p (locus, first_locus)))
+	discriminator = next_discriminator_for_locus (locus);
+    }
+
+  /* If the first instruction doesn't trigger a discriminator, check the
+     last instruction of the block.  This catches the case where the
+     increment portion of a for loop is placed at the end of the loop
+     body.  */
+  if (discriminator == 0)
+    {
+      last_in_to_bb = last_stmt (bb);
+      if (last_in_to_bb)
+	{
+	   location_t last_locus = gimple_location (last_in_to_bb);
+	   if (! has_discriminator (last_locus)
+	       && same_line_p (locus, last_locus))
+	     discriminator = next_discriminator_for_locus (locus);
+	}
+    }
+
+  if (discriminator != 0)
+    {
+      location_t new_locus = location_with_discriminator (locus, discriminator);
+      gimple_stmt_iterator gsi;
+
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	{
+	  gimple stmt = gsi_stmt (gsi);
+	  if (same_line_p (locus, gimple_location (stmt)))
+	    gimple_set_location (stmt, block ?
+		COMBINE_LOCATION_DATA (line_table, new_locus, block) :
+		LOCATION_LOCUS (new_locus));
+	}
+    }
 }
 
 /* Create the edges for a GIMPLE_COND starting at block BB.  */
Index: gcc/diagnostic.c
===================================================================
--- gcc/diagnostic.c	(revision 198895)
+++ gcc/diagnostic.c	(working copy)
@@ -185,6 +185,7 @@  diagnostic_set_info_translated (diagnostic_info *d
 				va_list *args, location_t location,
 				diagnostic_t kind)
 {
+  location = map_discriminator_location (location);
   diagnostic->message.err_no = errno;
   diagnostic->message.args_ptr = args;
   diagnostic->message.format_spec = msg;
@@ -477,6 +478,9 @@  diagnostic_report_current_module (diagnostic_conte
   if (where <= BUILTINS_LOCATION)
     return;
 
+  if (has_discriminator (where))
+    where = map_discriminator_location (where);
+
   linemap_resolve_location (line_table, where,
 			    LRK_MACRO_DEFINITION_LOCATION,
 			    &map);
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	(revision 198895)
+++ gcc/rtl.h	(working copy)
@@ -1916,6 +1916,7 @@  extern rtx prev_cc0_setter (rtx);
 extern int insn_line (const_rtx);
 extern const char * insn_file (const_rtx);
 extern tree insn_scope (const_rtx);
+extern int insn_discriminator (const_rtx);
 extern location_t prologue_location, epilogue_location;
 
 /* In jump.c */
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 198895)
+++ gcc/builtins.c	(working copy)
@@ -48,6 +48,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "value-prof.h"
 #include "diagnostic-core.h"
 #include "builtins.h"
+#include "input.h"
 
 
 #ifndef PAD_VARARGS_DOWN
@@ -12107,13 +12108,16 @@  fold_builtin_next_arg (tree exp, bool va_start_p)
   tree fntype = TREE_TYPE (current_function_decl);
   int nargs = call_expr_nargs (exp);
   tree arg;
+  location_t loc = LOCATION_LOCUS (input_location);
+  if (has_discriminator (loc))
+    loc = map_discriminator_location (loc);
+
   /* There is good chance the current input_location points inside the
      definition of the va_start macro (perhaps on the token for
      builtin) in a system header, so warnings will not be emitted.
      Use the location in real source code.  */
   source_location current_location =
-    linemap_unwind_to_first_non_reserved_loc (line_table, input_location,
-					      NULL);
+    linemap_unwind_to_first_non_reserved_loc (line_table, loc, NULL);
 
   if (!stdarg_p (fntype))
     {
Index: gcc/cfghooks.c
===================================================================
--- gcc/cfghooks.c	(revision 198895)
+++ gcc/cfghooks.c	(working copy)
@@ -483,7 +483,6 @@  split_block (basic_block bb, void *i)
 
   new_bb->count = bb->count;
   new_bb->frequency = bb->frequency;
-  new_bb->discriminator = bb->discriminator;
 
   if (dom_info_available_p (CDI_DOMINATORS))
     {
Index: gcc/final.c
===================================================================
--- gcc/final.c	(revision 198895)
+++ gcc/final.c	(working copy)
@@ -124,9 +124,6 @@  static int last_linenum;
 /* Last discriminator written to assembly.  */
 static int last_discriminator;
 
-/* Discriminator of current block.  */
-static int discriminator;
-
 /* Highest line number in current block.  */
 static int high_block_linenum;
 
@@ -136,9 +133,10 @@  static int high_function_linenum;
 /* Filename of last NOTE.  */
 static const char *last_filename;
 
-/* Override filename and line number.  */
+/* Override filename, line number, and discriminator.  */
 static const char *override_filename;
 static int override_linenum;
+static int override_discriminator;
 
 /* Whether to force emission of a line note before the next insn.  */
 static bool force_source_line = false;
@@ -1682,7 +1680,7 @@  final_start_function (rtx first, FILE *file,
 
   last_filename = LOCATION_FILE (prologue_location);
   last_linenum = LOCATION_LINE (prologue_location);
-  last_discriminator = discriminator = 0;
+  last_discriminator = 0;
 
   high_block_linenum = high_function_linenum = last_linenum;
 
@@ -2135,8 +2133,6 @@  final_scan_insn (rtx insn, FILE *file, int optimiz
 	  else
 	    *seen |= SEEN_BB;
 
-          discriminator = NOTE_BASIC_BLOCK (insn)->discriminator;
-
 	  break;
 
 	case NOTE_INSN_EH_REGION_BEG:
@@ -2229,6 +2225,8 @@  final_scan_insn (rtx insn, FILE *file, int optimiz
 		{
 		  override_filename = LOCATION_FILE (*locus_ptr);
 		  override_linenum = LOCATION_LINE (*locus_ptr);
+		  override_discriminator =
+		      get_discriminator_from_locus (*locus_ptr);
 		}
 	    }
 	  break;
@@ -2262,11 +2260,14 @@  final_scan_insn (rtx insn, FILE *file, int optimiz
 		{
 		  override_filename = LOCATION_FILE (*locus_ptr);
 		  override_linenum = LOCATION_LINE (*locus_ptr);
+		  override_discriminator =
+		      get_discriminator_from_locus (*locus_ptr);
 		}
 	      else
 		{
 		  override_filename = NULL;
 		  override_linenum = 0;
+		  override_discriminator = 0;
 		}
 	    }
 	  break;
@@ -2949,6 +2950,17 @@  final_scan_insn (rtx insn, FILE *file, int optimiz
     }
   return NEXT_INSN (insn);
 }
+
+/* Return discriminator of the statement that produced this insn.  */
+int
+insn_discriminator (const_rtx insn)
+{
+  location_t loc = INSN_LOCATION (insn);
+  if (!loc)
+    return 0;
+  return get_discriminator_from_locus (loc);
+}
+
 
 /* Return whether a source line note needs to be emitted before INSN.
    Sets IS_STMT to TRUE if the line should be marked as a possible
@@ -2959,16 +2971,19 @@  notice_source_line (rtx insn, bool *is_stmt)
 {
   const char *filename;
   int linenum;
+  int discriminator;
 
   if (override_filename)
     {
       filename = override_filename;
       linenum = override_linenum;
+      discriminator = override_discriminator;
     }
   else
     {
       filename = insn_file (insn);
       linenum = insn_line (insn);
+      discriminator = insn_discriminator (insn);
     }
 
   if (filename == NULL)
Index: gcc/input.c
===================================================================
--- gcc/input.c	(revision 198895)
+++ gcc/input.c	(working copy)
@@ -22,6 +22,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "intl.h"
 #include "input.h"
+#include "vec.h"
 
 /* Current position in real source file.  */
 
@@ -29,8 +30,18 @@  location_t input_location;
 
 struct line_maps *line_table;
 
+static vec<location_t> discriminator_location_locations;
+static vec<location_t> discriminator_location_discriminators;
+static location_t next_discriminator_location = UNKNOWN_LOCATION;
+static location_t min_discriminator_location = UNKNOWN_LOCATION;
+
 /* Expand the source location LOC into a human readable location.  If
    LOC resolves to a builtin location, the file name of the readable
+   location is set to the string "<built-in>".  */
+
+
+/* Expand the source location LOC into a human readable location.  If
+   LOC resolves to a builtin location, the file name of the readable
    location is set to the string "<built-in>". If EXPANSION_POINT_P is
    TRUE and LOC is virtual, then it is resolved to the expansion
    point of the involved macro.  Otherwise, it is resolved to the
@@ -58,6 +69,13 @@  expand_location_1 (source_location loc,
       loc = LOCATION_LOCUS (loc);
     }
 
+  /* If LOC describes a location with a discriminator, extract the
+     discriminator and map it to the real location.  */
+  if (min_discriminator_location != UNKNOWN_LOCATION
+      && loc >= min_discriminator_location
+      && loc < min_discriminator_location + next_discriminator_location)
+    loc = map_discriminator_location (loc);
+
   memset (&xloc, 0, sizeof (xloc));
 
   if (loc >= RESERVED_LOCATION_COUNT)
@@ -278,3 +296,69 @@  dump_line_table_statistics (void)
            STAT_LABEL (total_used_map_size));
   fprintf (stderr, "\n");
 }
+
+/* Associate the DISCRIMINATOR with LOCUS, and return a new locus.
+   We associate discriminators with a locus by allocating location_t
+   values beyond those assigned by libcpp.  Each new value is mapped
+   directly to a real location_t value, and separately to the
+   discriminator.  */
+
+location_t
+location_with_discriminator (location_t locus, int discriminator)
+{
+  tree block = LOCATION_BLOCK (locus);
+  location_t ret;
+  locus = LOCATION_LOCUS (locus);
+
+  if (locus == UNKNOWN_LOCATION)
+    return block ? COMBINE_LOCATION_DATA (line_table, locus, block)
+		 : locus;
+
+  if (min_discriminator_location == UNKNOWN_LOCATION)
+    {
+      min_discriminator_location = line_table->highest_location + 1;
+      next_discriminator_location = min_discriminator_location;
+    }
+
+  discriminator_location_locations.safe_push(locus);
+  discriminator_location_discriminators.safe_push(discriminator);
+
+  ret = block ?
+      COMBINE_LOCATION_DATA (line_table, next_discriminator_location, block)
+      : LOCATION_LOCUS (next_discriminator_location);
+  next_discriminator_location++;
+  return ret;
+}
+
+/* Return TRUE if LOCUS represents a location with a discriminator.  */
+
+bool
+has_discriminator (location_t locus)
+{
+  locus = LOCATION_LOCUS (locus);
+  return (min_discriminator_location != UNKNOWN_LOCATION
+	  && locus >= min_discriminator_location
+	  && locus < min_discriminator_location + next_discriminator_location);
+}
+
+/* Return the real location_t value for LOCUS.  */
+
+location_t
+map_discriminator_location (location_t locus)
+{
+  locus = LOCATION_LOCUS (locus);
+  if (! has_discriminator (locus))
+    return locus;
+  return (location_t) discriminator_location_locations[locus - min_discriminator_location];
+}
+
+/* Return the discriminator for LOCUS.  */
+
+int
+get_discriminator_from_locus (location_t locus)
+{
+  locus = LOCATION_LOCUS (locus);
+  if (! has_discriminator (locus))
+    return 0;
+  return (location_t) discriminator_location_discriminators[locus - min_discriminator_location];
+}
Index: gcc/input.h
===================================================================
--- gcc/input.h	(revision 198895)
+++ gcc/input.h	(working copy)
@@ -47,6 +47,11 @@  typedef source_location location_t;
 
 extern location_t input_location;
 
+extern location_t location_with_discriminator (location_t, int);
+extern bool has_discriminator (location_t);
+extern location_t map_discriminator_location (location_t);
+extern int get_discriminator_from_locus (location_t);
+
 #define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
 #define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
 #define LOCATION_COLUMN(LOC)((expand_location (LOC)).column)
@@ -59,7 +64,8 @@  extern location_t input_location;
 #define input_line LOCATION_LINE (input_location)
 #define input_filename LOCATION_FILE (input_location)
 #define in_system_header_at(LOC) \
-  ((linemap_location_in_system_header_p (line_table, LOC)))
+  ((linemap_location_in_system_header_p (line_table, \
+                                         map_discriminator_location (LOC))))
 #define in_system_header (in_system_header_at (input_location))
 
 void dump_line_table_statistics (void);
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c	(revision 198895)
+++ gcc/print-rtl.c	(working copy)
@@ -398,7 +398,13 @@  print_rtx (const_rtx in_rtx)
 		redundant with line number information and do not print anything
 		when there is no location information available.  */
 	    if (INSN_LOCATION (in_rtx) && insn_file (in_rtx))
-	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
+	      {
+		int discriminator = insn_discriminator (in_rtx);
+		fprintf (outfile, " %s:%i", insn_file (in_rtx),
+			 insn_line (in_rtx));
+		if (discriminator)
+		  fprintf (outfile, " discrim %d", discriminator);
+	      }
 #endif
 	  }
 	else if (i == 6 && GET_CODE (in_rtx) == ASM_OPERANDS)
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c	(revision 198895)
+++ gcc/tree-pretty-print.c	(working copy)
@@ -467,6 +467,7 @@  static void
 dump_location (pretty_printer *buffer, location_t loc)
 {
   expanded_location xloc = expand_location (loc);
+  int discriminator = get_discriminator_from_locus (loc);
 
   pp_character (buffer, '[');
   if (xloc.file)
@@ -475,6 +476,11 @@  dump_location (pretty_printer *buffer, location_t
       pp_string (buffer, " : ");
     }
   pp_decimal_int (buffer, xloc.line);
+  if (discriminator)
+    {
+      pp_string (buffer, " discrim ");
+      pp_decimal_int (buffer, discriminator);
+    }
   pp_string (buffer, "] ");
 }
 
Index: gcc/basic-block.h
===================================================================
--- gcc/basic-block.h	(revision 198895)
+++ gcc/basic-block.h	(working copy)
@@ -213,11 +213,6 @@  struct GTY((chain_next ("%h.next_bb"), chain_prev
 
   /* Expected frequency.  Normalized to be in range 0 to BB_FREQ_MAX.  */
   int frequency;
-
-  /* The discriminator for this block.  The discriminator distinguishes
-     among several basic blocks that share a common locus, allowing for
-     more accurate sample-based profiling.  */
-  int discriminator;
 };
 
 /* This ensures that struct gimple_bb_info is smaller than
Index: gcc/tree-diagnostic.c
===================================================================
--- gcc/tree-diagnostic.c	(revision 198895)
+++ gcc/tree-diagnostic.c	(working copy)
@@ -22,6 +22,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "input.h"
 #include "tree.h"
 #include "diagnostic.h"
 #include "tree-pretty-print.h"
@@ -107,6 +108,8 @@  maybe_unwind_expanded_macro_loc (diagnostic_contex
   unsigned ix;
   loc_map_pair loc, *iter;
 
+  if (has_discriminator (where))
+    where = map_discriminator_location (where);
   map = linemap_lookup (line_table, where);
   if (!linemap_macro_expansion_map_p (map))
     return;
Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c	(revision 198895)
+++ gcc/tree-ssa.c	(working copy)
@@ -28,6 +28,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "ggc.h"
 #include "langhooks.h"
 #include "basic-block.h"
+#include "input.h"
 #include "function.h"
 #include "gimple-pretty-print.h"
 #include "bitmap.h"
@@ -1610,6 +1611,8 @@  warn_uninit (enum opt_code wc, tree t,
   location = (context != NULL && gimple_has_location (context))
 	     ? gimple_location (context)
 	     : DECL_SOURCE_LOCATION (var);
+  if (has_discriminator (location))
+    location = map_discriminator_location (location);
   location = linemap_resolve_location (line_table, location,
 				       LRK_SPELLING_LOCATION,
 				       NULL);