discriminator support. Ported from google/gcc-4_9 branch
authorIlya Palachev <i.palachev@samsung.com>
Wed, 29 Apr 2015 14:38:43 +0000 (17:38 +0300)
committeruser <user@tizen-tc-fastmodels.rnd.samsung.ru>
Fri, 10 Jul 2015 12:35:27 +0000 (15:35 +0300)
Ported from
r210338
r210397
r210523
r214745

Change-Id: I4f3e93badd474092b375577c574cfa119b99a875
Signed-off-by: Ilya Palachev <i.palachev@samsung.com>
15 files changed:
gcc/basic-block.h
gcc/builtins.c
gcc/cfghooks.c
gcc/diagnostic.c
gcc/dwarf2out.c
gcc/final.c
gcc/gimple-pretty-print.c
gcc/input.c
gcc/input.h
gcc/print-rtl.c
gcc/rtl.h
gcc/tree-cfg.c
gcc/tree-diagnostic.c
gcc/tree-pretty-print.c
gcc/tree-ssa-uninit.c

index f55cd8d..64949c4 100644 (file)
@@ -201,11 +201,6 @@ struct GTY((chain_next ("%h.next_bb"), chain_prev ("%h.prev_bb"))) basic_block_d
 
   /* 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 0825391..3387f46 100644 (file)
@@ -12069,13 +12069,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 bc1634a..5de7cdc 100644 (file)
@@ -500,7 +500,6 @@ split_block (basic_block bb, void *i)
 
   new_bb->count = bb->count;
   new_bb->frequency = bb->frequency;
-  new_bb->discriminator = bb->discriminator;
 
   if (dom_info_available_p (CDI_DOMINATORS))
     {
index 0cc7593..7cb4ae7 100644 (file)
@@ -187,6 +187,7 @@ diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
                                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;
@@ -513,6 +514,9 @@ diagnostic_report_current_module (diagnostic_context *context, location_t where)
   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 6b4e83a..bb937f8 100644 (file)
@@ -18892,12 +18892,16 @@ gen_label_die (tree decl, dw_die_ref context_die)
 static inline void
 add_call_src_coords_attributes (tree stmt, dw_die_ref die)
 {
-  expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (stmt));
+  location_t locus = BLOCK_SOURCE_LOCATION (stmt);
+  expanded_location s = expand_location (locus);
 
   if (dwarf_version >= 3 || !dwarf_strict)
     {
       add_AT_file (die, DW_AT_call_file, lookup_filename (s.file));
       add_AT_unsigned (die, DW_AT_call_line, s.line);
+      unsigned discr = get_discriminator_from_locus (locus);
+      if (discr != 0)
+       add_AT_unsigned (die, DW_AT_GNU_discriminator, discr);
     }
 }
 
index 83abee2..1f1eded 100644 (file)
@@ -125,9 +125,6 @@ static int last_linenum;
 /* Last discriminator written to assembly.  */
 static int last_discriminator;
 
-/* Discriminator of current block.  */
-static int discriminator;
-
 /* Highest line number in current block.  */
 static int high_block_linenum;
 
@@ -137,9 +134,10 @@ static int high_function_linenum;
 /* Filename of last NOTE.  */
 static const char *last_filename;
 
-/* Override filename and line number.  */
+/* Override filename, line number, and discriminator.  */
 static const char *override_filename;
 static int override_linenum;
+static int override_discriminator;
 
 /* Whether to force emission of a line note before the next insn.  */
 static bool force_source_line = false;
@@ -1735,7 +1733,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;
 
@@ -2186,8 +2184,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
          if (targetm.asm_out.unwind_emit)
            targetm.asm_out.unwind_emit (asm_out_file, insn);
 
-          discriminator = NOTE_BASIC_BLOCK (insn)->discriminator;
-
          break;
 
        case NOTE_INSN_EH_REGION_BEG:
@@ -2280,6 +2276,8 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
                {
                  override_filename = LOCATION_FILE (*locus_ptr);
                  override_linenum = LOCATION_LINE (*locus_ptr);
+                 override_discriminator =
+                     get_discriminator_from_locus (*locus_ptr);
                }
            }
          break;
