设为首页 收藏本站
查看: 1876|回复: 0

[经验分享] 智能引入intrinsic函数。支持VC、GCC,兼容Windows、Linux、Mac OS X

[复制链接]

尚未签到

发表于 2015-12-31 07:02:51 | 显示全部楼层 |阅读模式
  http://blog.csdn.net/zyl910/article/details/8011147
  现在很多编译器支持intrinsic函数,这给编写SSE等SIMD代码带来了方便。但是各个编译器略有差异,于是我编写了zintrin.h,智能引入intrinsic函数。

一、各种编译器的区别

1.1 Visual C++(Windows)
  最早支持intrinsic函数的VC编译器是VC 6.0。它在装上Visual Studio 6.0 Service Pack 5、Visual C++ 6.0 Processor Pack这两个补丁后,便提供了mmintrin.h、mm3dnow.h、xmmintrin.h、emmintrin.h,用于支持MMX、3DNow!、SSE、SSE2的intrinsic函数。   从VC2005开始,提供了intrin.h,用于引入所有的intrinsic函数。   详见—— http://www.cnblogs.com/zyl910/archive/2012/02/28/vs_intrin_table.html Intrinsics头文件与SIMD指令集、Visual Studio版本对应表
  如果希望得知当前编译环境是否支持某种intrinsic函数,只能利用_MSC_VER判断VC的版本 来间接确认。   而且实际过程中会发现一些兼容性小问题,例如——VC不支持x64下的MMX指令、VC2008之前没有_mm_cvtss_f32 等。

1.2 GCC(Linux下的GCC、Windows下的MinGW)
  gcc也支持intrinsic函数。例如在Fedora 17中,“/usr/lib/gcc/i686-redhat-linux/4.7.0/include/”目录下有Intrinsics头文件。而对于Windows中的MinGW,Intrinsics头文件是在MinGW的“\lib\gcc\mingw32\4.6.2\include”子目录中。   详见—— http://www.cnblogs.com/zyl910/archive/2012/08/27/intrin_table_gcc.html GCC中的Intrinsics头文件与SIMD指令集、宏、参数的对应表
  gcc允许通过命令行参数来控制是否打开某种指令集的支持,例如“-mmmx”用于打开MMX支持。可在终端中执行“gcc --target-help”,得到详细的参数列表。
  当通过命令行参数打开指令集支持后,gcc会自动定义对应的预处理宏。例如用“-mmmx”打开MMX支持后,gcc会自动定义“__MMX__”这个预定义宏。这一类的预定义宏有—— __MMX__ __3dNOW__ __SSE__ __SSE2__ __SSE3__ __SSSE3__ __SSE4_1__ __SSE4_2__ __SSE4A__ __AES__ __PCLMUL__ __AVX__ __AVX2__ __F16C__ __FMA__ __FMA4__ __XOP__ __LWP__ __RDRND__ __FSGSBASE__ __LZCNT__ __POPCNT__ __BMI__ __BMI2__ __TBM__
  gcc用于引入所有x86平台intrinsic函数的头文件是“x86intrin.h”,它会根据那些指令集预定义宏来引入相关的intrinsic函数。例如有“__MMX__”宏时,x86intrin.h会引入MMX的intrinsic函数。

1.3 Mac OS X 中的 llvm-gcc
  我在Mac OS X系统中找了很久,貌似它不支持intrinsic函数。详细版本是—— 操作系统:Mac OS X Lion 10.7.4(11E53) 编程工具:Xcode 4.4.1(1448),并装好了它的“Command Line Tools”。
  __llvm__这个预定义宏可用来判断是不是llvm-gcc。

二、设计

2.1 思路
  不同的编译器引入intrinsic函数的办法—— 对于VS2005之前的版本,只能手动逐个逐个的包含emmintrin.h、mm3dnow.h; 对于VS2005之后的版本,可以利用intrin.h引入所有intrinsic函数; 对于GCC,首先应该判断__llvm__宏来排除llvm-gcc,然后利用x86intrin.h引入所有intrinsic函数。
  这样做太麻烦了,我想编写一个头文件智能引入intrinsic函数。这就是zintrin.h。
  其次—— VC中,没有直接判断是否支持某种intrinsic函数的办法,只能利用_MSC_VER判断VC的版本 来间接确认。而且还有x64环境下不支持MMX等特殊情况。 对于GCC,虽然可以利用__MMX__等宏判断是否打开了指令集支持,但这并不代表支持intrinsic函数。例如Mac OS X 中的 llvm-gcc,默认打开了__MMX__、__SSE__、__SSE2__,但它不支持intrinsic函数。
  于是我想,如果有一种统一的方式判断当前编译环境是否支持某种intrinsic函数的办法就好了。

