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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
           Keywords|                            |missed-optimization
                 CC|                            |jwakely.gcc at gmail dot com
   Last reconfirmed|                            |2023-03-31
             Status|UNCONFIRMED                 |NEW

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
<bb 8> [local count: 86938296]:
D.70713 ={v} {CLOBBER(eol)};
_74 = v1.D.60930._M_impl.D.60395._M_start.D.16824._M_p;
_638 = (long int) _74;
_261 = -_638;
_383 = (long unsigned int) _261;
if (_638 < -8)
  goto <bb 11>; [90.00%]
else
  goto <bb 12>; [10.00%]

<bb 11> [local count: 78244465]:
__builtin_memmove (_216, _74, _383);

so _383 is > 8, the reported access size looks good here.  We determine
the destination size as 8 which is also good since

_216 = operator new (8);

so the diagnostic seems legit.  The alternative code taken isn't very much
better:

<bb 12> [local count: 8693830]:
if (_74 == -8B)
  goto <bb 13>; [34.00%]
else
  goto <bb 14>; [66.00%]

<bb 13> [local count: 2955901]:
_266 = MEM[(long unsigned int *)-8B];
*_216 = _266;

<bb 14> [local count: 86938296]:
_268 = _216 + _383;
_324 = MEM[(_Bit_type *)_268];
_327 = _324 & 18446744073709551614;

so definitely bb13 looks to be better unreachable as well.

I have difficulties in tracing libstdc++ back to the ultimate caller but
the above control flow is from stl_algobase.h:435 which is

  template<bool _IsMove>
    struct __copy_move<_IsMove, true, random_access_iterator_tag>
    {
      template<typename _Tp, typename _Up>
        _GLIBCXX20_CONSTEXPR
        static _Up* 
        __copy_m(_Tp* __first, _Tp* __last, _Up* __result) 
        {
          const ptrdiff_t _Num = __last - __first;
          if (__builtin_expect(_Num > 1, true)) 
            __builtin_memmove(__result, __first, sizeof(_Tp) * _Num);
          else if (_Num == 1) 
            std::__copy_move<_IsMove, false, random_access_iterator_tag>::
              __assign_one(__result, __first);
          return __result + _Num; 
        }
    };

but the assign-one seems to be odd.  So I suppose this all happens before

   v1.push_back(T());

and thus _Num == 0.

v1.D.60930._M_impl.D.60395._M_start.D.16824._M_p is probably NULL at this
point but 'v1' escapes to _M_deallocate so the intervening
operator new calls and an __atomic_load_1 / __cxa_guard_acquire prevent
CSE of this value.

It might be possible (again) to CSE this manually in libstdc++ to help
code generation.

Reply via email to