c++ clang sse simd intrinsics

c++ - ¿Obtener miembro de__m128 por índice?



clang sse (4)

Como una modificación de la solución de hirschhornsalz, si i es una constante de tiempo de compilación, podría evitar la ruta de la unión por completo utilizando una aleatoria / tienda:

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 }

Tengo un código, originalmente dado por alguien que trabaja con MSVC, y estoy tratando de que funcione en Clang. Aquí está la función con la que estoy teniendo problemas:

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

El error que recibo es el siguiente:

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

Miré a mi alrededor y descubrí que Clang (y quizás GCC) tiene un problema con el tratamiento de __m128 como una estructura o unión. Sin embargo, no he logrado encontrar una respuesta directa sobre cómo puedo recuperar estos valores. He intentado usar el operador de subíndices y no pude hacer eso, y he echado un vistazo a la enorme lista de funciones intrínsecas SSE y todavía no he encontrado una adecuada.


Incluso si SSE4.1 está disponible y i es una constante de tiempo de compilación, no puede usar pextract etc. de esta manera:

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

No lo borro porque es un recordatorio útil de cómo no hacer las cosas y dejar que sea una humillación pública.

Mejor uso

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

que funcionará independientemente del conjunto de instrucciones disponibles.


La forma en que uso es

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

Parece que funciona bastante bien para mí.


Una unión es probablemente la forma más portátil de hacer esto:

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); u.v = V; return u.a[i]; }