2.2 功能说明
  功能—— 1. 引入了编译器支持的所有intrinsic函数. 2. 提供了 INTRIN_MMX 等一系列宏用于判断当前编译环境是否支持该intrin函数. 3. 兼容性补丁. 例如 _mm_cvtss_f32 等.
  用于判断当前编译环境是否支持该intrin函数的宏: INTRIN_MMX INTRIN_3dNOW INTRIN_SSE INTRIN_SSE2 INTRIN_SSE3 INTRIN_SSSE3 INTRIN_SSE4_1 INTRIN_SSE4_2 INTRIN_SSE4A INTRIN_AES INTRIN_PCLMUL INTRIN_AVX INTRIN_AVX2 INTRIN_F16C INTRIN_FMA INTRIN_FMA4 INTRIN_XOP INTRIN_LWP INTRIN_RDRND INTRIN_FSGSBASE INTRIN_LZCNT INTRIN_POPCNT INTRIN_BMI INTRIN_BMI2 INTRIN_TBM

三、源码

3.1 zintrin.h
  全部代码——






[cpp] view plaincopyprint?

  • #ifndef __ZINTRIN_H_INCLUDED   
  • #define __ZINTRIN_H_INCLUDED   
  •   
  • // 根据不同的编译器做不同的处理.   
  • #if defined(__GNUC__)   // GCC   
  •     #if (defined(__i386__) || defined(__x86_64__) ) && !defined(__llvm__)   // Mac OS X 的 llvm 不支持 intrin 函数.   
  •         // header files   
  •         #include <x86intrin.h>   
  •         #include <cpuid.h>   
  •   
  •         // macros   
  •         #ifdef __MMX__   
  •             #define INTRIN_MMX  1   
  •         #endif   
  •         #ifdef __3dNOW__   
  •             #define INTRIN_3dNOW    1   
  •         #endif   
  •         #ifdef __SSE__   
  •             #define INTRIN_SSE  1   
  •         #endif   
  •         #ifdef __SSE2__   
  •             #define INTRIN_SSE2 1   
  •         #endif   
  •         #ifdef __SSE3__   
  •             #define INTRIN_SSE3 1   
  •         #endif   
  •         #ifdef __SSSE3__   
  •             #define INTRIN_SSSE3    1   
  •         #endif   
  •         #ifdef __SSE4_1__   
  •             #define INTRIN_SSE4_1   1   
  •         #endif   
  •         #ifdef __SSE4_2__   
  •             #define INTRIN_SSE4_2   1   
  •         #endif   
  •         #ifdef __SSE4A__   
  •             #define INTRIN_SSE4A    1   
  •         #endif   
  •         #ifdef __AES__   
  •             #define INTRIN_AES  1   
  •         #endif   
  •         #ifdef __PCLMUL__   
  •             #define INTRIN_PCLMUL   1   
  •         #endif   
  •         #ifdef __AVX__   
  •             #define INTRIN_AVX  1   
  •         #endif   
  •         #ifdef __AVX2__   
  •             #define INTRIN_AVX2 1   
  •         #endif   
  •         #ifdef __F16C__   
  •             #define INTRIN_F16C 1   
  •         #endif   
  •         #ifdef __FMA__   
  •             #define INTRIN_FMA  1   
  •         #endif   
  •         #ifdef __FMA4__   
  •             #define INTRIN_FMA4 1   
  •         #endif   
  •         #ifdef __XOP__   
  •             #define INTRIN_XOP  1   
  •         #endif   
  •         #ifdef __LWP__   
  •             #define INTRIN_LWP  1   
  •         #endif   
  •         #ifdef __RDRND__   
  •             #define INTRIN_RDRND    1   
  •         #endif   
  •         #ifdef __FSGSBASE__   
  •             #define INTRIN_FSGSBASE 1   
  •         #endif   
  •         #ifdef __LZCNT__   
  •             #define INTRIN_LZCNT    1   
  •         #endif   
  •         #ifdef __POPCNT__   
  •             #define INTRIN_POPCNT   1   
  •         #endif   
  •         #ifdef __BMI__   
  •             #define INTRIN_BMI  1   
  •         #endif   
  •         #ifdef __BMI2__   
  •             #define INTRIN_BMI2 1   
  •         #endif   
  •         #ifdef __TBM__   
  •             #define INTRIN_TBM  1   
  •         #endif   
  •   
  •     #endif  // #if !defined(__llvm__)   
  •   
  • #elif defined(_MSC_VER) // MSVC   
  •     // header files   
  •     #if _MSC_VER >=1400  // VC2005   
  •         #include <intrin.h>   
  •     #elif _MSC_VER >=1200    // VC6   
  •         #if (defined(_M_IX86) || defined(_M_X64))   
  •             #include <emmintrin.h>    // MMX, SSE, SSE2   
  •             #include <mm3dnow.h>  // 3DNow!   
  •         #endif   
  •     #endif  // #if _MSC_VER >=1400   
  •     #include <malloc.h>   // _mm_malloc, _mm_free.   
  •   
  •     // macros   
  •     #if (defined(_M_IX86) || defined(_M_X64))   
  •         #if _MSC_VER >=1200  // VC6   
  •             #if defined(_M_X64) && !defined(__INTEL_COMPILER)   
  •                 // VC编译器不支持64位下的MMX.   
  •             #else   
  •                 #define INTRIN_MMX  1   // mmintrin.h   
  •                 #define INTRIN_3dNOW    1   // mm3dnow.h   
  •             #endif   
  •             #define INTRIN_SSE  1   // xmmintrin.h   
  •             #define INTRIN_SSE2 1   // emmintrin.h   
  •         #endif   
  •         #if _MSC_VER >=1300  // VC2003   
  •         #endif   
  •         #if _MSC_VER >=1400  // VC2005   
  •         #endif   
  •         #if _MSC_VER >=1500  // VC2008   
  •             #define INTRIN_SSE3 1   // pmmintrin.h   
  •             #define INTRIN_SSSE3    1   // tmmintrin.h   
  •             #define INTRIN_SSE4_1   1   // smmintrin.h   
  •             #define INTRIN_SSE4_2   1   // nmmintrin.h   
  •             #define INTRIN_SSE4A    1   // intrin.h   
  •             #define INTRIN_LZCNT    1   // intrin.h   
  •             #define INTRIN_POPCNT   1   // nmmintrin.h   
  •         #endif   
  •         #if _MSC_VER >=1600  // VC2010   
  •             #define INTRIN_AES  1   // wmmintrin.h   
  •             #define INTRIN_PCLMUL   1   // wmmintrin.h   
  •             #define INTRIN_AVX  1   // immintrin.h   
  •             #define INTRIN_FMA4 1   // ammintrin.h   
  •             #define INTRIN_XOP  1   // ammintrin.h   
  •             #define INTRIN_LWP  1   // ammintrin.h   
  •         #endif   
  •         #if _MSC_VER >=1700  // VC2012   
  •             #define INTRIN_AVX2 0   //TODO:待查证. 先设为0.   
  •             #define INTRIN_FMA  0   
  •             #define INTRIN_F16C 0   
  •             #define INTRIN_RDRND    0   
  •             #define INTRIN_FSGSBASE 0   
  •             #define INTRIN_BMI  0   
  •             #define INTRIN_BMI2 0   
  •             #define INTRIN_TBM  0   
  •         #endif   
  •     #endif   
  •     //TODO:待查证 VS配合intel C编译器时intrin函数的支持性.   
  •   
  •     // VC2008之前没有_mm_cvtss_f32   
  •     #if _MSC_VER <1500   // VC2008   
  •         // float _mm_cvtss_f32(__m128 _A);   
  •         #ifndef _mm_cvtss_f32   
  •             #define _mm_cvtss_f32(__m128_A) ( *(float*)(void*)&(__m128_A) )   
  •         #endif   
  •     #endif   
  •   
  • #else   
  • //#error Only supports GCC or MSVC.   
  • #endif  // #if defined(__GNUC__)   
  •   
  • #endif  // #ifndef __ZINTRIN_H_INCLUDED  