@@ -2313,11 +2311,14 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
                {
                  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;
@@ -3000,6 +3001,17 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
     }
   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);
+}
+
 \f
 /* 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
@@ -3010,16 +3022,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 741cd92..65f4566 100644 (file)
@@ -2268,8 +2268,6 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent, int flags)
                         indent, "", get_lineno (gsi_stmt (gsi)));
                break;
              }
-         if (bb->discriminator)
-           fprintf (outf, ", discriminator %i", bb->discriminator);
          fputc ('\n', outf);
        }
     }
index 63cd062..c819303 100644 (file)
@@ -109,6 +109,11 @@ location_t input_location;
 
 struct line_maps *line_table;
 
+static vec<location_t> discriminator_location_locations;
+static vec<int> discriminator_location_discriminators;
+static location_t next_discriminator_location = UNKNOWN_LOCATION;
+static location_t min_discriminator_location = UNKNOWN_LOCATION;
+
 static fcache *fcache_tab;
 static const size_t fcache_tab_size = 16;
 static const size_t fcache_buffer_size = 4 * 1024;
@@ -143,6 +148,13 @@ expand_location_1 (source_location loc,
       loc = LOCATION_LOCUS (loc);
     }
 
+  /* If LOC describes a location with a discriminator, extract the
+     discriminator and map it to the real location.  */
+  if (min_discriminator_location != UNKNOWN_LOCATION
+      && loc >= min_discriminator_location
+      && loc < next_discriminator_location)
+    loc = map_discriminator_location (loc);
+
   memset (&xloc, 0, sizeof (xloc));
 
   if (loc >= RESERVED_LOCATION_COUNT)
@@ -852,3 +864,84 @@ dump_line_table_statistics (void)
            STAT_LABEL (total_used_map_size));
   fprintf (stderr, "\n");
 }
+
+/* Associate the DISCRIMINATOR with LOCUS, and return a new locus.
+   We associate discriminators with a locus by allocating location_t
+   values beyond those assigned by libcpp.  Each new value is mapped
+   directly to a real location_t value, and separately to the
+   discriminator.  */
+
+location_t
+location_with_discriminator (location_t locus, int discriminator)
+{
+  tree block = LOCATION_BLOCK (locus);
+  location_t ret;
+  int i;
+  locus = map_discriminator_location (locus);
+
+  if (locus == UNKNOWN_LOCATION)
+    return block ? COMBINE_LOCATION_DATA (line_table, locus, block)
+                : locus;
+
+  if (min_discriminator_location == UNKNOWN_LOCATION)
+    {
+      min_discriminator_location = line_table->highest_location + 1;
+      next_discriminator_location = min_discriminator_location;
+    }
+
+  /* Traverse the last few discriminator_locations to see if we can reuse
+     the entry.  */
+  for (i = next_discriminator_location - min_discriminator_location - 1;
+       (i >= 0 && LOCATION_LINE (discriminator_location_locations[i]) ==
+                                LOCATION_LINE (locus)
+        && discriminator_location_discriminators[i] == discriminator);
+       i--)
+    if (discriminator_location_locations[i] == locus)
+      return (block
+         ? COMBINE_LOCATION_DATA (line_table, min_discriminator_location + i,
+                                  block)
+         : min_discriminator_location + i);
+
+  discriminator_location_locations.safe_push(locus);
+  discriminator_location_discriminators.safe_push(discriminator);
+
+  ret = (block
+      ? COMBINE_LOCATION_DATA (line_table, next_discriminator_location, block)
+      : next_discriminator_location);
+
+  next_discriminator_location++;
+  return ret;
+}
+
+/* Return TRUE if LOCUS represents a location with a discriminator.  */
+
+bool
+has_discriminator (location_t locus)
+{
+  locus = LOCATION_LOCUS (locus);
+  return (min_discriminator_location != UNKNOWN_LOCATION
+         && locus >= min_discriminator_location
+         && locus < next_discriminator_location);
+}
+
+/* Return the real location_t value for LOCUS.  */
+
+location_t
+map_discriminator_location (location_t locus)
+{
+  locus = LOCATION_LOCUS (locus);
+  if (! has_discriminator (locus))
+    return locus;
+  return (location_t) discriminator_location_locations[locus - min_discriminator_location];
+}
+
+/* Return the discriminator for LOCUS.  */
+
+int
+get_discriminator_from_locus (location_t locus)
+{
+  locus = LOCATION_LOCUS (locus);
+  if (! has_discriminator (locus))
+    return 0;
+  return discriminator_location_discriminators[locus - min_discriminator_location];
+}
index d910bb8..1b73ee8 100644 (file)
@@ -48,6 +48,11 @@ typedef source_location location_t;
 
 extern location_t input_location;
 
