is -O2 breaking sse2 alignment?
JP Fournier
jape41@gmail.com
Fri Mar 14 00:13:00 GMT 2008
Brian Dessent wrote:
>
> You're violates the C aliasing rules. You can't store through a casted
> pointer like that. You also don't have to do the load/store, the
> compiler know what you want when you use a union instead:
>
> union { __m128i v; long l[2]; } a, b, c;
>
> a.l[0] = a.l[1] = 1;
> b.l[0] = b.l[1] = 1;
>
> c.v = _mm_add_epi8 (a.v, b.v);
> printf("c0=%ld c1=%ld\n", c.l[0], c.l[1]);
Many Thanks Brian. My little program now behaves better:
bash-3.1$ gcc -O2 -msse2 -o sse2 sse2-1.c
bash-3.1$ ./sse2
c0=2 c1=2
#include <stdio.h>
#include <emmintrin.h>
void test_int() {
union { __m128i v; long l[2]; } a, b, c;
a.l[0] = a.l[1] = 1;
b.l[0] = b.l[1] = 1;
c.l[0] = c.l[1] = 0;
c.v = _mm_add_epi8( a.v, b.v );
printf("c0=%ld c1=%ld\n", c.l[0], c.l[1] );
}
int main( int count, char ** args ) {
test_int();
return 0;
}
>
> There's an even more natural way to do this though using gcc's built-in
> vector extensions without any of the Intel mmintrin.h stuff. This way
> will result in code that will vectorize to altivec, sse2, spu, whatever
> the machine supports, it's not hardware specific:
>
> typedef int v4si __attribute__ ((vector_size (16)));
>
> v4si a = { 1, 2, 3, 4 }, b = { 5, 6, 7, 8 }, c;
>
> c = a + b;
>
> You can use all the normal C operators like + and * as if they were
> scalars but they will be compiled using the corresponding SIMD
> instructions. See
> <http://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html> for more. If
> you want access to the individual parts you can again use the union,
My thinking is that I'd like try to be compiler independent, so by using
the intel intrinsics I figure I should be able to get gcc and the intel
compiler to work as a start.
What I am _really_ trying to do is to implement is the addition of
elements of two arrays.
Is there a more efficient way of doing this than this way?:
#include <stdio.h>
#include <emmintrin.h>
void test_add_long(long * result, long * a, long * b, long size) {
union { __m128i v; long l[2]; } temp1, temp2, temp3;
int index=0;
for( index=0; index < size; index+=2 ) {
temp1.l[0] = a[index];
temp1.l[1] = a[index+1];
temp2.l[0] = b[index];
temp2.l[1] = b[index + 1];
temp3.v = _mm_add_epi8( temp1.v, temp2.v );
result[index] = temp3.l[0];
result[index+1] = temp3.l[1];
printf("c0=%ld c1=%ld\n", result[index], result[index+1] );
}
}
int main( int count, char ** args ) {
// array of 4 8 byte ints
long a[] = { 1, 2, 3, 4};
long b[] = { 1, 2, 3, 4};
long result[] = {0,0,0,0};
test_add_long(result, a, b, 4);
return 0;
}
More information about the Gcc-help
mailing list