#ifndef __ZINTRIN_H_INCLUDED
#define __ZINTRIN_H_INCLUDED
// 根据不同的编译器做不同的处理.
#if defined(__GNUC__)// GCC
#if (defined(__i386__) || defined(__x86_64__) ) && !defined(__llvm__)// Mac OS X 的 llvm 不支持 intrin 函数.
// header files
#include <x86intrin.h>
#include <cpuid.h>
// macros
#ifdef __MMX__
#define INTRIN_MMX1
#endif
#ifdef __3dNOW__
#define INTRIN_3dNOW1
#endif
#ifdef __SSE__
#define INTRIN_SSE1
#endif
#ifdef __SSE2__
#define INTRIN_SSE21
#endif
#ifdef __SSE3__
#define INTRIN_SSE31
#endif
#ifdef __SSSE3__
#define INTRIN_SSSE31
#endif
#ifdef __SSE4_1__
#define INTRIN_SSE4_11
#endif
#ifdef __SSE4_2__
#define INTRIN_SSE4_21
#endif
#ifdef __SSE4A__
#define INTRIN_SSE4A1
#endif
#ifdef __AES__
#define INTRIN_AES1
#endif
#ifdef __PCLMUL__
#define INTRIN_PCLMUL1
#endif
#ifdef __AVX__
#define INTRIN_AVX1
#endif
#ifdef __AVX2__
#define INTRIN_AVX21
#endif
#ifdef __F16C__
#define INTRIN_F16C1
#endif
#ifdef __FMA__
#define INTRIN_FMA1
#endif
#ifdef __FMA4__
#define INTRIN_FMA41
#endif
#ifdef __XOP__
#define INTRIN_XOP1
#endif
#ifdef __LWP__
#define INTRIN_LWP1
#endif
#ifdef __RDRND__
#define INTRIN_RDRND1
#endif
#ifdef __FSGSBASE__
#define INTRIN_FSGSBASE1
#endif
#ifdef __LZCNT__
#define INTRIN_LZCNT1
#endif
#ifdef __POPCNT__
#define INTRIN_POPCNT1
#endif
#ifdef __BMI__
#define INTRIN_BMI1
#endif
#ifdef __BMI2__
#define INTRIN_BMI21
#endif
#ifdef __TBM__
#define INTRIN_TBM1
#endif
#endif// #if !defined(__llvm__)
#elif defined(_MSC_VER)// MSVC
// header files
#if _MSC_VER >=1400// VC2005
#include <intrin.h>
#elif _MSC_VER >=1200// VC6
#if (defined(_M_IX86) || defined(_M_X64))
#include <emmintrin.h>// MMX, SSE, SSE2
#include <mm3dnow.h>// 3DNow!
#endif
#endif// #if _MSC_VER >=1400
#include <malloc.h>// _mm_malloc, _mm_free.
// macros
#if (defined(_M_IX86) || defined(_M_X64))
#if _MSC_VER >=1200// VC6
#if defined(_M_X64) && !defined(__INTEL_COMPILER)
// VC编译器不支持64位下的MMX.
#else
#define INTRIN_MMX1// mmintrin.h
#define INTRIN_3dNOW1// mm3dnow.h
#endif
#define INTRIN_SSE1// xmmintrin.h
#define INTRIN_SSE21// emmintrin.h
#endif
#if _MSC_VER >=1300// VC2003
#endif
#if _MSC_VER >=1400// VC2005
#endif
#if _MSC_VER >=1500// VC2008
#define INTRIN_SSE31// pmmintrin.h
#define INTRIN_SSSE31// tmmintrin.h
#define INTRIN_SSE4_11// smmintrin.h
#define INTRIN_SSE4_21// nmmintrin.h
#define INTRIN_SSE4A1// intrin.h
#define INTRIN_LZCNT1// intrin.h
#define INTRIN_POPCNT1// nmmintrin.h
#endif
#if _MSC_VER >=1600// VC2010
#define INTRIN_AES1// wmmintrin.h
#define INTRIN_PCLMUL1// wmmintrin.h
#define INTRIN_AVX1// immintrin.h
#define INTRIN_FMA41// ammintrin.h
#define INTRIN_XOP1// ammintrin.h
#define INTRIN_LWP1// ammintrin.h
#endif
#if _MSC_VER >=1700// VC2012
#define INTRIN_AVX20//TODO:待查证. 先设为0.
#define INTRIN_FMA0
#define INTRIN_F16C0
#define INTRIN_RDRND0
#define INTRIN_FSGSBASE0
#define INTRIN_BMI0
#define INTRIN_BMI20
#define INTRIN_TBM0
#endif
#endif
//TODO:待查证 VS配合intel C编译器时intrin函数的支持性.
// VC2008之前没有_mm_cvtss_f32
#if _MSC_VER <1500// VC2008
// float _mm_cvtss_f32(__m128 _A);
#ifndef _mm_cvtss_f32
#define _mm_cvtss_f32(__m128_A) ( *(float*)(void*)&(__m128_A) )
#endif
#endif
#else
//#error Only supports GCC or MSVC.
#endif// #if defined(__GNUC__)
#endif// #ifndef __ZINTRIN_H_INCLUDED

  

3.2 testzintrin.c
  全部代码——






[cpp] view plaincopyprint?

  • #include <stdio.h>   
  •   
  • #include "zintrin.h"   
  •   
  • #define PT_MAKE_STR(x)  { #x, PT_MAKE_STR_ESC(x) }   
  • #define PT_MAKE_STR_ESC(x)  #x   
  •   
  • typedefstruct tagMACRO_T  
  • {  
  •     constchar *name;  
  •     constchar *value;  
  • } MACRO_T;  
  •   
  • /* Intrinsics */  
  • const MACRO_T g_intrins[] =  
  • {  
  •     {"[Intrinsics]", ""},  
  •   
  • #ifdef INTRIN_MMX   
  •     PT_MAKE_STR(INTRIN_MMX),  
  • #endif   
  •   
  • #ifdef INTRIN_3dNOW   
  •     PT_MAKE_STR(INTRIN_3dNOW),  
  • #endif   
  •   
  • #ifdef INTRIN_SSE   
  •     PT_MAKE_STR(INTRIN_SSE),  
  • #endif   
  •   
  • #ifdef INTRIN_SSE2   
  •     PT_MAKE_STR(INTRIN_SSE2),  
  • #endif   
  •   
  • #ifdef INTRIN_SSE3   
  •     PT_MAKE_STR(INTRIN_SSE3),  
  • #endif   
  •   
  • #ifdef INTRIN_SSSE3   
  •     PT_MAKE_STR(INTRIN_SSSE3),  
  • #endif   
  •   
  • #ifdef INTRIN_SSE4_1   
  •     PT_MAKE_STR(INTRIN_SSE4_1),  
  • #endif   
  •   
  • #ifdef INTRIN_SSE4_2   
  •     PT_MAKE_STR(INTRIN_SSE4_2),  
  • #endif   
  •   
  • #ifdef INTRIN_SSE4A   
  •     PT_MAKE_STR(INTRIN_SSE4A),  
  • #endif   
  •   
  • #ifdef INTRIN_AES   
  •     PT_MAKE_STR(INTRIN_AES),  
  • #endif   
  •   
  • #ifdef INTRIN_PCLMUL   
  •     PT_MAKE_STR(INTRIN_PCLMUL),  
  • #endif   
  •   
  • #ifdef INTRIN_AVX   
  •     PT_MAKE_STR(INTRIN_AVX),  
  • #endif   
  •   
  • #ifdef INTRIN_AVX2   
  •     PT_MAKE_STR(INTRIN_AVX2),  
  • #endif   
  •   
  • #ifdef INTRIN_F16C   
  •     PT_MAKE_STR(INTRIN_F16C),  
  • #endif   
  •   
  • #ifdef INTRIN_FMA   
  •     PT_MAKE_STR(INTRIN_FMA),  
  • #endif   
  •   
  • #ifdef INTRIN_FMA4   
  •     PT_MAKE_STR(INTRIN_FMA4),  
  • #endif   
  •   
  • #ifdef INTRIN_XOP   
  •     PT_MAKE_STR(INTRIN_XOP),  
  • #endif   
  •   
  • #ifdef INTRIN_LWP   
  •     PT_MAKE_STR(INTRIN_LWP),  
  • #endif   
  •   
  • #ifdef INTRIN_RDRND   
  •     PT_MAKE_STR(INTRIN_RDRND),  
  • #endif   
  •   
  • #ifdef INTRIN_FSGSBASE   
  •     PT_MAKE_STR(INTRIN_FSGSBASE),  
  • #endif   
  •   
  • #ifdef INTRIN_LZCNT   
  •     PT_MAKE_STR(INTRIN_LZCNT),  
  • #endif   
  •   
  • #ifdef INTRIN_POPCNT   
  •     PT_MAKE_STR(INTRIN_POPCNT),  
  • #endif   
  •   
  • #ifdef INTRIN_BMI   
  •     PT_MAKE_STR(INTRIN_BMI),  
  • #endif   
  •   
  • #ifdef INTRIN_BMI2   
  •     PT_MAKE_STR(INTRIN_BMI2),  
  • #endif   
  •   
  • #ifdef INTRIN_TBM   
  •     PT_MAKE_STR(INTRIN_TBM),  
  • #endif   
  •   
  • };  
  •   
  •   
  • // 获取程序位数(被编译为多少位的代码)   
  • int GetProgramBits(void)  
  • {  
  •     returnsizeof(int*) * 8;  
  • }  
  •   
  • void print_MACRO_T(const MACRO_T* pArray, int cnt)  
  • {  
  •     int i;  
  •     for( i = 0; i < cnt; ++i )  
  •     {  
  •         printf( "%s\t%s\n", pArray.name, pArray.value );  
  •     }  
  •     printf( "\n" );  
  • }  
  •   
  •   
  • int main(int argc, char* argv[])  
  • {  
  •   
  •     printf("testzintrin v1.00 (%dbit)\n\n", GetProgramBits());  
  •     print_MACRO_T(g_intrins, sizeof(g_intrins)/sizeof(g_intrins[0]));  
  •   
  •     // _mm_malloc   
  • #ifdef INTRIN_SSE   
  •     if(1)  
  •     {  
  •         void* p;  
  •         p = _mm_malloc(0x10, 0x10);  
  •         printf("_mm_malloc:\t%ph\n", p);  
  •         _mm_free(p);  
  •     }  
  • #endif   
  •   
  •     // mmx   
  • #ifdef INTRIN_MMX   
  •     _mm_empty();  
  • #endif   
  •   
  •     // 3DNow!   
  • #ifdef INTRIN_3dNOW   
  •     //_m_femms();   // AMD cpu only.   
  • #endif   
  •   
  •     // sse   
  • #ifdef INTRIN_SSE   
  •     if(1)  
  •     {  
  •         __m128 xmm1;  
  •         float f;  
  •         printf("&xmm1:\t%ph\n", &xmm1);  
  •         xmm1 = _mm_setzero_ps();    // SSE instruction: xorps   
  •         f = _mm_cvtss_f32(xmm1);  
  •         printf("_mm_cvtss_f32:\t%f\n", f);  
  •     }  
  • #endif   
  •   
  •     // popcnt   
  • #ifdef INTRIN_POPCNT   
  •     printf("popcnt(0xffffffffu):\t%u\n", _mm_popcnt_u32(0xffffffffu));  
  • #endif   
  •   
  •     return 0;  
  • }  

