[C] zintrin.h: 智能引入intrinsic函数 V1.01版。改进对Mac OS X

新版本——[C] zintrin.h: 智能引入intrinsic函数 V1.02版。支持VC2012,增加INTRIN_ALIGN、INTRIN_COMPILER_NAME宏

作者:zyl910。

  之前的zintrin V1.00版对Mac OS X平台支持性不佳。现在的V1.01版改进对Mac OS X的支持,还做了这些改进——增加INTRIN_WORDSIZE宏 等。

一、更新说明1.1 改进对Mac OS X的支持

  前几天在使用Xcode时,网站空间,发现mac下也有intrinsic头文件,详见。  但是在终端中调用gcc编译时,总是报告找不到cpuid.h、x86intrin.h等文件。  后来才发现,“使用Xcode” 与 “终端中调用gcc”这两种情况下,编译器的include目录是不同的——使用Xcode:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/4.0/include终端中调用gcc:/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin11/4.2.1/include

  “/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin11/4.2.1/include”文件夹下的intrinsic头文件版本较老,没有提供cpuid.h、x86intrin.h等新版本的文件。

  该怎么办呢?  方案一:用宏判断gcc的版本,香港虚拟主机,然后引入最高支持的intrinsic头文件。  方案二:强制要求用户配置好include目录。  方案三:根据__MMX__等宏判断当前编译器是否启用该指令集,然后引入相应文件。

  方案一不行。因为现在gcc的版本一样,只是include目录不同。  方案二也不好。因为这样给使用带来了麻烦。  方案三不错。按需引入对应的文件。当发现启用AVX等新指令集时,x86intrin.h应该是可用的。

1.2 增加INTRIN_WORDSIZE宏

  某些intrinsic函数仅在64位下可用,例如_mm_popcnt_u64。所以需要一种能判断目标机器字长的办法。

  一般情况下,免备案空间,指针变量的长度就是机器字长,但是sizeof运算符不能用于宏预处理。

  这是可以利用C99的stdint.h,它提供了一系列宏用于判断各种数据类型的范围。其中有PTRDIFF_MAX,我们可以利用它来判断机器字长——

PTRDIFF_MAX >= INT64_MAX#define INTRIN_WORDSIZE 64#elif PTRDIFF_MAX >= INT32_MAX#define INTRIN_WORDSIZE 32#else#define INTRIN_WORDSIZE 16#endif

  有一点需要注意,根据C99标准——对于纯C程序来说,PTRDIFF_MAX等宏默认是启用的。但对于C++程序,PTRDIFF_MAX等宏默认不启用。只有在引入stdint.h之前定义了__STDC_LIMIT_MACROS,才会启用这些宏。

  当发现没有PTRDIFF_MAX等宏时,可以这样报告错误——

#include !defined(PTRDIFF_MAX) || !defined(INT32_MAX)#error Need C99 marcos: __STDC_LIMIT_MACROS.#endif

1.3 其他改进

  gcc不再引入cpuid.h。这是因为难以判断cpuid.h是否存在。而使用ccpuid模块能更方便的判断cpu指令集。

  不再假定未来VC版本支持AVX2等指令集。这是为了避免潜在的错误,宁缺毋滥。

  调整了一下INTRIN_常数的顺序。

二、全部代码2.1 zintrin.h

  全部代码——

View Code

