2

我在 SunOS 5.11 (Solaris 11.3) 上的 Sun Studio 12.3 下工作。它提供了一个我不太明白的编译错误:

$ /opt/solarisstudio12.3/bin/CC -xarch=sse2 -xarch=aes -xarch=sse4_2 -c test.cxx 
"test.cxx", line 11: ube: error: _mm_aeskeygenassist_si128 intrinsic requires at least -xarch=aes.
CC: ube failed for test.cxx

添加-m64会产生相同的错误。

测试程序没有太多内容。它只是练习 SSE2 内在函数和 AES 内在函数:

$ cat test.cxx
#include <stdint.h>
#include <wmmintrin.h>
#include <emmintrin.h>
int main(int argc, char* argv[])
{
  // SSE2
  int64_t x[2];
  __m128i y = _mm_loadu_si128((__m128i*)x);

  // AES
  __m128i z = _mm_aeskeygenassist_si128(y,0);

  return 0;
}

我一直在尝试阅读手册并学习如何指定多个 cpu 架构功能,如 SSE2、SSSE3、AES 和 SSE4。但我似乎无法确定如何指定多个。这是我发现的更完整的页面之一:Oracle Man Page CC.1,但我显然遗漏了一些关于-xarch.

我做错了什么,我该如何解决?

4

2 回答 2

3

这个命令行

$ /opt/solarisstudio12.3/bin/CC -xarch=sse2 -xarch=aes -xarch=sse4_2 -c test.cxx 

将使用最后一个-xarch=sse2 -xarch=aes -xarch=sse4_2并导致编译器发出sse4_2- 兼容的二进制文件。

这记录在C++ 用户指南的第 3 章中

3.2 一般准则

C++ 编译器选项的一些一般准则是:

  • -llib 选项与库 liblib.a(或 liblib.so)链接。将-llib 放在源文件和目标文件之后总是更安全,以确保搜索库的顺序。

  • 一般来说,编译器选项的处理是从左到右的(除了 -U 选项在所有 -D 选项之后处理),允许选择性地覆盖宏选项(包括其他选项的选项)。此规则不适用于链接器选项。

  • -features、-I -l、-L、-library、-pti、-R、-staticlib、-U、-verbose 和 -xprefetch 选项会累积,它们不会覆盖。

  • -D 选项累加。但是,同名的多个 -D 选项会相互覆盖。

源文件、目标文件和库按照它们在命令行中出现的顺序进行编译和链接。

这样做是为了让您可以执行诸如覆盖参数扩展之类的操作-fast,它扩展为大约 10 个单独的参数

您应该使用该-xarch=aes标志 - 最后一个或作为唯一-xarch=...选项。

于 2016-06-10T12:39:15.750 回答
0

我将为来自 GCC 的人提供一个答案。在 GCC 世界中,我们这样做-march=native,并且 GCC 定义了宏,如-D__SSE2__, -D__SSE4_1__, -D__SSE4_2__, -D__AES__, -D__AVX__,-D__BMI__等。

SunCC 不像 GCC 那样做。它不提供类似的定义__SSE2__;它也不提供-xarch.

以下是对相关 Sun Studio 手册和-xarch选项/指令集选择的参考:

以下是我们如何确定可以使用哪些标志,然后将它们转换为 GCC 预处理器宏。它很糟糕,但我不知道如何获取生成的代码。

CC=...
EGREP=...

X86_CPU_FLAGS=$(isainfo -v 2>/dev/null)
SUNCC_510_OR_ABOVE=$("$CXX" -V 2>&1 | "$EGREP" -c "CC: (Sun|Studio) .* (5\.1[0-9]|5\.[2-9]|[6-9]\.)")
SUNCC_511_OR_ABOVE=$("$CXX" -V 2>&1 | "$EGREP" -c "CC: (Sun|Studio) .* (5\.1[1-9]|5\.[2-9]|[6-9]\.)")
SUNCC_512_OR_ABOVE=$("$CXX" -V 2>&1 | "$EGREP" -c "CC: (Sun|Studio) .* (5\.1[2-9]|5\.[2-9]|[6-9]\.)")
SUNCC_513_OR_ABOVE=$("$CXX" -V 2>&1 | "$EGREP" -c "CC: (Sun|Studio) .* (5\.1[3-9]|5\.[2-9]|[6-9]\.)")

SUNCC_XARCH=
if [[ ("$SUNCC_511_OR_ABOVE" -ne "0") ]]; then
    if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "sse2") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__SSE2__"); SUNCC_XARCH=sse2; fi
        if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "sse3") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__SSE3__"); SUNCC_XARCH=ssse3; fi
        if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "ssse3") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__SSSE3__"); SUNCC_XARCH=ssse3; fi
        if [[ ("$SUNCC_512_OR_ABOVE" -ne "0") ]]; then
            if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "sse4.1") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__SSE4_1__"); SUNCC_XARCH=ssse4_1; fi
            if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "sse4.2") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__SSE4_2__"); SUNCC_XARCH=ssse4_2; fi
            if [[ ("$SUNCC_513_OR_ABOVE" -ne "0") ]]; then
                if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "aes") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__AES__"); SUNCC_XARCH=aes; fi
                if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "pclmulqdq") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__PCLMUL__"); SUNCC_XARCH=aes; fi
                if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "rdrand") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__RDRND__"); SUNCC_XARCH=avx_i; fi
                if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "rdseed") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__RDSEED__"); SUNCC_XARCH=avx_i; fi
                if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "avx") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__AVX__"); SUNCC_XARCH=avx; fi
                if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "avx2") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__AVX2__"); SUNCC_XARCH=avx2; fi
                if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "bmi") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__BMI__"); SUNCC_XARCH=avx2; fi
                if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "bmi2") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__BMI2__"); SUNCC_XARCH=avx2; fi
                if [[ ($(echo -n "$X86_CPU_FLAGS" | "$GREP" -c "adx") -ne "0") ]]; then PLATFORM_CXXFLAGS+=("-D__ADX__"); SUNCC_XARCH=avx2_i; fi        
            fi
        fi
    fi
fi
PLATFORM_CXXFLAGS+=("-xarch=$SUNCC_XARCH")

上面的回转允许我们做这样的事情(除了我们需要 SSE2 虽然 ADX)。

#if (_MSC_VER >= 1700) || defined(__RDRND__)
    uint64_t val;
    if(_rdrand64_step(&val))
    {
        // Use RDRAND value
    }
#endif

如果没有旋转,我们会在使用内联汇编和内在函数进行测试期间不断地使 12.1 到 12.3 编译器崩溃。

运行脚本的结果为我们提供了CFLAGS和的秘诀CXXFLAGS。以下来自第四代酷睿 i5。XEON 产生不同的结果,第 5 代 Core i5 也是如此。例如,第 5 代 Core i5 将具有ADX并使用-xarch=avx_i.

Pathname: /opt/solstudio12.2/bin/CC (symlinked)
CXXFLAGS: -D__SSE2__ -D__SSE3__ -D__SSSE3__ -xarch=ssse3

/opt/solarisstudio12.3/bin/CC (symlinked)
CXXFLAGS: -D__SSE2__ -D__SSE3__ -D__SSSE3__ -D__SSE4_1__ -D__SSE4_2__ -xarch=ssse4_2

Pathname: /opt/solarisstudio12.4/bin/CC
CXXFLAGS: -D__SSE2__ -D__SSE3__ -D__SSSE3__ -D__SSE4_1__ -D__SSE4_2__ -D__AES__ -D__PCLMUL__ -D__RDRND__ -D__AVX__ -xarch=avx

...
于 2016-09-11T12:35:54.940 回答