我最近偶然发现了隐式 SSE/AVX 加载/存储。我认为这些是 GCC 的一些特殊扩展,但后来意识到它们也适用于 MSVC。
__m128 a = *(__m128*)data // same as __m128 a = _mm_load_ps(data)?
__m128 *b = (__m128*)result; // same as _mm_store_ps(result, a)?
这些隐式加载/存储的正确语法是什么?
根据我的阅读(寻址非整数地址和 sse),隐式加载/存储使用对齐的加载/存储,因此内存必须正确对齐。假设它们对于支持 SSE/AVX 内在函数的大多数编译器(GCC/ICC/MSVC/Clang/MinGW,...)工作相同是否公平?拥有这些隐式加载/存储的动机是什么?
我的下一组问题是关于将 SSE/AVX 寄存器推送和弹出到堆栈。这是如何实施的?如果堆栈不是 16 字节对齐的怎么办?然后它是否使用未对齐的加载/存储?据我了解,堆栈现在通常是 16 字节对齐的,但不一定是 32 字节对齐的(至少在 64 位模式下)。如果算法具有高 AVX 占用率并且需要经常将 AVX 寄存器推送到堆栈上,将堆栈对齐到 32 个字节(例如,在具有 mpreferred-stack-boundary 的 GCC 中)以潜在地提高性能是否有意义?