I'd like to combine two 256 bit vectors (__m256d
) which contain the masks as a result of a comparison-operation (such as _mm256_cmp_pd
) to one 256 bit vector, by omitting the upper half of every 64 bit double.
So, if in the following, a_i, b_i, ...
are 32 bit words, and I have two 256 bit (4 x double) vectors that have the following structure:
a_0, a_0, b_0, b_0, c_0, c_0, d_0, d_0
, and a_1, a_1, b_1, b_1, c_1, c_1, d_1, d_1
.
I'd like to have a single 256 bit vector with the following structure:
a_0, b_0, c_0, d_0, a_1, b_1, c_1, d_1
.
How do I do this efficiently using Intel intrinsics? The instruction set available is everything up to AVX.
It looks like you can exploit the fact that a bit pattern of all 1s is a NaN
in both single and double precision, and similarly a bit pattern of all 0s is a 0.0 in both cases. So to pack your two double mask vectors to a single float vector you can do this:
__m256 v = _mm256_set_m128(_mm256_cvtpd_ps(v0), _mm256_cvtpd_ps(v1));
Note that if you do not have _mm256_set_m128
then you can define it as:
#define _mm256_set_m128(va, vb) \
_mm256_insertf128_ps(_mm256_castps128_ps256(vb), va, 1)
Here's a demo:
#include <stdio.h>
#include <immintrin.h>
#define _mm256_set_m128(va, vb) \
_mm256_insertf128_ps(_mm256_castps128_ps256(vb), va, 1)
static void printvd(const char * label, __m256d v)
{
int64_t a[4];
_mm256_storeu_pd((double *)a, v);
printf("%s = %lld %lld %lld %lld\n", label, a[0], a[1], a[2], a[3]);
}
static void printvf(const char * label, __m256 v)
{
int32_t a[8];
_mm256_storeu_ps((float *)a, v);
printf("%s = %d %d %d %d %d %d %d %d\n", label, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
}
int main()
{
__m256d v0 = _mm256_set_pd(0.0, 1.0, 2.0, 3.0);
__m256d v1 = _mm256_set_pd(3.0, 2.0, 1.0, 0.0);
__m256d vcmp0 = _mm256_cmp_pd(v0, v1, 1);
__m256d vcmp1 = _mm256_cmp_pd(v1, v0, 1);
__m256 vcmp = _mm256_set_m128(_mm256_cvtpd_ps(vcmp0), _mm256_cvtpd_ps(vcmp1));
printvd("vcmp0", vcmp0);
printvd("vcmp1", vcmp1);
printvf("vcmp ", vcmp);
return 0;
}
Test:
$ gcc -Wall -mavx so_avx_test.c && ./a.out
vcmp0 = 0 0 -1 -1
vcmp1 = -1 -1 0 0
vcmp = -1 -1 0 0 0 0 -1 -1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With