#include <stdio.h>
#include "zintrin.h"
#define PT_MAKE_STR(x){ #x, PT_MAKE_STR_ESC(x) }
#define PT_MAKE_STR_ESC(x)#x
typedef struct tagMACRO_T
{
const char *name;
const char *value;
} MACRO_T;
/* Intrinsics */
const MACRO_T g_intrins[] =
{
{"[Intrinsics]", ""},
#ifdef INTRIN_MMX
PT_MAKE_STR(INTRIN_MMX),
#endif
#ifdef INTRIN_3dNOW
PT_MAKE_STR(INTRIN_3dNOW),
#endif
#ifdef INTRIN_SSE
PT_MAKE_STR(INTRIN_SSE),
#endif
#ifdef INTRIN_SSE2
PT_MAKE_STR(INTRIN_SSE2),
#endif
#ifdef INTRIN_SSE3
PT_MAKE_STR(INTRIN_SSE3),
#endif
#ifdef INTRIN_SSSE3
PT_MAKE_STR(INTRIN_SSSE3),
#endif
#ifdef INTRIN_SSE4_1
PT_MAKE_STR(INTRIN_SSE4_1),
#endif
#ifdef INTRIN_SSE4_2
PT_MAKE_STR(INTRIN_SSE4_2),
#endif
#ifdef INTRIN_SSE4A
PT_MAKE_STR(INTRIN_SSE4A),
#endif
#ifdef INTRIN_AES
PT_MAKE_STR(INTRIN_AES),
#endif
#ifdef INTRIN_PCLMUL
PT_MAKE_STR(INTRIN_PCLMUL),
#endif
#ifdef INTRIN_AVX
PT_MAKE_STR(INTRIN_AVX),
#endif
#ifdef INTRIN_AVX2
PT_MAKE_STR(INTRIN_AVX2),
#endif
#ifdef INTRIN_F16C
PT_MAKE_STR(INTRIN_F16C),
#endif
#ifdef INTRIN_FMA
PT_MAKE_STR(INTRIN_FMA),
#endif
#ifdef INTRIN_FMA4
PT_MAKE_STR(INTRIN_FMA4),
#endif
#ifdef INTRIN_XOP
PT_MAKE_STR(INTRIN_XOP),
#endif
#ifdef INTRIN_LWP
PT_MAKE_STR(INTRIN_LWP),
#endif
#ifdef INTRIN_RDRND
PT_MAKE_STR(INTRIN_RDRND),
#endif
#ifdef INTRIN_FSGSBASE
PT_MAKE_STR(INTRIN_FSGSBASE),
#endif
#ifdef INTRIN_LZCNT
PT_MAKE_STR(INTRIN_LZCNT),
#endif
#ifdef INTRIN_POPCNT
PT_MAKE_STR(INTRIN_POPCNT),
#endif
#ifdef INTRIN_BMI
PT_MAKE_STR(INTRIN_BMI),
#endif
#ifdef INTRIN_BMI2
PT_MAKE_STR(INTRIN_BMI2),
#endif
#ifdef INTRIN_TBM
PT_MAKE_STR(INTRIN_TBM),
#endif
};

