通过函数指针使用内部函数时出现链接器错误

Linker errors when using intrinsic function via function pointer

下面的代码不能用 visual studio 2013 编译。我得到 mm 函数的链接器错误无法解析的外部符号(LNK 2019)。如果我直接使用这些功能,一切都很好。 为什么它不编译?有没有解决方法

        #include "emmintrin.h"
        #include <smmintrin.h>
        #include <intrin.h>


        __m128i (*load)(const __m128i*) = NULL;

        if (it::isAligned<16>(ucpSrc, iXOffset * sizeof(unsigned char)) )
            load = &_mm_load_si128;
        else
            load = &_mm_lddqu_si128;

一些编译器,如 gcc 和 clang 在这些方法上使用一些特殊注释(static extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) 用于 gcc,或 static __inline__ __attribute__((__always_inline__, __nodebug__)) 用于 clang),其他编译器(如 Intel 在 Windows 和cl,不要,可能会在幕后做一些特别的事情。

关键是这些函数并不意味着被视为函数。他们不会显示任何序言,执行标准 ABI。这些只是调用某些汇编指令的 C 语法方式,比 __asm (...)

更具可读性

我相信你可以通过以下方式完成这个函数指针的事情:

__m128i load_aligned (const __m128i* p)
{
    return _mm_load_si128(p);
}

__m128i load_unaligned (const __m128i* p)
{
    return _mm_lddqu_si128(p);
}


__m128i (*load)(const __m128i*) = NULL;

void f(bool a)
{
    if (a)
        load = load_aligned;
    else
        load = load_unaligned;
}

int main()
{
    __m128i a, b ;
    f(argc != 0);
    return 0;
}

不过,我要强调一个性能说明:使用函数指针比一直使用未对齐的加载要昂贵得多。当内存对齐时,未对齐加载的开销大约是百分之几,调用函数指针将迫使您尊重 ABI,因此将寄存器存储在堆栈上,很可能会经历一些缓存未命中等。