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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |missed-optimization
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2016-12-06
                 CC|                            |jamborm at gcc dot gnu.org,
                   |                            |rguenth at gcc dot gnu.org
     Ever confirmed|0                           |1

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
Trunk rejects it with (might be worth another bug?)

t.C: In function ‘ref_proxy<qual_option, inplace_ref<qual_option> >
make_object_4(ref_proxy<option_2, variant_ref<option_1, option_2> >&&)’:
t.C:469:39: error: conversion from ‘inplace_ref<qual_option>’ to
‘ref_proxy<qual_option, inplace_ref<qual_option> >’ is ambiguous
     return make_object_3(std::move(a0));
                                       ^
t.C:394:8: note: candidate: constexpr
inplace_ref<qual_option>::inplace_ref(const inplace_ref<qual_option>&)
 struct inplace_ref
        ^~~~~~~~~~~
t.C:380:17: note:   inherited here
     using Base::Base;
                 ^~~~
t.C:394:8: note: candidate: constexpr
inplace_ref<qual_option>::inplace_ref(inplace_ref<qual_option>&&)
 struct inplace_ref
        ^~~~~~~~~~~
t.C:380:17: note:   inherited here
     using Base::Base;
                 ^~~~
t.C:387:5: note: candidate: ref_proxy<T, Base>::ref_proxy(Base) [with T =
qual_option; Base = inplace_ref<qual_option>]
     ref_proxy(Base ptr)
     ^~~~~~~~~


Confirmed with GCC 6.2 - we have quite many aggregate temporaries not optimized
away:

__attribute__((noinline))
ref_proxy<qual_option, inplace_ref<qual_option> > f() ()
{
  struct qual_optionD.34988 D.41115;
  struct ref_proxyD.34990 D.41114;
  struct qual_optionD.34988 innerD.41113;
  struct ref_proxyD.34990 typeD.41111;
  struct ref_proxyD.34990 typeD.41112;
  struct ref_proxyD.36874 D.41109;
  struct ref_proxyD.36874 ptrD.41110;
  struct inplace_refD.37561 D.41107;
  struct inplace_refD.37561 ptrD.41106;

  <bb 2>:
  MEM[(struct ref_proxyD.36874 *)&D.41109 + 40B] = 2;
  ptrD.41110 = D.41109;
  MEM[(struct  &)&D.41114] ={v} {CLOBBER};
  MEM[(struct variantD.35001 *)&ptrD.41110 + 40B] = 2;
  MEM[(struct variant_refD.34986 *)&D.41114].inner_storage_D.35021 =
ptrD.41110.D.36914.inner_storage_D.35021;
  MEM[(struct ref_proxyD.34990 *)&D.41114 + 40B] = 2;
  typeD.41111 = D.41114;
  MEM[(struct ref_proxyD.34990 *)&typeD.41111 + 40B] = 2;
  typeD.41112 = typeD.41111;
  MEM[(struct  &)&D.41115] ={v} {CLOBBER};
  MEM[(struct ref_proxyD.34990 *)&typeD.41112 + 40B] = 2;
  D.41115.type_D.36509 = typeD.41112;
  MEM[(struct qual_optionD.34988 *)&D.41115 + 40B] = 2;
  MEM[(struct qual_optionD.34988 *)&D.41115 + 48B] = 0;
  innerD.41113 = D.41115;
  MEM[(struct  &)&D.41107] ={v} {CLOBBER};
  MEM[(struct qual_optionD.34988 *)&innerD.41113 + 48B] = 0;
  D.41107.inner_D.37568 = innerD.41113;
  D.41115 ={v} {CLOBBER};
  D.41114 ={v} {CLOBBER};
  MEM[(struct inplace_refD.37561 *)&D.41107 + 48B] = 0;
  ptrD.41106 = D.41107;
  MEM[(struct  &)&<retval>] ={v} {CLOBBER};
  MEM[(struct inplace_refD.37561 *)&ptrD.41106 + 48B] = 0;
  <retval>.D.37651 = ptrD.41106;
  return <retval>;

}

it usually is SRAs job to do this but it seems to fail in this case:

  <bb 2>:
  MEM[(struct  &)&D.37695] ={v} {CLOBBER};
  SR.31_24 = 2;
  MEM[(struct ref_proxyD.36874 *)&D.41109 + 40B] = SR.31_24;
  SR.34_26 = SR.31_24;
  MEM[(struct ref_proxyD.36874 *)&D.41109 + 40B] = SR.34_26;
  ptrD.41110 = D.41109;
^^^ aggregate copy not scalarized
  ptr$D36914$inner_storage_$_storage$_which_28 = SR.34_26;
  MEM[(struct  &)&D.41114] ={v} {CLOBBER};
  MEM[(struct variantD.35001 *)&ptrD.41110 + 40B] =
ptr$D36914$inner_storage_$_storage$_which_28;

in fact ptrD.41110 is not scalarized at all.  Looks like the init from D.41109
makes us fail here.

Martin?

Reply via email to