https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71002

--- Comment #6 from rguenther at suse dot de <rguenther at suse dot de> ---
On Mon, 9 May 2016, tavianator at gmail dot com wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71002
> 
> --- Comment #5 from Tavian Barnes <tavianator at gmail dot com> ---
> > But if it is not POD then assuming it gets copied correctly when
> > init-constructing a POD union where they placed such object is
> > an interesting assumption...
> 
> Hrm?  They seem to always copy it manually with long_t's copy constructor:
> 
> ::new(&m_repr.long_repr()) long_t(other.m_repr.long_repr());

I stand corrected.  At least they always read from short_t when
computing is_short() even if that is not the active union member.

Some missed optimizations:

foo::foo(string) (struct foo * const this, struct string & restrict str)
{
...
  <bb 2>:
  MEM[(struct short_t &)this_2(D)].h.is_short = 1;
  MEM[(struct short_t &)this_2(D)].h.length = 0;
  MEM[(struct short_t &)this_2(D)].data[0] = 0;
  _19 = BIT_FIELD_REF <MEM[(const struct string *)this_2(D)], 8, 0>;
  _20 = _19 & 1;
  if (_20 != 0)

this is fold-const.c at work replacing the load from h.is_short
with the BIT_FIELD_REF.

But then we go to

        short_t short_backup(m_repr.short_repr());
        m_repr.short_repr().~short_t();
        ::new(&m_repr.long_repr()) long_t(other.m_repr.long_repr());
        other.m_repr.long_repr().~long_t();
        ::new(&other.m_repr.short_repr()) short_t(short_backup);

  <bb 5>:
  short_backup = MEM[(const struct short_t &)this_2(D)];
  MEM[(struct long_t *)this_2(D)] = MEM[(const struct long_t *)str_5(D)];
  MEM[(struct short_t *)str_5(D)] = short_backup;
  short_backup ={v} {CLOBBER};
  goto <bb 11>;

which looks good.  But

  <bb 11>:
  # prephitmp_52 = PHI <_51(10), 0(5)>
  goto <bb 13>;

  <bb 13>:
  # iftmp.7_13 = PHI <prephitmp_52(11), _12(12)>
  *this_2(D).m_len = iftmp.7_13;

stores zero into the length field.  Somehow PRE does this transform.

I'll investigate some more.

Reply via email to