#ifndef __ZINTRIN_H_INCLUDED#define __ZINTRIN_H_INCLUDED#include !defined(PTRDIFF_MAX) || !defined(INT32_MAX)#error Need C99 marcos: __STDC_LIMIT_MACROS.PTRDIFF_MAX >= INT64_MAX#define INTRIN_WORDSIZE 64#elif PTRDIFF_MAX >= INT32_MAX#define INTRIN_WORDSIZE 32#else#define INTRIN_WORDSIZE 16defined(__GNUC__) (defined(__i386__) || defined(__x86_64__) )// header files mac下有时找不到. 于是放弃, 使用ccpuid模块会更方便. mac下有时找不到. 于是根据宏来加载头文件.// macros#ifdef __MMX__#define INTRIN_MMX 1#include <mmintrin.h>#endif#ifdef __3dNOW__#define INTRIN_3dNOW 1#include <mm3dnow.h>#endif#ifdef __SSE__#define INTRIN_SSE 1#include <xmmintrin.h>#endif#ifdef __SSE2__#define INTRIN_SSE2 1#include <emmintrin.h>#endif#ifdef __SSE3__#define INTRIN_SSE3 1#include <pmmintrin.h>#endif#ifdef __SSSE3__#define INTRIN_SSSE3 1#include <tmmintrin.h>#endif#ifdef __SSE4_1__#define INTRIN_SSE4_1 1#include <smmintrin.h>#endif#ifdef __SSE4_2__#define INTRIN_SSE4_2 1#include <nmmintrin.h>#endif#ifdef __SSE4A__#define INTRIN_SSE4A 1#include <ammintrin.h>#endif#ifdef __AES__#define INTRIN_AES 1#include <x86intrin.h>#endif#ifdef __PCLMUL__#define INTRIN_PCLMUL 1#include <x86intrin.h>#endif#ifdef __AVX__#define INTRIN_AVX 1#include <x86intrin.h>#endif#ifdef __AVX2__#define INTRIN_AVX2 1#include <x86intrin.h>#endif#ifdef __F16C__#define INTRIN_F16C 1#include <x86intrin.h>#endif#ifdef __FMA__#define INTRIN_FMA 1#include <x86intrin.h>#endif#ifdef __FMA4__#define INTRIN_FMA4 1#include <x86intrin.h>#endif#ifdef __XOP__#define INTRIN_XOP 1#include <xopintrin.h>#endif#ifdef __LWP__#define INTRIN_LWP 1#include <x86intrin.h>#endif#ifdef __RDRND__#define INTRIN_RDRND 1#include <x86intrin.h>#endif#ifdef __FSGSBASE__#define INTRIN_FSGSBASE 1#include <x86intrin.h>#endif#ifdef __POPCNT__#define INTRIN_POPCNT 1#include <popcntintrin.h>#endif#ifdef __LZCNT__#define INTRIN_LZCNT 1#include <x86intrin.h>#endif#ifdef __TBM__#define INTRIN_TBM 1#include <x86intrin.h>#endif#ifdef __BMI__#define INTRIN_BMI 1#include <x86intrin.h>#endif#ifdef __BMI2__#define INTRIN_BMI2 1#include <x86intrin.h>defined(_MSC_VER) _MSC_VER >=1400 // VC2005#include <intrin.h>(defined(_M_IX86) || defined(_M_X64))#include <emmintrin.h> // MMX, SSE, SSE2#include <mm3dnow.h> #include <malloc.h> // _mm_malloc, _mm_free.(defined(_M_IX86) || defined(_M_X64))defined(_M_X64) && !defined(__INTEL_COMPILER)INTRIN_MMX 1 INTRIN_3dNOW 1 INTRIN_SSE 1 INTRIN_SSE2 1 _MSC_VER >=1300 _MSC_VER >=1400 _MSC_VER >=1500 INTRIN_SSE3 1 INTRIN_SSSE3 1 INTRIN_SSE4_1 1 INTRIN_SSE4_2 1 INTRIN_POPCNT 1 INTRIN_SSE4A 1 INTRIN_LZCNT 1 _MSC_VER >=1600 INTRIN_AES 1 INTRIN_PCLMUL 1 INTRIN_AVX 1 INTRIN_FMA4 1 INTRIN_XOP 1 INTRIN_LWP 1 _MSC_VER >=1700 TODO:待查证, 注释掉.//#define INTRIN_FMA 1//#define INTRIN_F16C 1//#define INTRIN_RDRND 1//#define INTRIN_FSGSBASE 1//#define INTRIN_TBM 1//#define INTRIN_BMI 1TODO:待查证 VS配合intel C编译器时intrin函数的支持性._MSC_VER <1500 #ifndef _mm_cvtss_f32#define _mm_cvtss_f32(__m128_A) ( *(float*)(void*)&(__m128_A) )

2.2 testzintrin.c

  全部代码——

当你感到悲哀痛苦时,最好是去学些什么东西。

[C] zintrin.h: 智能引入intrinsic函数 V1.01版。改进对Mac OS X

相关文章:

你感兴趣的文章:

标签云: