This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]