随机播放 AVX 寄存器中的元素
Shuffle elements in AVX register
我有一个双精度向量存储在一个 AVX 寄存器中,其元素为 {a0,a1,a2,a3}
。现在,我想制作三个新向量(也应存储为 __m256d
变量),比方说 b、c 和 d,包含以下元素:
b = {a0,a1,a0,a0}
c = {a1,a2,a2,a1}
d = {a2,a3,a3,a2}
如何使用 AVX 执行此操作?
看看编译器是如何做到的,对 -march=core-avx2
使用 gcc
向量扩展
#include <stdint.h>
typedef double v4df __attribute__((vector_size(32)));
typedef uint64_t v4u64 __attribute__((vector_size(32)));
void foo(v4df a, v4df *b, v4df *c, v4df *d)
{
*b = __builtin_shuffle(a, (v4u64){0, 1, 0, 0});
*c = __builtin_shuffle(a, (v4u64){1, 2, 2, 1});
*d = __builtin_shuffle(a, (v4u64){2, 3, 3, 2});
}
gcc-4.8.4 -march=core-avx2 -O3 产生:
vpermpd , %ymm0, %ymm1
vmovapd %ymm1, (%rdi)
vpermpd 5, %ymm0, %ymm1
vpermpd 0, %ymm0, %ymm0
vmovapd %ymm1, (%rsi)
vmovapd %ymm0, (%rdx)
vzeroupper
ret
gcc-4.8.4 -march=corei7-avx -O3 产生:
vinsertf128 , %xmm0, %ymm0, %ymm1
vpermilpd , %ymm1, %ymm1
vmovapd %ymm1, (%rdi)
vperm2f128 , %ymm0, %ymm0, %ymm1
vshufpd , %ymm1, %ymm0, %ymm1
vmovapd %ymm1, (%rsi)
vperm2f128 , %ymm0, %ymm0, %ymm0
vpermilpd , %ymm0, %ymm0
vmovapd %ymm0, (%rdx)
vzeroupper
ret
我有一个双精度向量存储在一个 AVX 寄存器中,其元素为 {a0,a1,a2,a3}
。现在,我想制作三个新向量(也应存储为 __m256d
变量),比方说 b、c 和 d,包含以下元素:
b = {a0,a1,a0,a0}
c = {a1,a2,a2,a1}
d = {a2,a3,a3,a2}
如何使用 AVX 执行此操作?
看看编译器是如何做到的,对 -march=core-avx2
gcc
向量扩展
#include <stdint.h>
typedef double v4df __attribute__((vector_size(32)));
typedef uint64_t v4u64 __attribute__((vector_size(32)));
void foo(v4df a, v4df *b, v4df *c, v4df *d)
{
*b = __builtin_shuffle(a, (v4u64){0, 1, 0, 0});
*c = __builtin_shuffle(a, (v4u64){1, 2, 2, 1});
*d = __builtin_shuffle(a, (v4u64){2, 3, 3, 2});
}
gcc-4.8.4 -march=core-avx2 -O3 产生:
vpermpd , %ymm0, %ymm1
vmovapd %ymm1, (%rdi)
vpermpd 5, %ymm0, %ymm1
vpermpd 0, %ymm0, %ymm0
vmovapd %ymm1, (%rsi)
vmovapd %ymm0, (%rdx)
vzeroupper
ret
gcc-4.8.4 -march=corei7-avx -O3 产生:
vinsertf128 , %xmm0, %ymm0, %ymm1
vpermilpd , %ymm1, %ymm1
vmovapd %ymm1, (%rdi)
vperm2f128 , %ymm0, %ymm0, %ymm1
vshufpd , %ymm1, %ymm0, %ymm1
vmovapd %ymm1, (%rsi)
vperm2f128 , %ymm0, %ymm0, %ymm0
vpermilpd , %ymm0, %ymm0
vmovapd %ymm0, (%rdx)
vzeroupper
ret