Get __m128 member by index?

I have code originally provided to me by someone working with MSVC, and I'm trying to get it to work on Clang. Here is the function I'm having problems with:

float vectorGetByIndex( __m128 V, unsigned int i ) { assert( i <= 3 ); return V.m128_f32[i]; } 

The error I am getting is as follows:

 Member reference has base type '__m128' is not a structure or union. 

I looked around and found that Clang (and possibly GCC) has a problem handling __m128 as a structure or union. However, I could not find a direct answer on how I can return these values. I tried using the index operator and could not do it, and I looked through the huge list of functions of the embedded SSE and have not yet found a suitable one.

+25
c ++ sse simd intrinsics clang
source share
4 answers

Combining is probably the most portable way:

 union { __m128 v; // SSE 4 x float vector float a[4]; // scalar array of 4 floats } U; float vectorGetByIndex(__m128 V, unsigned int i) { U u; assert(i <= 3); uv = V; return ua[i]; } 
+17
source share

using

 template<unsigned i> float vectorGetByIndex( __m128 V) { union { __m128 v; float a[4]; } converter; converter.v = V; return converter.a[i]; } 

which will work regardless of the available set of commands.

Note. Even if SSE4.1 is available and i pextract is a compile-time constant, you cannot use pextract , etc. Thus, since these instructions extract a 32-bit integer, not a number with a float :

 // broken code starts here template<unsigned i> float vectorGetByIndex( __m128 V) { return _mm_extract_epi32(V, i); } // broken code ends here 

I do not delete this because it is a useful reminder of how not to do things.

+16
source share

As a modification of the hirschhornsalz solution, if i is a compile-time constant, you can completely exclude the join path using shuffle / storage:

 template<unsigned i> float vectorGetByIndex( __m128 V) { #ifdef __SSE4_1__ return _mm_extract_epi32(V, i); #else float ret; // shuffle V so that the element that you want is moved to the least- // significant element of the vector (V[0]) V = _mm_shuffle_ps(V, V, _MM_SHUFFLE(i, i, i, i)); // return the value in V[0] return _mm_cvtss_f32(V); #endif } 
+16
source share

I use

 union vec { __m128 sse, float f[4] }; float accessmember(__m128 v, int index) { vec v.sse = v; return vf[index]; } 

This seems to be very good for me.

+3
source share

All Articles