[PATCH] Fix the one entry mem{{,p}cpy,move,set} optimization aliasing issues (PR middle-end/29272)

Mike Stump mrs@apple.com
Sat Sep 30 00:21:00 GMT 2006


On Sep 29, 2006, at 10:42 AM, Mark Mitchell wrote:
> In C++, placement new makes things even more complicated, as things  
> like:
>
>   buf = new char[4096];
>   s = new (buf) S();
>   s->~S();
>   t = new (buf) T();

Actually, it is worse:

char b[4096];
int *ip = b;

ip += 16
p &= ~15;

foo(*(float*)ip)

Starts the lifetime of a float object, without the placement  
operator.  We can so start the lifetime of any object with a trivial  
constructor as well.  We don't need a placement operator to so start  
the lifetime.

int i, j, k;
*(float *)&i = 4.3;
*(flloat *)&j = *(float*)&i;

mempcy (&k, &j, 4)

here, memcpy doesn't copy an int, but rather a float (in C++).  The  
dynamic type is a runtime property in C++, and C++ is what our  
understanding of the C rules are, if they had been written down and  
made sense.

If one might have had an int in i, then the memcpy would also alias  
ints.  If there is no way it could have had an int, then it would be  
fine to just treat it as a float.  Compare:

{
   int i, j, k;

   i = 12;

   if (random()) {
     *(float *)&i = 4.3;
     *(flloat *)&j = *(float*)&i;
   }

   mempcy (&k, &j, 4);
}

Here, the alias set would be int|float, if you wanted to optimize  
aggressively.

> I think the best way to handle this is conservatively: use alias  
> set zero for all reads/writes from things like memcpy, so that we  
> don't create any no-aliasing expectations in the compiler.

Kinda agree.  I'm all for optimization people taking things to the  
limit, but I'd rather have them understand the language rules first.   
One can add additional things, but you have to be very, very  
careful.  If something is later read as a float, then the previous  
store can be promoted to a float store, or if something is stored as  
a float, than the later read can be thought of as a float read.

> I think that trying to get clever about the effective types here is  
> likely to break code, and I'm not at all confident that the rules  
> in the standard are even self-consistent.

The C++ rules should be well thought out and correct.  I'll note,  
they are slightly different from the C rules.  For example, the  
effective type in C of int i, is always int.  In C++, the dynamic  
type isn't always int.

I think the reasoning to be used (C++ rules) for the PR is that the  
value stored when we do:

   __builtin_memcpy (&node->next, &pool, sizeof(struct Node*));

is of type character (conservatively), or, if we want to optimize,  
the type read from that location when it is next accessed.  That type  
in the program is int, not Node*.  If the alias set had been int, 0  
would not have been returned.



More information about the Gcc-patches mailing list