Re: Aliasing: reliable code or not?

2006-11-29 Thread Jakub Jelinek
On Tue, Nov 28, 2006 at 11:36:19PM -0800, Ian Lance Taylor wrote:
 Or you can use constructor expressions to make this slightly more
 elegant, though I retain the assumptions about type sizes:
 
 char *foo1(char* buf){
   memcpy(buf, (char[]) { 42 }, 1);
   buf += 1;
   memcpy(buf, (short[]) { 0xfeed }, 2);
   buf += 2;
   memcpy(buf, (int[]) { 0x12345678 }, 4);
   buf += 4;
   memcpy(buf, (int[]) { 0x12345678 }, 4);
   buf += 4;
   return buf;
 }

Or even use mempcpy to make it even more compact:

char *
foo1 (char *buf)
{
  buf = mempcpy (buf, (char[]) { 42 }, 1);
  buf = mempcpy (buf, (short[]) { 0xfeed }, 2);
  buf = mempcpy (buf, (int[]) { 0x12345678 }, 4);
  buf = mempcpy (buf, (int[]) { 0x12345678 }, 4);
  return buf;
}

Jakub


Aliasing: reliable code or not?

2006-11-28 Thread Albert Cahalan

I have code that goes something like this:

char *foo(char *buf){
   *buf++ = 42;
   *((short*)buf) = 0xfeed;
   buf += 2;
   *((int*)buf) = 0x12345678;
   buf += 4;
   *((int*)buf) = 0x12345678;
   buf += 4;
   return buf;
}

The buffer is really of type char. The above comes
from a pile of macros and inline functions (C99 code),
or alternately from a pile of evil C++ templates.

Real C99-compliance would be cute, but then again
the buffer will end up getting executed as x86 code.
Intentionally executing data is surely a standards
violation of the highest order.

I can't afford to just use char to do the writes.
Currently gcc won't merge those into larger writes.
Performance matters.

So, how likely is gcc to do what I obviously want?
It seems to be working right now...

It would be nice to have this documented to work,
just as was done with unions for type punning.
The next best would be a big giant warning and a
work-around that doesn't kill performance.


Re: Aliasing: reliable code or not?

2006-11-28 Thread Andrew Pinski
 
 I have code that goes something like this:
 
 char *foo(char *buf){
 *buf++ = 42;
 *((short*)buf) = 0xfeed;
 buf += 2;
 *((int*)buf) = 0x12345678;
 buf += 4;
 *((int*)buf) = 0x12345678;
 buf += 4;
 return buf;
 }

This does violate C aliasing rules.

Here is how I would write it so you can get the best results:

char *foo(char *buf)
{
  short temp;
  int temp1;
  *buf++=42;
  temp = 0xfeed;
  memcpy(buf, temp, sizeof(temp));
  buf+=sizeof(temp);
  temp1 = 0x12345678;
  memcpy(buf, temp1, sizeof(temp1));
  buf+=sizeof(temp1);
  temp1 = 0x12345678;
  memcpy(buf, temp1, sizeof(temp1));
  buf+=sizeof(temp1);
  return buf;
}

As using memcpy does not cause a violation of the aliasing rules.

And does the correct thing:
lis 11,0x1234
li 0,42
li 9,-275
ori 11,11,22136
stb 0,0(3)
sth 9,1(3)
stw 11,7(3)
stw 11,3(3)
addi 3,3,11


-- Pinski


Re: Aliasing: reliable code or not?

2006-11-28 Thread Ian Lance Taylor
Andrew Pinski [EMAIL PROTECTED] writes:

 Here is how I would write it so you can get the best results:
 
 char *foo(char *buf)
 {
   short temp;
   int temp1;
   *buf++=42;
   temp = 0xfeed;
   memcpy(buf, temp, sizeof(temp));
   buf+=sizeof(temp);
   temp1 = 0x12345678;
   memcpy(buf, temp1, sizeof(temp1));
   buf+=sizeof(temp1);
   temp1 = 0x12345678;
   memcpy(buf, temp1, sizeof(temp1));
   buf+=sizeof(temp1);
   return buf;
 }

Or you can use constructor expressions to make this slightly more
elegant, though I retain the assumptions about type sizes:

char *foo1(char* buf){
  memcpy(buf, (char[]) { 42 }, 1);
  buf += 1;
  memcpy(buf, (short[]) { 0xfeed }, 2);
  buf += 2;
  memcpy(buf, (int[]) { 0x12345678 }, 4);
  buf += 4;
  memcpy(buf, (int[]) { 0x12345678 }, 4);
  buf += 4;
  return buf;
}

Ian