dwarf2out.h (enum dw_val_class): Add dw_val_class_const_implicit...
authorJakub Jelinek <jakub@redhat.com>
Mon, 31 Oct 2016 16:59:21 +0000 (17:59 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 31 Oct 2016 16:59:21 +0000 (17:59 +0100)
* dwarf2out.h (enum dw_val_class): Add dw_val_class_const_implicit,
dw_val_class_unsigned_const_implicit and dw_val_class_file_implicit.
(struct dw_val_node): Add val_file_implicit field.
* dwarf2out.c (dw_val_equal_p, print_dw_val, attr_checksum,
attr_checksum_ordered, same_dw_val_p, size_of_die, value_format,
output_die): Handle dw_val_class_const_implicit,
dw_val_class_unsigned_const_implicit and dw_val_class_file_implicit.
(abbrev_die_table): Change into va_gc vec.
(abbrev_die_table_allocated, abbrev_die_table_in_use,
ABBREV_DIE_TABLE_INCREMENT): Remove.
(AT_int, AT_unsigned, AT_file): Allow dw_val_class_*_implicit.
(abbrev_opt_start, abbrev_usage_count, sorted_abbrev_dies): New
variables.
(build_abbrev_table): Adjust for abbrev_die_table being a va_gc vec.
If abbrev_opt_start, fill in abbrev_usage_count and abbrev_dies
vectors.
(die_abbrev_cmp, optimize_implicit_const, optimize_abbrev_table): New
functions.
(output_die_abbrevs): For DW_FORM_implicit_const emit sleb128 with
the implicit value.
(output_abbrev_section): Adjust for abbrev_die_table being a va_gc
vec.
(output_comp_unit): Initialize abbrev_opt_start if emitting the main
unit.  Call optimize_abbrev_table.
(dwarf2out_init, dwarf2out_finish, dwarf2out_c_finalize): Adjust for
abbrev_die_table being a va_gc vec.

From-SVN: r241709

gcc/ChangeLog
gcc/dwarf2out.c
gcc/dwarf2out.h

index d596b17..e3347c0 100644 (file)
@@ -1,5 +1,32 @@
 2016-10-31  Jakub Jelinek  <jakub@redhat.com>
 
+       * dwarf2out.h (enum dw_val_class): Add dw_val_class_const_implicit,
+       dw_val_class_unsigned_const_implicit and dw_val_class_file_implicit.
+       (struct dw_val_node): Add val_file_implicit field.
+       * dwarf2out.c (dw_val_equal_p, print_dw_val, attr_checksum,
+       attr_checksum_ordered, same_dw_val_p, size_of_die, value_format,
+       output_die): Handle dw_val_class_const_implicit,
+       dw_val_class_unsigned_const_implicit and dw_val_class_file_implicit.
+       (abbrev_die_table): Change into va_gc vec.
+       (abbrev_die_table_allocated, abbrev_die_table_in_use,
+       ABBREV_DIE_TABLE_INCREMENT): Remove.
+       (AT_int, AT_unsigned, AT_file): Allow dw_val_class_*_implicit.
+       (abbrev_opt_start, abbrev_usage_count, sorted_abbrev_dies): New
+       variables.
+       (build_abbrev_table): Adjust for abbrev_die_table being a va_gc vec.
+       If abbrev_opt_start, fill in abbrev_usage_count and abbrev_dies
+       vectors.
+       (die_abbrev_cmp, optimize_implicit_const, optimize_abbrev_table): New
+       functions.
+       (output_die_abbrevs): For DW_FORM_implicit_const emit sleb128 with
+       the implicit value.
+       (output_abbrev_section): Adjust for abbrev_die_table being a va_gc
+       vec.
+       (output_comp_unit): Initialize abbrev_opt_start if emitting the main
+       unit.  Call optimize_abbrev_table.
+       (dwarf2out_init, dwarf2out_finish, dwarf2out_c_finalize): Adjust for
+       abbrev_die_table being a va_gc vec.
+
        PR tree-optimization/77860
        * tree-ssa-reassoc.c (eliminate_using_constants): Handle
        also integral complex and vector constants.
index 615eca8..60e2274 100644 (file)
@@ -1363,6 +1363,8 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b)
     case dw_val_class_offset:
     case dw_val_class_unsigned_const:
     case dw_val_class_const:
+    case dw_val_class_unsigned_const_implicit:
+    case dw_val_class_const_implicit:
     case dw_val_class_range_list:
     case dw_val_class_lineptr:
     case dw_val_class_macptr:
@@ -1385,6 +1387,7 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b)
     case dw_val_class_flag:
       return a->v.val_flag == b->v.val_flag;
     case dw_val_class_file:
+    case dw_val_class_file_implicit:
       return a->v.val_file == b->v.val_file;
     case dw_val_class_decl_ref:
       return a->v.val_decl_ref == b->v.val_decl_ref;
@@ -3006,17 +3009,9 @@ struct dw_loc_list_hasher : ggc_ptr_hash<cached_dw_loc_list>
 /* Table of cached location lists.  */
 static GTY (()) hash_table<dw_loc_list_hasher> *cached_dw_loc_list_table;
 
-/* A pointer to the base of a list of references to DIE's that
-   are uniquely identified by their tag, presence/absence of
-   children DIE's, and list of attribute/value pairs.  */
-static GTY((length ("abbrev_die_table_allocated")))
-  dw_die_ref *abbrev_die_table;
-
-/* Number of elements currently allocated for abbrev_die_table.  */
-static GTY(()) unsigned abbrev_die_table_allocated;
-
-/* Number of elements in abbrev_die_table currently in use.  */
-static GTY(()) unsigned abbrev_die_table_in_use;
+/* A vector of references to DIE's that are uniquely identified by their tag,
+   presence/absence of children DIE's, and list of attribute/value pairs.  */
+static GTY(()) vec<dw_die_ref, va_gc> *abbrev_die_table;
 
 /* A hash map to remember the stack usage for DWARF procedures.  The value
    stored is the stack size difference between before the DWARF procedure
@@ -3024,10 +3019,6 @@ static GTY(()) unsigned abbrev_die_table_in_use;
    that consumes N stack slots and that pushes M ones, this stores M - N.  */
 static hash_map<dw_die_ref, int> *dwarf_proc_stack_usage_map;
 
-/* Size (in elements) of increments by which we may expand the
-   abbrev_die_table.  */
-#define ABBREV_DIE_TABLE_INCREMENT 256
-
 /* A global counter for generating labels for line number data.  */
 static unsigned int line_info_label_num;
 
@@ -3905,7 +3896,8 @@ add_AT_int (dw_die_ref die, enum dwarf_attribute attr_kind, HOST_WIDE_INT int_va
 static inline HOST_WIDE_INT
 AT_int (dw_attr_node *a)
 {
-  gcc_assert (a && AT_class (a) == dw_val_class_const);
+  gcc_assert (a && (AT_class (a) == dw_val_class_const
+                   || AT_class (a) == dw_val_class_const_implicit));
   return a->dw_attr_val.v.val_int;
 }
 
@@ -3927,7 +3919,8 @@ add_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind,
 static inline unsigned HOST_WIDE_INT
 AT_unsigned (dw_attr_node *a)
 {
-  gcc_assert (a && AT_class (a) == dw_val_class_unsigned_const);
+  gcc_assert (a && (AT_class (a) == dw_val_class_unsigned_const
+                   || AT_class (a) == dw_val_class_unsigned_const_implicit));
   return a->dw_attr_val.v.val_unsigned;
 }
 
@@ -4506,7 +4499,8 @@ add_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind,
 static inline struct dwarf_file_data *
 AT_file (dw_attr_node *a)
 {
-  gcc_assert (a && AT_class (a) == dw_val_class_file);
+  gcc_assert (a && (AT_class (a) == dw_val_class_file
+                   || AT_class (a) == dw_val_class_file_implicit));
   return a->dw_attr_val.v.val_file;
 }
 
@@ -5581,9 +5575,11 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
       fprintf (outfile, "range list");
       break;
     case dw_val_class_const:
+    case dw_val_class_const_implicit:
       fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, val->v.val_int);
       break;
     case dw_val_class_unsigned_const:
+    case dw_val_class_unsigned_const_implicit:
       fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, val->v.val_unsigned);
       break;
     case dw_val_class_const_double:
@@ -5650,6 +5646,7 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
        fprintf (outfile, "<null>");
       break;
     case dw_val_class_file:
+    case dw_val_class_file_implicit:
       fprintf (outfile, "\"%s\" (%d)", val->v.val_file->filename,
               val->v.val_file->emitted_number);
       break;
@@ -5979,9 +5976,11 @@ attr_checksum (dw_attr_node *at, struct md5_ctx *ctx, int *mark)
   switch (AT_class (at))
     {
     case dw_val_class_const:
+    case dw_val_class_const_implicit:
       CHECKSUM (at->dw_attr_val.v.val_int);
       break;
     case dw_val_class_unsigned_const:
+    case dw_val_class_unsigned_const_implicit:
       CHECKSUM (at->dw_attr_val.v.val_unsigned);
       break;
     case dw_val_class_const_double:
@@ -6032,6 +6031,7 @@ attr_checksum (dw_attr_node *at, struct md5_ctx *ctx, int *mark)
       break;
 
     case dw_val_class_file:
+    case dw_val_class_file_implicit:
       CHECKSUM_STRING (AT_file (at)->filename);
       break;
 
@@ -6256,11 +6256,13 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_node *at,
   switch (AT_class (at))
     {
     case dw_val_class_const:
+    case dw_val_class_const_implicit:
       CHECKSUM_ULEB128 (DW_FORM_sdata);
       CHECKSUM_SLEB128 (at->dw_attr_val.v.val_int);
       break;
 
     case dw_val_class_unsigned_const:
+    case dw_val_class_unsigned_const_implicit:
       CHECKSUM_ULEB128 (DW_FORM_sdata);
       CHECKSUM_SLEB128 ((int) at->dw_attr_val.v.val_unsigned);
       break;
@@ -6324,6 +6326,7 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_node *at,
       break;
 
     case dw_val_class_file:
+    case dw_val_class_file_implicit:
       CHECKSUM_ULEB128 (DW_FORM_string);
       CHECKSUM_STRING (AT_file (at)->filename);
       break;
@@ -6766,8 +6769,10 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
   switch (v1->val_class)
     {
     case dw_val_class_const:
+    case dw_val_class_const_implicit:
       return v1->v.val_int == v2->v.val_int;
     case dw_val_class_unsigned_const:
+    case dw_val_class_unsigned_const_implicit:
       return v1->v.val_unsigned == v2->v.val_unsigned;
     case dw_val_class_const_double:
       return v1->v.val_double.high == v2->v.val_double.high
@@ -6817,6 +6822,7 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
       return 1;
 
     case dw_val_class_file:
+    case dw_val_class_file_implicit:
       return v1->v.val_file == v2->v.val_file;
 
     case dw_val_class_data8:
@@ -8252,6 +8258,20 @@ optimize_external_refs (dw_die_ref die)
   return map;
 }
 
+/* The following 3 variables are temporaries that are computed only during the
+   build_abbrev_table call and used and released during the following
+   optimize_abbrev_table call.  */
+
+/* First abbrev_id that can be optimized based on usage.  */
+static unsigned int abbrev_opt_start;
+
+/* Vector of usage counts during build_abbrev_table.  Indexed by
+   abbrev_id - abbrev_opt_start.  */
+static vec<unsigned int> abbrev_usage_count;
+
+/* Vector of all DIEs added with die_abbrev >= abbrev_opt_start.  */
+static vec<dw_die_ref> sorted_abbrev_dies;
+
 /* The format of each DIE (and its attribute value pairs) is encoded in an
    abbreviation table.  This routine builds the abbreviation table and assigns
    a unique abbreviation id for each abbreviation entry.  The children of each
@@ -8260,11 +8280,11 @@ optimize_external_refs (dw_die_ref die)
 static void
 build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
 {
-  unsigned long abbrev_id;
-  unsigned int n_alloc;
+  unsigned int abbrev_id = 0;
   dw_die_ref c;
   dw_attr_node *a;
   unsigned ix;
+  dw_die_ref abbrev;
 
   /* Scan the DIE references, and replace any that refer to
      DIEs from other CUs (i.e. those which are not marked) with
@@ -8284,13 +8304,14 @@ build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
          set_AT_ref_external (a, 1);
       }
 
-  for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
+  FOR_EACH_VEC_SAFE_ELT (abbrev_die_table, abbrev_id, abbrev)
     {
-      dw_die_ref abbrev = abbrev_die_table[abbrev_id];
       dw_attr_node *die_a, *abbrev_a;
       unsigned ix;
       bool ok = true;
 
+      if (abbrev_id == 0)
+       continue;
       if (abbrev->die_tag != die->die_tag)
        continue;
       if ((abbrev->die_child != NULL) != (die->die_child != NULL))
@@ -8313,25 +8334,179 @@ build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
        break;
     }
 
-  if (abbrev_id >= abbrev_die_table_in_use)
+  if (abbrev_id >= vec_safe_length (abbrev_die_table))
+    {
+      vec_safe_push (abbrev_die_table, die);
+      if (abbrev_opt_start)
+       abbrev_usage_count.safe_push (0);
+    }
+  if (abbrev_opt_start && abbrev_id >= abbrev_opt_start)
+    {
+      abbrev_usage_count[abbrev_id - abbrev_opt_start]++;
+      sorted_abbrev_dies.safe_push (die);
+    }
+
+  die->die_abbrev = abbrev_id;
+  FOR_EACH_CHILD (die, c, build_abbrev_table (c, extern_map));
+}
+
+/* Callback function for sorted_abbrev_dies vector sorting.  We sort
+   by die_abbrev's usage count, from the most commonly used
+   abbreviation to the least.  */
+
+static int
+die_abbrev_cmp (const void *p1, const void *p2)
+{
+  dw_die_ref die1 = *(const dw_die_ref *) p1;
+  dw_die_ref die2 = *(const dw_die_ref *) p2;
+
+  gcc_checking_assert (die1->die_abbrev >= abbrev_opt_start);
+  gcc_checking_assert (die2->die_abbrev >= abbrev_opt_start);
+
+  if (abbrev_usage_count[die1->die_abbrev - abbrev_opt_start]
+      > abbrev_usage_count[die2->die_abbrev - abbrev_opt_start])
+    return -1;
+  if (abbrev_usage_count[die1->die_abbrev - abbrev_opt_start]
+      < abbrev_usage_count[die2->die_abbrev - abbrev_opt_start])
+    return 1;
+
+  /* Stabilize the sort.  */
+  if (die1->die_abbrev < die2->die_abbrev)
+    return -1;
+  if (die1->die_abbrev > die2->die_abbrev)
+    return 1;
+
+  return 0;
+}
+
+/* Convert dw_val_class_const and dw_val_class_unsigned_const class attributes
+   of DIEs in between sorted_abbrev_dies[first_id] and abbrev_dies[end_id - 1]
+   into dw_val_class_const_implicit or
+   dw_val_class_unsigned_const_implicit.  */
+
+static void
+optimize_implicit_const (unsigned int first_id, unsigned int end,
+                        vec<bool> &implicit_consts)
+{
+  /* It never makes sense if there is just one DIE using the abbreviation.  */
+  if (end < first_id + 2)
+    return;
+
+  dw_attr_node *a;
+  unsigned ix, i;
+  dw_die_ref die = sorted_abbrev_dies[first_id];
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+    if (implicit_consts[ix])
+      {
+       enum dw_val_class new_class = dw_val_class_none;
+       switch (AT_class (a))
+         {
+         case dw_val_class_unsigned_const:
+           if ((HOST_WIDE_INT) AT_unsigned (a) < 0)
+             continue;
+
+           /* The .debug_abbrev section will grow by
+              size_of_sleb128 (AT_unsigned (a)) and we avoid the constants
+              in all the DIEs using that abbreviation.  */
+           if (constant_size (AT_unsigned (a)) * (end - first_id)
+               <= (unsigned) size_of_sleb128 (AT_unsigned (a)))
+             continue;
+
+           new_class = dw_val_class_unsigned_const_implicit;
+           break;
+
+         case dw_val_class_const:
+           new_class = dw_val_class_const_implicit;
+           break;
+
+         case dw_val_class_file:
+           new_class = dw_val_class_file_implicit;
+           break;
+
+         default:
+           continue;
+         }
+       for (i = first_id; i < end; i++)
+         (*sorted_abbrev_dies[i]->die_attr)[ix].dw_attr_val.val_class
+           = new_class;
+      }
+}
+
+/* Attempt to optimize abbreviation table from abbrev_opt_start
+   abbreviation above.  */
+
+static void
+optimize_abbrev_table (void)
+{
+  if (abbrev_opt_start
+      && vec_safe_length (abbrev_die_table) > abbrev_opt_start
+      && (dwarf_version >= 5 || vec_safe_length (abbrev_die_table) > 127))
     {
-      if (abbrev_die_table_in_use >= abbrev_die_table_allocated)
+      auto_vec<bool, 32> implicit_consts;
+      sorted_abbrev_dies.qsort (die_abbrev_cmp);
+
+      unsigned int abbrev_id = abbrev_opt_start - 1;
+      unsigned int first_id = 0;
+      unsigned int last_abbrev_id = 0;
+      unsigned int i;
+      dw_die_ref die;
+      /* Reassign abbreviation ids from abbrev_opt_start above, so that
+        most commonly used abbreviations come first.  */
+      FOR_EACH_VEC_ELT (sorted_abbrev_dies, i, die)
        {
-         n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
-         abbrev_die_table = GGC_RESIZEVEC (dw_die_ref, abbrev_die_table,
-                                           n_alloc);
+         dw_attr_node *a;
+         unsigned ix;
 
-         memset (&abbrev_die_table[abbrev_die_table_allocated], 0,
-                (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
-         abbrev_die_table_allocated = n_alloc;
-       }
+         if (die->die_abbrev != last_abbrev_id)
+           {
+             last_abbrev_id = die->die_abbrev;
+             if (dwarf_version >= 5 && i)
+               optimize_implicit_const (first_id, i, implicit_consts);
+             abbrev_id++;
+             (*abbrev_die_table)[abbrev_id] = die;
+             if (dwarf_version >= 5)
+               {
+                 first_id = i;
+                 implicit_consts.truncate (0);
 
-      ++abbrev_die_table_in_use;
-      abbrev_die_table[abbrev_id] = die;
+                 FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+                   switch (AT_class (a))
+                     {
+                     case dw_val_class_const:
+                     case dw_val_class_unsigned_const:
+                     case dw_val_class_file:
+                       implicit_consts.safe_push (true);
+                       break;
+                     default:
+                       implicit_consts.safe_push (false);
+                       break;
+                     }
+               }
+           }
+         else if (dwarf_version >= 5)
+           {
+             FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+               if (!implicit_consts[ix])
+                 continue;
+               else
+                 {
+                   dw_attr_node *other_a
+                     = &(*(*abbrev_die_table)[abbrev_id]->die_attr)[ix];
+                   if (!dw_val_equal_p (&a->dw_attr_val,
+                                        &other_a->dw_attr_val))
+                     implicit_consts[ix] = false;
+                 }
+           }
+         die->die_abbrev = abbrev_id;
+       }
+      gcc_assert (abbrev_id == vec_safe_length (abbrev_die_table) - 1);
+      if (dwarf_version >= 5)
+       optimize_implicit_const (first_id, i, implicit_consts);
     }
 
-  die->die_abbrev = abbrev_id;
-  FOR_EACH_CHILD (die, c, build_abbrev_table (c, extern_map));
+  abbrev_opt_start = 0;
+  abbrev_usage_count.release ();
+  sorted_abbrev_dies.release ();
 }
 \f
 /* Return the power-of-two number of bytes necessary to represent VALUE.  */
@@ -8418,6 +8593,12 @@ size_of_die (dw_die_ref die)
              size += csize;
          }
          break;
+       case dw_val_class_const_implicit:
+       case dw_val_class_unsigned_const_implicit:
+       case dw_val_class_file_implicit:
+         /* These occupy no size in the DIE, just an extra sleb128 in
+            .debug_abbrev.  */
+         break;
        case dw_val_class_const_double:
          size += HOST_BITS_PER_DOUBLE_INT / HOST_BITS_PER_CHAR;
          if (HOST_BITS_PER_WIDE_INT >= 64)
@@ -8798,6 +8979,10 @@ value_format (dw_attr_node *a)
        default:
          gcc_unreachable ();
        }
+    case dw_val_class_const_implicit:
+    case dw_val_class_unsigned_const_implicit:
+    case dw_val_class_file_implicit:
+      return DW_FORM_implicit_const;
     case dw_val_class_const_double:
       switch (HOST_BITS_PER_WIDE_INT)
        {
@@ -8951,6 +9136,17 @@ output_die_abbrevs (unsigned long abbrev_id, dw_die_ref abbrev)
       dw2_asm_output_data_uleb128 (a_attr->dw_attr, "(%s)",
                                    dwarf_attr_name (a_attr->dw_attr));
       output_value_format (a_attr);
+      if (value_format (a_attr) == DW_FORM_implicit_const)
+       {
+         if (AT_class (a_attr) == dw_val_class_file_implicit)
+           {
+             int f = maybe_emit_file (a_attr->dw_attr_val.v.val_file);
+             const char *filename = a_attr->dw_attr_val.v.val_file->filename;
+             dw2_asm_output_data_sleb128 (f, "(%s)", filename);
+           }
+         else
+           dw2_asm_output_data_sleb128 (a_attr->dw_attr_val.v.val_int, NULL);
+       }
     }
 
   dw2_asm_output_data (1, 0, NULL);
@@ -8964,10 +9160,12 @@ output_die_abbrevs (unsigned long abbrev_id, dw_die_ref abbrev)
 static void
 output_abbrev_section (void)
 {
-  unsigned long abbrev_id;
+  unsigned int abbrev_id;
+  dw_die_ref abbrev;
 
-  for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
-    output_die_abbrevs (abbrev_id, abbrev_die_table[abbrev_id]);
+  FOR_EACH_VEC_SAFE_ELT (abbrev_die_table, abbrev_id, abbrev)
+    if (abbrev_id != 0)
+      output_die_abbrevs (abbrev_id, abbrev);
 
   /* Terminate the table.  */
   dw2_asm_output_data (1, 0, NULL);
@@ -9264,6 +9462,20 @@ output_die (dw_die_ref die)
          }
          break;
 
+       case dw_val_class_const_implicit:
+         if (flag_debug_asm)
+           fprintf (asm_out_file, "\t\t\t%s %s ("
+                                  HOST_WIDE_INT_PRINT_DEC ")\n",
+                    ASM_COMMENT_START, name, AT_int (a));
+         break;
+
+       case dw_val_class_unsigned_const_implicit:
+         if (flag_debug_asm)
+           fprintf (asm_out_file, "\t\t\t%s %s ("
+                                  HOST_WIDE_INT_PRINT_HEX ")\n",
+                    ASM_COMMENT_START, name, AT_unsigned (a));
+         break;
+
        case dw_val_class_const_double:
          {
            unsigned HOST_WIDE_INT first, second;
@@ -9457,6 +9669,14 @@ output_die (dw_die_ref die)
            break;
          }
 
+       case dw_val_class_file_implicit:
+         if (flag_debug_asm)
+           fprintf (asm_out_file, "\t\t\t%s %s (%d, %s)\n",
+                    ASM_COMMENT_START, name,
+                    maybe_emit_file (a->dw_attr_val.v.val_file),
+                    a->dw_attr_val.v.val_file->filename);
+         break;
+
        case dw_val_class_data8:
          {
            int i;
@@ -9564,8 +9784,16 @@ output_comp_unit (dw_die_ref die, int output_if_empty)
 
   external_ref_hash_type *extern_map = optimize_external_refs (die);
 
+  /* For now, optimize only the main CU, in order to optimize the rest
+     we'd need to see all of them earlier.  Leave the rest for post-linking
+     tools like DWZ.  */
+  if (die == comp_unit_die ())
+    abbrev_opt_start = vec_safe_length (abbrev_die_table);
+
   build_abbrev_table (die, extern_map);
 
+  optimize_abbrev_table ();
+
   delete extern_map;
 
   /* Initialize the beginning DIE offset - and calculate sizes/offsets.  */
@@ -25720,11 +25948,9 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
   vec_alloc (decl_scope_table, 256);
 
   /* Allocate the initial hunk of the abbrev_die_table.  */
-  abbrev_die_table = ggc_cleared_vec_alloc<dw_die_ref>
-    (ABBREV_DIE_TABLE_INCREMENT);
-  abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
+  vec_alloc (abbrev_die_table, 256);
   /* Zero-th entry is allocated, but unused.  */
-  abbrev_die_table_in_use = 1;
+  abbrev_die_table->quick_push (NULL);
 
   /* Allocate the dwarf_proc_stack_usage_map.  */
   dwarf_proc_stack_usage_map = new hash_map<dw_die_ref, int>;
@@ -28111,7 +28337,7 @@ dwarf2out_finish (const char *)
     output_skeleton_debug_sections (main_comp_unit_die);
 
   /* Output the abbreviation table.  */
-  if (abbrev_die_table_in_use != 1)
+  if (vec_safe_length (abbrev_die_table) != 1)
     {
       switch_to_section (debug_abbrev_section);
       ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
@@ -28334,8 +28560,6 @@ dwarf2out_c_finalize (void)
   tail_call_site_count = -1;
   cached_dw_loc_list_table = NULL;
   abbrev_die_table = NULL;
-  abbrev_die_table_allocated = 0;
-  abbrev_die_table_in_use = 0;
   delete dwarf_proc_stack_usage_map;
   dwarf_proc_stack_usage_map = NULL;
   line_info_label_num = 0;
index abf0550..a0e881a 100644 (file)
@@ -153,7 +153,10 @@ enum dw_val_class
   dw_val_class_vms_delta,
   dw_val_class_high_pc,
   dw_val_class_discr_value,
-  dw_val_class_discr_list
+  dw_val_class_discr_list,
+  dw_val_class_const_implicit,
+  dw_val_class_unsigned_const_implicit,
+  dw_val_class_file_implicit
 };
 
 /* Describe a floating point constant value, or a vector constant value.  */
@@ -198,7 +201,8 @@ struct GTY(()) dw_val_node {
       dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list;
       dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
       HOST_WIDE_INT GTY ((default)) val_int;
-      unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
+      unsigned HOST_WIDE_INT
+       GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
       double_int GTY ((tag ("dw_val_class_const_double"))) val_double;
       wide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide;
       dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec;
@@ -212,6 +216,8 @@ struct GTY(()) dw_val_node {
       char * GTY ((tag ("dw_val_class_lbl_id"))) val_lbl_id;
       unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag;
       struct dwarf_file_data * GTY ((tag ("dw_val_class_file"))) val_file;
+      struct dwarf_file_data *
+       GTY ((tag ("dw_val_class_file_implicit"))) val_file_implicit;
       unsigned char GTY ((tag ("dw_val_class_data8"))) val_data8[8];
       tree GTY ((tag ("dw_val_class_decl_ref"))) val_decl_ref;
       struct dw_val_vms_delta_union