+extern location_t location_with_discriminator (location_t, int);
+extern bool has_discriminator (location_t);
+extern location_t map_discriminator_location (location_t);
+extern int get_discriminator_from_locus (location_t);
+
 #define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
 #define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
 #define LOCATION_COLUMN(LOC)((expand_location (LOC)).column)
@@ -59,7 +64,8 @@ extern location_t input_location;
    : NULL))
 
 #define in_system_header_at(LOC) \
-  ((linemap_location_in_system_header_p (line_table, LOC)))
+  ((linemap_location_in_system_header_p (line_table, \
+                                        map_discriminator_location (LOC))))
 
 void dump_line_table_statistics (void);
 
index 09ac387..668d0c4 100644 (file)
@@ -410,8 +410,13 @@ print_rtx (const_rtx in_rtx)
                redundant with line number information and do not print anything
                when there is no location information available.  */
            if (INSN_LOCATION (in_rtx) && insn_file (in_rtx))
-             fprintf (outfile, " %s:%i", insn_file (in_rtx),
-                      insn_line (in_rtx));
+              {
+                int discriminator = insn_discriminator (in_rtx);
+               fprintf (outfile, " %s:%i", insn_file (in_rtx),
+                        insn_line (in_rtx));
+                if (discriminator)
+                  fprintf (outfile, " discrim %d", discriminator);
+              }
 #endif
          }
        else if (i == 6 && GET_CODE (in_rtx) == ASM_OPERANDS)
index f1cda4c..115491a 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1920,6 +1920,7 @@ extern rtx prev_cc0_setter (rtx);
 extern int insn_line (const_rtx);
 extern const char * insn_file (const_rtx);
 extern tree insn_scope (const_rtx);
+extern int insn_discriminator (const_rtx);
 extern location_t prologue_location, epilogue_location;
 
 /* In jump.c */
index 1469d78..d466195 100644 (file)
@@ -110,7 +110,14 @@ static struct cfg_stats_d cfg_stats;
 struct locus_discrim_map
 {
   location_t locus;
-  int discriminator;
+  /* Different calls belonging to the same source line will be assigned
+     different discriminators. But we want to keep the discriminator of
+     the first call in the same source line to be 0, in order to reduce
+     the .debug_line section size. needs_increment is used for this
+     purpose. It is initialized as false and will be set to true after
+     the first call is seen.  */
+  bool needs_increment:1;
+  int discriminator:31;
 };
 
 /* Hashtable helpers.  */
@@ -942,10 +949,15 @@ make_edges (void)
 /* Find the next available discriminator value for LOCUS.  The
    discriminator distinguishes among several basic blocks that
    share a common locus, allowing for more accurate sample-based
-   profiling.  */
+   profiling. If RETURN_NEXT is true, return the next discriminator
+   anyway. If RETURN_NEXT is not true, we may not increase the
+   discriminator if locus_discrim_map::needs_increment is false,
+   which is used when the stmt is the first call stmt in current
+   source line. locus_discrim_map::needs_increment will be set to
+   true after the first call is seen.  */
 
 static int
-next_discriminator_for_locus (location_t locus)
+next_discriminator_for_locus (location_t locus, bool return_next)
 {
   struct locus_discrim_map item;
   struct locus_discrim_map **slot;
@@ -960,9 +972,13 @@ next_discriminator_for_locus (location_t locus)
       *slot = XNEW (struct locus_discrim_map);
       gcc_assert (*slot);
       (*slot)->locus = locus;
+      (*slot)->needs_increment = false;
       (*slot)->discriminator = 0;
     }
