使用__m128i*
从的int
阵列装入因为__m128
类型被定义为允许混叠是安全的。 (例如,在海湾合作委员会的标题中,定义包括__attribute__((may_alias))
。)
反向不是安全。它可能碰巧在大多数情况下工作,但为什么冒这个险呢?
(uint32_t*) &my_vector
违反C和C++别名规则,并且不保证以您期望的方式工作。存储到本地阵列,然后访问它保证是安全的。它甚至可以优化大多数编译器,例如,您可以直接从xmm获取movq
/pextrq
到整数寄存器,而不是实际的存储/重载。
Source + asm output on the Godbolt compiler explorer:证明它用MSVC编译等等。
#include <immintrin.h>
#include <stdint.h>
#include <stdio.h>
#ifndef __cplusplus
#include <stdalign.h> // C11 defines _Alignas(). This header defines alignas()
#endif
void p128_hex_u8(__m128i in) {
alignas(16) uint8_t v[16];
_mm_store_si128((__m128i*)v, in);
printf("v16_u8: %x %x %x %x | %x %x %x %x | %x %x %x %x | %x %x %x %x\n",
v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7],
v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]);
}
void p128_hex_u16(__m128i in) {
alignas(16) uint16_t v[8];
_mm_store_si128((__m128i*)v, in);
printf("v8_u16: %x %x %x %x, %x %x %x %x\n", v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
}
void p128_hex_u32(__m128i in) {
alignas(16) uint32_t v[4];
_mm_store_si128((__m128i*)v, in);
printf("v4_u32: %x %x %x %x\n", v[0], v[1], v[2], v[3]);
}
void p128_hex_u64(__m128i in) {
alignas(16) long long v[2]; // uint64_t might give format-string warnings with %llx; it's just long in some ABIs
_mm_store_si128((__m128i*)v, in);
printf("v2_u64: %llx %llx\n", v[0], v[1]);
}
如果需要移植到C99或C++ 03或更早(即没有C11/C++ 11),取出和alignas()
使用storeu
代替store
。或者使用__attribute__((aligned(16)))
或__declspec(align(16))
。 (如果你正在编写带有内在函数的代码,你应该使用最近的编译器版本,较之以前的编译器,包括SSE/AVX内在函数,通常比asm编译器更好,但也许你想用gcc-6.3来-std=gnu++03
C++ 03模式为代码库是没有准备好C++ 11或东西。)从主叫所有4个功能输出
样品上
// source used:
__m128i vec = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 16);
// output:
v2_u64: 0x807060504030201 0x100f0e0d0c0b0a09
v4_u32: 0x4030201 0x8070605 0xc0b0a09 0x100f0e0d
v8_u16: 0x201 0x403 0x605 0x807 | 0xa09 0xc0b 0xe0d 0x100f
v16_u8: 0x1 0x2 0x3 0x4 | 0x5 0x6 0x7 0x8 | 0x9 0xa 0xb 0xc | 0xd 0xe 0xf 0x10
调整格式字符串如果你想填充前导零来保持一致输出宽度。见printf(3)
。
另请注意,'__m128i'没有关于正在存储的类型的任何信息。它可以是8位整数,16位整数,32位等等。一些编译器支持'.m128i_i32'字段扩展。但这绝对不是标准,也不是GCC。 – Mysticial
与标题相关:[如何使用gcc打印__uint128_t数字?](http://stackoverflow.com/q/11656241/4279) – jfs
请注意,某些编译器对SIMD类型具有内置的printf支持,例如, Apple的gcc,clang等版本都支持'%vld'打印'__m128i'为4 x 32位整数。 –