// 获取程序位数(被编译为多少位的代码)
int GetProgramBits(void)
{
return sizeof(int*) * 8;
}
void print_MACRO_T(const MACRO_T* pArray, int cnt)
{
int i;
for( i = 0; i < cnt; ++i )
{
printf( "%s\t%s\n", pArray.name, pArray.value );
}
printf( "\n" );
}

int main(int argc, char* argv[])
{
printf("testzintrin v1.00 (%dbit)\n\n", GetProgramBits());
print_MACRO_T(g_intrins, sizeof(g_intrins)/sizeof(g_intrins[0]));
// _mm_malloc
#ifdef INTRIN_SSE
if(1)
{
void* p;
p = _mm_malloc(0x10, 0x10);
printf("_mm_malloc:\t%ph\n", p);
_mm_free(p);
}
#endif
// mmx
#ifdef INTRIN_MMX
_mm_empty();
#endif
// 3DNow!
#ifdef INTRIN_3dNOW
//_m_femms();// AMD cpu only.
#endif
// sse
#ifdef INTRIN_SSE
if(1)
{
__m128 xmm1;
float f;
printf("&xmm1:\t%ph\n", &xmm1);
xmm1 = _mm_setzero_ps();// SSE instruction: xorps
f = _mm_cvtss_f32(xmm1);
printf("_mm_cvtss_f32:\t%f\n", f);
}
#endif
// popcnt
#ifdef INTRIN_POPCNT
printf("popcnt(0xffffffffu):\t%u\n", _mm_popcnt_u32(0xffffffffu));
#endif
return 0;
}

  

