内联时奇怪的编译器行为(包括ASM代码)

时间:2013-11-18 02:44:34

标签: c++ compiler-construction optimization

我的问题是,编译器选择不在特定情况下内联函数,从而使代码变得更慢。该函数应该计算向量的点积(SIMD加速)。我写了有两种不同的风格:

 1.The Vector class aggregates a __m128 member.
 2.The Vector is just a typedef of the __m128 member.

在案例1中,我得到的代码慢2倍,该函数不会内联。在案例2中,我获得了最佳代码,非常快,内联。

在案例1中,Vector和Dot函数如下所示:

__declspec(align(16)) class Vector
{
    public:
        __m128 Entry;

       Vector(__m128 s)
      {
          Entry = s;
      }
};

Vector Vector4Dot(Vector v1, Vector v2)
{
    return(Vector(_mm_dp_ps(v1.Entry, v2.Entry, DotMask4)));
}

在案例2中,Vector和Dot函数如下所示:

typedef __m128 Vector;

Vector Vector4Dot(Vector v1, Vector v2)
{
    return(_mm_dp_ps(v1, v2, DotMask4));
}

我正在发布模式下在x86上的Visual Studio 2012中编译MSVC,启用所有优化,优化速度,整个程序优化等。是否我将案例1的所有代码放在标题中或使用它与组合使用forceinline,没关系,它没有内联。这是生成的ASM:

案例1:

movaps  xmm0, XMMWORD PTR [esi]
lea eax, DWORD PTR $T1[esp+32]
movaps  xmm1, xmm0
push    eax
call    ?Vector4Dot@Framework@@SA?AVVector@23@T__m128@@0@Z ; Framework::Vector4Dot
movaps  xmm0, XMMWORD PTR [eax]
add esp, 4
movaps  XMMWORD PTR [esi], xmm0
lea esi, DWORD PTR [esi+16]
dec edi
jne SHORT $LL3@Test89

这是我调用Vector4Dot的地方。这里是它的内部(函数):

mov eax, DWORD PTR _v2$[esp-4]
movaps  xmm0, XMMWORD PTR [edx]
dpps    xmm0, XMMWORD PTR [eax], 255        ; 000000ffH
movaps  XMMWORD PTR [ecx], xmm0
mov eax, ecx

对于案例2,我得到:

movaps  xmm0, XMMWORD PTR [eax]
dpps    xmm0, xmm0, 255             ; 000000ffH
movaps  XMMWORD PTR [eax], xmm0
lea eax, DWORD PTR [eax+16]
dec ecx
jne SHORT $LL3@Test78

哪个更快。我不知道为什么编译器无法处理那个构造函数。如果我像这样改变case1:

__m128 Vector4Dot(Vector v1, Vector v2)
{
    return(_mm_dp_ps(v1.Entry, v2.Entry, DotMask4));
}

它以最大速度编译,与案例2相同。正是这种“类开销”给了我性能损失。有什么方法可以解决这个问题吗?或者我坚持使用原始__m128而不是Vector类?

0 个答案:

没有答案