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