std::vector move assign patch
François Dumont
frs.dumont@gmail.com
Wed Apr 26 19:35:00 GMT 2017
I plan to propose this patch when back to stage 1. As it defaults
default and move constructor I wonder if it can make any change to the
generated code.
François
On 25/04/2017 23:02, Marc Glisse wrote:
> On Tue, 25 Apr 2017, Jonathan Wakely wrote:
>
>>>>> That's only 5 more memory operations. If I tweak vector swapping
>>>>> to avoid calling swap on each member (which drops type-based
>>>>> aliasing information, that was the topic of PR64601)
>>>>
>>>> I didn't really understand the discussion in the PR. I find that's
>>>> true of most TBAA discussions.
>>>>
>>>> std::swap(T& x, T& y) is hard to optimise because we don't know that
>>>> the dynamic type of the thing at &x is the same type as T?
>>>
>>> std::swap<int*> only knows that it is dealing with pointers to
>>> integers, so _M_start from one vector might be in the same location
>>> as _M_finish from some other vector...
>>>
>>> When I access __x._M_start directly, I am accessing some part of a
>>> _Vector_impl, and 2 _Vector_impl can only be the same or disjoint,
>>> they cannot partially overlap.
>>
>> I see. I'm surprised that after the std::swap calls get inlined, so
>> that the references can be "seen through", the pessimisation is still
>> present.
>
> (this is my understanding of how compilers handle TBAA)
>
> The only things that carry information are the declaration of an
> object, and accesses (read/write). Pointers and references are
> meaningless until the object is accessed, they are just a fancy way to
> do pointer arithmetic, and the way the object is accessed carries the
> whole information. If I have a reference p to std::pair<int,int>,
> p.first=42 or x=p.first access the first element of a pair, while
> *&p.first=42 or x=*&p.first are only accesses to an int. p.first and
> q.second cannot alias, while *&p.first and *&q.second can.
>
> In other words
> illegal: ((std::pair<int,int>*)&p.second)->first=2
> allowed: *(int*)&((std::pair<int,int>*)&p.second)->first=2
> because there is no actual access through the "wrong" pointers (I
> added a redundant cast to int* to try and clarify the difference).
>
> (actually, gcc wrongly optimizes *&x to x so you need to use an
> intermediate variable to notice this: auto y=&x; ... *y ... while
> clang is stricter)
>
> I think this is horrible but that's not a fight I feel capable of
> leading.
>
> If what I said is too hard to understand, it is fine to ignore. And if
> it is wrong, I'll be happy to learn that :-)
>
>>> By the way, do we have a policy on writing if(p)delete p; vs
>>> directly delete p; which does nothing for p==0? There are cases
>>> where the extra shortcut is a nice optimization, others where it is
>>> redundant work. At -Os, the middle-end could optimize if(p)free(p)
>>> to free(p) in the future.
>>
>> No official policy. I always consider the if (p) to be redundant
>> noise, but that's based on readability and correctness, not
>> performance.
>
> I was going to say we have that in std::vector's destructor, but
> allocators do not have the same property as free/delete, deallocate
> can only be called with something allocate returned, not 0. So we
> don't have a choice.
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: stl_vector.h.patch
Type: text/x-patch
Size: 3976 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/libstdc++/attachments/20170426/fdcb826f/attachment.bin>
More information about the Libstdc++
mailing list