[英]Detect -xarch option in the preprocessor?
我在Solaris 11上使用Sun Studio 12.4和12.5。我們有一個源文件,它提供CRC32的直接C / C ++實現,或者提供使用Intel內在函數的CRC32的優化版本。 在運行時,將使用適當的實現填充函數指針。
在具有雙至強處理器的x86服務器上進行測試會產生以下結果,因為我們基於編譯器版本提供了可用的代碼路徑。 SunCC 12.1添加了對SSE4的支持(如果我正確地解析了矩陣),因此我們嘗試在__SUNPRO_CC >= 0x5100
時啟用它。
"crc.cpp", line 311: ube: error: _mm_crc32_u8 intrinsic requires at least -xarch=sse4_2.
SunCC 沒有定義常規的GCC定義,例如__SSE4_1__
和__SSE4_2__
。 此外,SunCC似乎沒有像MS VC ++那樣使內部函數可用,在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位,以便程序可以在低級處理器上運行?
請參閱《鏈接器和庫指南》的第7章:能力處理:
https://docs.oracle.com/cd/E53394_01/html/E54813/index.html
這顯示了如何交付具有功能位標記的同一功能的多個實例。 運行時鏈接程序將根據報告的功能來確定使用哪個功能。
如果您真的想自己管理功能位,請參閱第9章Mapfile中的“ CAPABILITY指令”一節。 這顯示了如何從生成的對象中刪除功能。
我認為,對於您的特定情況(第二部分),唯一簡單的方法是執行此操作:使用顯式設置“ -xarch = sse4.2”進行編譯(這使編譯器可以擴展SSE4.2內部函數)然后將HWCAP位剝離為最小的體系結構(這使您的程序可以在SSE4.2之前的硬件上運行)。
有關剝離HWCAP的信息,請參見: https ://docs.oracle.com/cd/E23823_01/html/816-5165/elfedit-1.html
(示例2刪除硬件功能位)
首先,您不想從已編譯的二進制文件中刪除指令集標志。 -xarch=NNNN
選項進行編譯時,編譯將使用這些指令。 如果您嘗試在未實現-xarch
參數提供的體系結構中的指令的“較低級”處理器上運行,則二進制文件很有可能無法正常工作。
1.3二進制兼容性驗證
在Solaris系統上,從Solaris Studio 11開始,使用Oracle Solaris Studio編譯器編譯的程序二進制文件標記有體系結構硬件標志,這些標志指示已編譯二進制文件假定的指令集。 在運行時,將檢查這些標記標志,以驗證二進制文件可以在其嘗試執行的硬件上運行。
在未使用適當功能或指令集擴展啟用的平台上運行不包含這些體系結構硬件標志的程序,可能會導致分段錯誤或出現錯誤結果,而沒有任何明確的警告消息。
還請注意功能和指令集的提及。 根據我在Solaris文檔中的經驗,僅留一點警告就足以說明可能還有很多其他事情要做。
我不知道通過預處理器檢測可用指令集的任何方法。 您可能可以在https://community.oracle.com/community/server_%26_storage_systems/application_development_in_c__c%2B%2B__and_fortran/developer_studio_c_c_c%2B%2B_fortran_compilers的 Solaris Studio的Oracle論壇上獲得幫助。
我懷疑即使在那兒,您也找不到使用預處理器的方法。 在Solaris上提供平台和指令集特定實現的通常方法是通過特定共享對象。 從《 Solaris鏈接器和庫指南》中 :
指令集特定的共享對象
動態令牌
$ISALIST
在運行時進行擴展,以反映在該平台上可執行的本機指令集,如實用工具isalist(1)
。任何包含
$ISALIST
令牌的字符串名稱都有效地復制為多個字符串。 每個字符串都分配有可用的指令集之一。 該令牌僅可用於過濾器或運行路徑規范。...
或者在具有
MMX
配置的Pentium 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
請注意,庫搜索是如何從“最高”指令集特定庫開始的,然后移至“較低”庫。 這允許定位多個指令集特定的共享對象,從“最快的特定”到“最慢的通用”。 Solaris上的libc.so
這樣做是為了提供特定於平台的庫函數版本,例如memcpy()
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.