Macros 是否在预处理器中检测-xarch选项?

Macros 是否在预处理器中检测-xarch选项?,macros,c-preprocessor,solaris,cpu-architecture,sunstudio,Macros,C Preprocessor,Solaris,Cpu Architecture,Sunstudio,我正在Solaris 11上使用Sun Studio 12.4和12.5。我们有一个源文件,它提供了CRC32的直接C/C++实现,或使用Intel Intrinsic的CRC32优化版本。在运行时,函数指针由正确的实现填充 使用双Xeon在x86服务器上进行测试会产生以下结果,因为我们根据编译器版本提供代码路径。SUNCC12.1增加了对SSE4的支持(如果我正确地解析了矩阵),因此我们尝试在\uuu SUNPRO\u CC>=0x5100时启用它 "crc.cpp", line 311: u

我正在Solaris 11上使用Sun Studio 12.4和12.5。我们有一个源文件,它提供了CRC32的直接C/C++实现,或使用Intel Intrinsic的CRC32优化版本。在运行时,函数指针由正确的实现填充

使用双Xeon在x86服务器上进行测试会产生以下结果,因为我们根据编译器版本提供代码路径。SUNCC12.1增加了对SSE4的支持(如果我正确地解析了矩阵),因此我们尝试在
\uuu SUNPRO\u CC>=0x5100
时启用它

"crc.cpp", line 311: ube: error: _mm_crc32_u8 intrinsic requires at least -xarch=sse4_2.
SunCC不定义常规的GCC定义,如
\uuuuSSE4\uu1\uuuuu
\uuuuuSSE4\u2\uuuu
。此外,SunCC似乎不像MS-VC++那样提供内部函数,其中编译器版本表示支持

SunCC似乎启用了基于
-xarch
选项的功能,但我不清楚如何在预处理器中检测它。此外,使用
-xarch
设置一些位,这些位会导致程序在底层处理器(类似于“最小”平台)上执行失败

我有两个问题

  • 如何检测预处理器中的
    -xarch
    选项
  • 如何禁用
    -xarch
    位,使程序可以在底层处理器上运行

下面是使用
-xarch=aes
编译的宏转储。请注意,没有任何内容指示可用的功能

$ /opt/solarisstudio12.4/bin/CC -native -m64 -xarch=aes -xdumpmacros -E /dev/null 2>&1 | /usr/gnu/bin/sort --ignore-case

#1 "/dev/null"
#define __alignof__ __alignof
#define __amd64 1
#define __amd64__ 1
#define __ARRAYNEW 1
#define __asm asm
#define __asm__ asm
#define __attribute __attribute__
#define __builtin_constant_p __oracle_builtin_constant_p
#define __builtin_fpclassify __oracle_builtin_fpclassify
#define __builtin_huge_val __oracle_builtin_huge_val
#define __builtin_huge_valf __oracle_builtin_huge_valf
#define __builtin_huge_vall __oracle_builtin_huge_vall
#define __builtin_infinity __oracle_builtin_infinity
#define __builtin_isfinite __oracle_builtin_isfinite
#define __builtin_isgreater __oracle_builtin_isgreater
#define __builtin_isgreaterequal __oracle_builtin_isgreaterequal
#define __builtin_isinf __oracle_builtin_isinf
#define __builtin_isless __oracle_builtin_isless
#define __builtin_islessequal __oracle_builtin_islessequal
#define __builtin_islessgreater __oracle_builtin_islessgreater
#define __builtin_isnan __oracle_builtin_isnan
#define __builtin_isnormal __oracle_builtin_isnormal
#define __builtin_isunordered __oracle_builtin_isunordered
#define __builtin_nan __oracle_builtin_nan
#define __builtin_signbit __oracle_builtin_signbit
#define __BUILTIN_VA_STRUCT 1
#define __cplusplus 199711L
#define __DATE__ "Jul 11 2016"
#define __FILE__ 
#define __has_attribute(x) __oracle_has_attribute(x)
#define __has_nothrow_assign(x) __oracle_has_nothrow_assign(x)
#define __has_nothrow_constructor(x) __oracle_has_nothrow_constructor(x)
#define __has_nothrow_copy(x) __oracle_has_nothrow_copy(x)
#define __has_trivial_assign(x) __oracle_has_trivial_assign(x)
#define __has_trivial_constructor(x) __oracle_has_trivial_constructor(x)
#define __has_trivial_copy(x) __oracle_has_trivial_copy(x)
#define __has_trivial_destructor(x) __oracle_has_trivial_destructor(x)
#define __has_virtual_destructor(x) __oracle_has_virtual_destructor(x)
#define __is_abstract(x) __oracle_is_abstract(x)
#define __is_base_of(x,y) __oracle_is_base_of(x,y)
#define __is_class(x) __oracle_is_class(x)
#define __is_empty(x) __oracle_is_empty(x)
#define __is_enum(x) __oracle_is_enum(x)
#define __is_final(x) __oracle_is_final(x)
#define __is_literal_type(x) __oracle_is_literal_type(x)
#define __is_pod(x) __oracle_is_pod(x)
#define __is_polymorphic(x) __oracle_is_polymorphic(x)
#define __is_standard_layout(x) __oracle_is_standard_layout(x)
#define __is_trivial(x) __oracle_is_trivial(x)
#define __is_union(x) __oracle_is_union(x)
#define __LINE__ 
#define __LP64__ 1
#define __PRAGMA_REDEFINE_EXTNAME 1
#define __STDC__ 0
#define __sun 1
#define __SUN_PREFETCH 1
#define __SunOS 1
#define __SunOS_5_11 1
#define __SUNPRO_CC 0x5130
#define __SUNPRO_CC_COMPAT 5
#define __SVR4 1
#define __TIME__ "20:58:00"
#define __underlying_type(x) __oracle_underlying_type(x)
#define __unix 1
#define __volatile volatile
#define __volatile__ volatile
#define __x86_64 1
#define __x86_64__ 1
#define _BOOL 1
#define _LARGEFILE64_SOURCE 1
#define _LP64 1
#define _SIGNEDCHAR_ 1
#define _TEMPLATE_NO_EXTDEF 1
#define _WCHAR_T 
#define sun 1
#define unix 1

