Visual Studio 2017:_MM_LOAD_PS经常被编译为移动

Visual Studio 2017: _mm_load_ps often compiled to movups

本文关键字:编译 移动 LOAD 2017 Studio MM Visual PS      更新时间:2023-10-16

我正在查看我的代码生成的汇编(使用Visual Studio 2017),并注意到_mm_load_ps经常(总是?)汇编为移动。

我正在使用_mm_load_ps上的数据是这样定义的:

struct alignas(16) Vector {
    float v[4];
}
// often embedded in other structs like this
struct AABB {
    Vector min;
    Vector max;
    bool intersection(/* parameters */) const;
}

现在,当我使用此构造时,将会发生以下内容:

// this code
__mm128 bb_min = _mm_load_ps(min.v);
// generates this
movups  xmm4, XMMWORD PTR [r8]

我期望由于载体(16)而引起动作。在这种情况下,我还需要其他内容来说服编译器使用动作吗?

编辑:我的问题与这个问题有所不同,因为我没有崩溃。该结构是专门对齐的,我还使用对齐分配。相反,我很好奇编译器为什么要切换_mm_load_ps(对齐内存的固有语言)将其切换到移动。如果我知道struct是在一个对齐的地址分配的,并且我通过此*来称呼它*是安全的,对吗?

在最新版本的Visual Studio和Intel编译器(最近作为2013年后?)上,编译器很少会生成Aligned Simd Load/Stores。

用于AVX或更高版本时:

  • Microsoft编译器(> VS2013?)不会生成对齐负载。但它仍然会生成对齐的商店。
  • 英特尔编译器(> Parallel Studio 2012?)根本不再这样做。但是您仍然会在其手工优化库中的ICC编译的二进制文件中看到它们,例如memset()
  • 从GCC 6.1开始,当您使用对齐的固有时,它仍然会生成对齐的负载/存储。

允许编译器执行此操作,因为当正确编写代码时,它不是功能损失。从Nehalem开始的所有处理器都没有对地址对齐时对未对准负载/商店的罚款。

微软在此问题上的立场是"通过不崩溃来帮助程序员"。不幸的是,我再也找不到Microsoft的原始来源了。我认为,这与此相反,因为它隐藏了未对准的惩罚。从正确的角度来看,它也隐藏了不正确的代码。

无论是什么情况,都无条件地使用Unigned Load/Stores会简化编译器。

新相关性:

  • 启动并行工作室2018,英特尔编译器根本不再产生对齐的动作 - 即使对于预纳哈勒姆的目标也是如此。
  • 从Visual Studio 2017开始,Microsoft编译器也根本不再生成对齐的动作 - 即使针对AVX预备硬件。

这两种情况都会导致较旧的处理器的不可避免的性能降解。但这似乎是故意的,因为英特尔和微软都不再关心旧处理器。


唯一免疫此免疫的载荷/存储固有是非阶梯载荷/存储。它们没有不一致的等同,因此编译器别无选择。

因此,如果您只想对代码的正确性进行测试,则可以在Load/Store Intrinsics中代替非时空的代码。但是,请注意不要让类似的东西进入生产代码,因为NT负载/商店(尤其是NT商店)是一把双刃剑,如果您不知道自己在做什么,可能会伤害您。