-  (*slot)->discriminator++;
+  if (return_next || (*slot)->needs_increment)
+    (*slot)->discriminator++;
+  else
+    (*slot)->needs_increment = true;
   return (*slot)->discriminator;
 }
 
@@ -988,6 +1004,32 @@ same_line_p (location_t locus1, location_t locus2)
           && filename_cmp (from.file, to.file) == 0);
 }
 
+/* Assign a unique discriminator value to instructions in block BB that
+   have the same LOCUS as its predecessor block.  */
+
+static void
+assign_discriminator (location_t locus, basic_block bb)
+{
+  gimple_stmt_iterator gsi;
+  int discriminator;
+
+  locus = map_discriminator_location (locus);
+
+  if (locus == UNKNOWN_LOCATION)
+    return;
+
+  discriminator = next_discriminator_for_locus (locus, true);
+
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple stmt = gsi_stmt (gsi);
+      location_t stmt_locus = gimple_location (stmt);
+      if (same_line_p (locus, stmt_locus))
+       gimple_set_location (stmt,
+           location_with_discriminator (stmt_locus, discriminator));
+    }
+}
+
 /* Assign discriminators to each basic block.  */
 
 static void
@@ -999,8 +1041,26 @@ assign_discriminators (void)
     {
       edge e;
       edge_iterator ei;
+      gimple_stmt_iterator gsi;
       gimple last = last_stmt (bb);
       location_t locus = last ? gimple_location (last) : UNKNOWN_LOCATION;
+      location_t curr_locus = UNKNOWN_LOCATION;
+      int curr_discr = 0;
+
+      /* Traverse the basic block, if two function calls within a basic block
+        are mapped to a same line, assign a new discriminator because a call
+        stmt could be a split point of a basic block.  */
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         gimple stmt = gsi_stmt (gsi);
+          if (gimple_code (stmt) == GIMPLE_CALL)
+            {
+             curr_locus = gimple_location (stmt);
+             curr_discr = next_discriminator_for_locus (curr_locus, false);
+             gimple_set_location (stmt, location_with_discriminator (
+                 curr_locus, curr_discr));
+           }
+       }
 
       if (locus == UNKNOWN_LOCATION)
        continue;
@@ -1012,10 +1072,12 @@ assign_discriminators (void)
          if ((first && same_line_p (locus, gimple_location (first)))
              || (last && same_line_p (locus, gimple_location (last))))
            {
-             if (e->dest->discriminator != 0 && bb->discriminator == 0)
-               bb->discriminator = next_discriminator_for_locus (locus);
+             if (((first && has_discriminator (gimple_location (first)))
+                  || (last && has_discriminator (gimple_location (last))))
+                 && !has_discriminator (locus))
+               assign_discriminator (locus, bb);
              else
-               e->dest->discriminator = next_discriminator_for_locus (locus);
+               assign_discriminator (locus, e->dest);
            }
        }
     }
index ee71555..dec95f8 100644 (file)
@@ -108,6 +108,8 @@ maybe_unwind_expanded_macro_loc (diagnostic_context *context,
   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 d6f39d8..fae506a 100644 (file)
@@ -671,6 +671,7 @@ static void
 dump_location (pretty_printer *buffer, location_t loc)
 {
   expanded_location xloc = expand_location (loc);
+  int discriminator = get_discriminator_from_locus (loc);
 
   pp_left_bracket (buffer);
   if (xloc.file)
@@ -679,6 +680,11 @@ dump_location (pretty_printer *buffer, location_t loc)
       pp_string (buffer, " : ");
     }
   pp_decimal_int (buffer, xloc.line);
+  if (discriminator)
+    {
+      pp_string (buffer, " discrim ");
+       pp_decimal_int (buffer, discriminator);
+    }
   pp_string (buffer, "] ");
 }
 
index eee83f7..ca68412 100644 (file)
@@ -149,6 +149,7 @@ warn_uninit (enum opt_code wc, tree t,
   location = (context != NULL && gimple_has_location (context))
             ? gimple_location (context)
             : DECL_SOURCE_LOCATION (var);
+  location = map_discriminator_location (location);
   location = linemap_resolve_location (line_table, location,
                                       LRK_SPELLING_LOCATION,
                                       NULL);