> > So I think all we can hope for is merging memcpy with the extra write of 0. > > That's not actually clear. > > It would be reasonable to assume that foo isn't likely to change the string > and have the inlined destructor for a string that was initialized as a short > string like here do something like > > if (stuff_got_changed) [[unlikely]] > obj.noninlined_full_destructor(); > > That would still work if someone were to naughtily cast away the "const", but > they would pay the price in the form of two jumps and the function call.
Using const as a hint is an interesting idea which did not come to my mind. Sadly I do not see how to fit it into the optimization pipeline. We first do early inlining (essentially intra-module inlining for size) followed by early optimizations (basic cleanup of the code). Then profile is constructed and inter-procedural optimizations starts. Interesting inlining happens in inter-procedural inlining and thus at the profile construction time we do not yeat know what the constructor and destructor is doing, so we do not know it has likely hot path. Moreover the destruction is now: _48 = D.35539._M_dataplus._M_p; if (&D.35539.D.25336._M_local_buf == _48) goto <bb 8>; [18.09%] else goto <bb 7>; [81.91%] <bb 7> [local count: 879501928]: _50 = D.35539.D.25336._M_allocated_capacity; _51 = _50 + 1; operator delete (_48, _51); Which is essentially one if (that would need to stay to test if something changed) and a call. Only what we could save is computing the string size which we could save anyway by calling variant of delete with unknown size...