OK.

On Thu, Nov 3, 2016 at 12:42 PM, Jakub Jelinek <ja...@redhat.com> wrote:
> Hi!
>
> My recent optimize_abbrev_table optimization apparently broke Solaris
> bootstrap.
> The bug is specific I think just to -gdwarf-{2,3} -gno-strict-dwarf, where
> DW_FORM_exprloc can't be used for location expressions and some location
> expression contains DW_OP_GNU_{{const,regval,deref}_type,convert,reinterpret}
> and there are at least 128 die abbreviations used by more than one DIE.
> Because of the lack of DW_FORM_exprloc we need to decide on
> DW_FORM_block{1,2,4} and size the location expression, for that we need to 
> know
> the DIE offsets of base offset DIEs that are referenced (earlier code
> ensures such types appear very early in the CU, right after the
> DW_TAG_compile_unit DIE) and for that their size and their abbreviation values
> need to be constant, so the optimize_abbrev_table opts that reorder 
> abbreviation
> numbers by decreasing usage count or for -gdwarf-5 attempt to optimize 
> implicit
> constants can't be done for the CU and base types.
> For -gdwarf-4 and above, we can emit DW_FORM_exprloc, so value_format doesn't
> need to compute any sizes and thus calc_base_type_die_sizes shouldn't be
> called.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux and Rainer has kindly
> tested it on Solaris, ok for trunk?
>
> 2016-11-03  Jakub Jelinek  <ja...@redhat.com>
>
>         * dwarf2out.c (size_of_discr_list): Fix typo in function comment.
>
>         PR debug/78191
>         * dwarf2out.c (abbrev_opt_base_type_end): New variable.
>         (die_abbrev_cmp): Sort dies with die_abbrev smaller than
>         abbrev_opt_base_type_end only by increasing die_abbrev, before
>         any other dies.
>         (optimize_abbrev_table): Don't change abbrev numbers of
>         base types and CU or optimize implicit consts in them if
>         calc_base_type_die_sizes has been called during build_abbrev_table.
>         (calc_base_type_die_sizes): If abbrev_opt_start, set
>         abbrev_opt_base_type_end to one plus largest base type's
>         die_abbrev.
>
> --- gcc/dwarf2out.c.jj  2016-11-03 08:47:59.000000000 +0100
> +++ gcc/dwarf2out.c     2016-11-03 12:26:03.192459170 +0100
> @@ -1909,7 +1909,7 @@ size_of_discr_value (dw_discr_value *dis
>      return size_of_sleb128 (discr_value->v.sval);
>  }
>
> -/* Return the size of the value in a DW_discr_list attribute.  */
> +/* Return the size of the value in a DW_AT_discr_list attribute.  */
>
>  static int
>  size_of_discr_list (dw_discr_list_ref discr_list)
> @@ -8548,6 +8548,11 @@ optimize_external_refs (dw_die_ref die)
>  /* First abbrev_id that can be optimized based on usage.  */
>  static unsigned int abbrev_opt_start;
>
> +/* Maximum abbrev_id of a base type plus one (we can't optimize DIEs with
> +   abbrev_id smaller than this, because they must be already sized
> +   during build_abbrev_table).  */
> +static unsigned int abbrev_opt_base_type_end;
> +
>  /* Vector of usage counts during build_abbrev_table.  Indexed by
>     abbrev_id - abbrev_opt_start.  */
>  static vec<unsigned int> abbrev_usage_count;
> @@ -8646,12 +8651,16 @@ die_abbrev_cmp (const void *p1, const vo
>    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;
> +  if (die1->die_abbrev >= abbrev_opt_base_type_end
> +      && die2->die_abbrev >= abbrev_opt_base_type_end)
> +    {
> +      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)
> @@ -8729,10 +8738,12 @@ optimize_abbrev_table (void)
>        sorted_abbrev_dies.qsort (die_abbrev_cmp);
>
>        unsigned int abbrev_id = abbrev_opt_start - 1;
> -      unsigned int first_id = 0;
> +      unsigned int first_id = ~0U;
>        unsigned int last_abbrev_id = 0;
>        unsigned int i;
>        dw_die_ref die;
> +      if (abbrev_opt_base_type_end > abbrev_opt_start)
> +       abbrev_id = abbrev_opt_base_type_end - 1;
>        /* 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)
> @@ -8740,10 +8751,15 @@ optimize_abbrev_table (void)
>           dw_attr_node *a;
>           unsigned ix;
>
> +         /* If calc_base_type_die_sizes has been called, the CU and
> +            base types after it can't be optimized, because we've already
> +            calculated their DIE offsets.  We've sorted them first.  */
> +         if (die->die_abbrev < abbrev_opt_base_type_end)
> +           continue;
>           if (die->die_abbrev != last_abbrev_id)
>             {
>               last_abbrev_id = die->die_abbrev;
> -             if (dwarf_version >= 5 && i)
> +             if (dwarf_version >= 5 && first_id != ~0U)
>                 optimize_implicit_const (first_id, i, implicit_consts);
>               abbrev_id++;
>               (*abbrev_die_table)[abbrev_id] = die;
> @@ -8783,11 +8799,12 @@ optimize_abbrev_table (void)
>           die->die_abbrev = abbrev_id;
>         }
>        gcc_assert (abbrev_id == vec_safe_length (abbrev_die_table) - 1);
> -      if (dwarf_version >= 5)
> +      if (dwarf_version >= 5 && first_id != ~0U)
>         optimize_implicit_const (first_id, i, implicit_consts);
>      }
>
>    abbrev_opt_start = 0;
> +  abbrev_opt_base_type_end = 0;
>    abbrev_usage_count.release ();
>    sorted_abbrev_dies.release ();
>  }
> @@ -9041,6 +9058,9 @@ calc_base_type_die_sizes (void)
>                   && base_type->die_abbrev);
>        prev = base_type;
>  #endif
> +      if (abbrev_opt_start
> +         && base_type->die_abbrev >= abbrev_opt_base_type_end)
> +       abbrev_opt_base_type_end = base_type->die_abbrev + 1;
>        base_type->die_offset = die_offset;
>        die_offset += size_of_die (base_type);
>      }
>
>
>         Jakub

Reply via email to