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.