3.3 makefile
  全部代码——






[plain] view plaincopyprint?

  • # flags  
  • CC = gcc  
  • CFS = -Wall  
  • LFS =   
  •   
  • # args  
  • RELEASE =0  
  • BITS =  
  • CFLAGS = -msse  
  •   
  • # [args] 生成模式. 0代表debug模式, 1代表release模式. make RELEASE=1.  
  • ifeq ($(RELEASE),0)  
  •     # debug  
  •     CFS += -g  
  • else  
  •     # release  
  •     CFS += -static -O3 -DNDEBUG  
  •     LFS += -static  
  • endif  
  •   
  • # [args] 程序位数. 32代表32位程序, 64代表64位程序, 其他默认. make BITS=32.  
  • ifeq ($(BITS),32)  
  •     CFS += -m32  
  •     LFS += -m32  
  • else  
  •     ifeq ($(BITS),64)  
  •         CFS += -m64  
  •         LFS += -m64  
  •     else  
  •     endif  
  • endif  
  •   
  • # [args] 使用 CFLAGS 添加新的参数. make CFLAGS="-mpopcnt -msse4a".  
  • CFS += $(CFLAGS)  
  •   
  •   
  • .PHONY : all clean  
  •   
  • # files  
  • TARGETS = testzintrin  
  • OBJS = testzintrin.o  
  •   
  • all : $(TARGETS)  
  •   
  • testzintrin : $(OBJS)  
  •     $(CC) $(LFS) -o $@ $^  
  •   
  •   
  • testzintrin.o : testzintrin.c zintrin.h  
  •     $(CC) $(CFS) -c $<  
  •   
  •   
  • clean :  
  •     rm -f $(OBJS) $(TARGETS) $(addsuffix .exe,$(TARGETS))  

