On Fri, 21 Oct 2011 21:11:16 +0200, Jakub Jelinek wrote:
> Well, you calculate the sizes multiple times anyway, so I don't see why you
> during the size calculations you couldn't start with DW_FORM_ref_udata
> as first guess and compute on the side also total sizes of those
> DW_FORM_ref_udata bytes and use that number plus the guessed length
> of the whole CU to decide if replacing all DW_FORM_ref_udata with
> DW_FORM_ref{1,2,4} wouldn't be beneficial.

The optimal sizes are:
        value less than 1 <<  8: DW_FORM_ref1
        value less than 1 << 16: DW_FORM_ref2
        value less than 1 << 21: DW_FORM_ref_udata
        value less than 1 << 32: DW_FORM_ref4

One would have to decide each size specifically if it isn't worth to use the
larger size for the few instances.  It could be done, just the gain is not
expected (not measured) big against DW_FORM_ref_udata.  The currently
suboptimal ranges are:
        (1 <<  7) <= value < (1 <<  8)
        (1 << 14) <= value < (1 << 16)
        (1 << 28) <= value

This suboptimal loss is at most 9316 bytes = 0.177% of .debug size but it will
be less as I do not calculate here with the abbrevs multiplication at all:
        readelf -wi libstdc++.so|perl -nle 'next if 
!/^.*<(0x[0-9a-f]+)>.*$/;$x=eval $1;$b++ if 
(1<<7)<=$x&&$x<(1<<8)||(1<<14)<=$x&&$x<(1<<16)||(1<<28)<=$x;END{print $b;}'
        9316

IMHO it is not worth it.

Also this problem is already present there.  The following code may enlarge the
output in specific cases due to duplication of the abbrev definitions:
  /* If the string is shorter or equal to the size of the reference, it is
     always better to put it inline.  */
     ^^^^^^ = not always
  if (len <= DWARF_OFFSET_SIZE || node->refcount == 0)
    return node->form = DW_FORM_string;

This patch has a size regression for DIE_OFFSETs larger than 1 << 28 = 256MB
when DW_FORM_ref_udata becomes 5 bytes while DW_FORM_ref4 was 4 bytes.
Still I do not think it needs to care about optimal output for a single CU of
size larger than 256MB.


> > +  /* The DIE sizes can increase, due to DW_FORM_ref_udata size increase
> > +     dependent on increases of other DIE_OFFSETs.  */
> > +  do
> > +    {
> > +      /* Initialize the beginning DIE offset - and calculate 
> > sizes/offsets.  */
> > +      next_die_offset = init_die_offset;
> > +      calc_die_sizes_change = false;
> > +      calc_die_sizes (die);
> > +    }
> > +  while (calc_die_sizes_change);
> 
> loop guaranteed to terminate?  If the CU is either only growing or only
> shrinking then it hopefully should, but it would be nice to assert that.
> For references to DIEs with lower offsets you start with a roughly correct
> guess, for references to DIEs with higher offsets you start with 0 and then
> just keep growing?

Yes.  The initial DIE_OFFSETs are 0, therefore their sizeof(uleb128) is 1.
As I assume
        VAL1 <= VAL2 implicates sizeof (uleb128 (VAL1)) <= sizeof (uleb128 
(VAL2))

there must be valid on each calc_die_sizes call the updated assertion:
        gcc_assert ((unsigned long int) die->die_offset <= next_die_offset);

I do not see anything could shrink anywhere.


Thanks,
Jan

Reply via email to