首先,您不想从已编译的二进制文件中删除指令集标志。使用
-xarch=NNNN
选项编译时,编译将使用这些指令。如果您试图在一个“较低”的处理器上运行,而该处理器没有实现您在
-xarch
参数中提供的体系结构中的指令,那么二进制文件很有可能无法工作

从:

1.3二进制兼容性验证

在Solaris系统上,从Solaris Studio 11开始,程序二进制文件 使用Oracle Solaris Studio编译器编译的编译器标记为 体系结构硬件标志,指示所采用的指令集 已编译的二进制文件。在运行时,将选中这些标记标志以 验证二进制文件是否可以在其尝试运行的硬件上运行 继续执行

正在运行不包含这些体系结构硬件标志的程序 在未启用相应功能的平台上,或 指令集扩展可能导致分段错误或 在没有任何明确警告消息的情况下出现不正确的结果

还要注意提到的功能以及指令集。根据我在Solaris文档中的经验,这一点就足以警告我们,可能还有更多的东西要做

我不知道如何通过预处理器检测可用的指令集。您可以在以下位置获得有关Solaris Studio Oracle论坛的帮助:

我怀疑即使在那里,你也找不到使用预处理器的方法。在Solaris上提供特定于平台和指令集的实现的通常方式是通过特定的共享对象。从:

特定于指令集的共享对象

动态令牌
$ISALIST
在运行时展开以反映 本机指令集可在此平台上执行,如 实用程序
isalist(1)

任何包含
$ISALIST
标记的字符串名称都是有效的 复制到多个字符串中。每个字符串都指定了一个 可用的指令集。此令牌仅适用于以下情况: 过滤器运行路径规范

或者在配置的奔腾Pro上执行具有类似依赖关系的应用程序:

$ ldd -ls prog
.....
  find object=libbar.so.1; required by ./libfoo.so.1
    search path=/opt/ISV/lib/$ISALIST  (RPATH from file ./libfoo.so.1)
      trying path=/opt/ISV/lib/pentium_pro+mmx/libbar.so.1
      trying path=/opt/ISV/lib/pentium_pro/libbar.so.1
      trying path=/opt/ISV/lib/pentium+mmx/libbar.so.1
      trying path=/opt/ISV/lib/pentium/libbar.so.1
      trying path=/opt/ISV/lib/i486/libbar.so.1
      trying path=/opt/ISV/lib/i386/libbar.so.1
      trying path=/opt/ISV/lib/i86/libbar.so.1

请注意,库搜索是如何从“最高”指令集特定的库开始,然后移动到“较低”的库的。这允许定位多个特定于指令集的共享对象,从“最快的特定”到“最慢的通用”
libc。因此,Solaris上的
提供了特定于平台的库函数版本,如
memcpy()

,用于第二个问题:

如何禁用-xarch位,使程序可以在底层处理器上运行

请参阅第7章链接器和库的功能处理指南:

这将向您展示如何交付同一函数的多个实例 它们被标记为能力位。运行时链接器将 根据报告的功能确定使用哪种功能

如果您真的想自己管理功能位, 参见第9章“能力指令”中的“映射文件”。
这显示了如何从生成的对象中删除功能。

我认为,对于您特定的情况(第二部分),实现所需功能的唯一简单方法是:使用显式设置“-xarch=sse4.2”编译(这允许编译器扩展sse4.2内部函数)然后将HWCAP位剥离到您的最小架构(这使您的程序可以在SSE4.2之前的硬件上运行)

欲了解更多信息,请参阅:


(示例2删除硬件功能位)

谢谢John。我们在运行时保护我们的代码路径,所以我们通常只需要编译器就可以使用ASM或内部代码。也就是说,为SSE2构建,我们可以处理其余的,比如优化的SSE3和SSE4实现。例如,请参见和。我假设您所引用的防护是hasse2()和hasse4()之类的函数。如果这些运行时检查硬件功能,那么您只需使用Studio添加选项-Mmapfile进行编译。映射文件将包含诸如“HW-=SSE2”之类的功能条目。屏蔽在提供后备功能的能力最低的系统上运行所需的每个功能。谢谢John。有