# flags
CC = gcc
CFS = -Wall
LFS =
# args
RELEASE =0
BITS =
CFLAGS = -msse
# [args] 生成模式. 0代表debug模式, 1代表release模式. make RELEASE=1.
ifeq ($(RELEASE),0)
# debug
CFS += -g
else
# release
CFS += -static -O3 -DNDEBUG
LFS += -static
endif
# [args] 程序位数. 32代表32位程序, 64代表64位程序, 其他默认. make BITS=32.
ifeq ($(BITS),32)
CFS += -m32
LFS += -m32
else
ifeq ($(BITS),64)
CFS += -m64
LFS += -m64
else
endif
endif
# [args] 使用 CFLAGS 添加新的参数. make CFLAGS="-mpopcnt -msse4a".
CFS += $(CFLAGS)

.PHONY : all clean
# files
TARGETS = testzintrin
OBJS = testzintrin.o
all : $(TARGETS)
testzintrin : $(OBJS)
$(CC) $(LFS) -o $@ $^

testzintrin.o : testzintrin.c zintrin.h
$(CC) $(CFS) -c $<

clean :
rm -f $(OBJS) $(TARGETS) $(addsuffix .exe,$(TARGETS))

  

四、测试
  在以下编译器中成功编译—— VC6:x86版。 VC2003:x86版。 VC2005:x86版、x64版。 VC2010:x86版、x64版。 GCC 4.7.0(Fedora 17 x64):x86版、x64版。 GCC 4.6.2(MinGW(20120426)):x86版。 GCC 4.6.1(TDM-GCC(MinGW-w64)):x86版、x64版。 llvm-gcc-4.2(Mac OS X Lion 10.7.4, Xcode 4.4.1):x86版、x64版。 DSC0000.png DSC0001.png DSC0002.png DSC0003.png
  
  参考文献—— 《Predefined Macros》. http://msdn.microsoft.com/en-us/library/b0084kay(v=vs.110).aspx 《Intrinsics头文件与SIMD指令集、Visual Studio版本对应表》. http://www.cnblogs.com/zyl910/archive/2012/02/28/vs_intrin_table.html 《GCC中的Intrinsics头文件与SIMD指令集、宏、参数的对应表》. http://www.cnblogs.com/zyl910/archive/2012/08/27/intrin_table_gcc.html
  
  源码下载—— http://files.cnblogs.com/zyl910/zintrin.rar

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-158599-1-1.html 上篇帖子: 在Mac OS X Lion 安装 XCode 3.2 下篇帖子: Mac OS X 安装 brew 工具!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表