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.