[C] zintrin.h: 智能引入intrinsic函数 V1.02版。支持VC2012,增

作者:zyl910。

一、更新说明1.1 支持VC2012

  VC2012增加了很多Intrinsics函数,详见——检查了一下VC2012新增的Intrinsics函数集,发现它支持ARM指令和Haswell新指令

  根据上述信息改进zintrin,检测到是VC2012时定义相关的宏——

INTRIN_AVX2 1 INTRIN_FMA 1 INTRIN_F16C 1 INTRIN_RDRND 1 INTRIN_FSGSBASE 1 INTRIN_TBM 1 INTRIN_LZCNT 1 INTRIN_BMI 1 INTRIN_BMI2 1 INTRIN_INVPCID 1 INTRIN_HLE 1 INTRIN_RTM 1

  INVPCID、HLE、RTM是Haswell的新指令,原先的“INTRIN_*”判断宏没有它们。于是增加了这几个定义——INTRIN_INVPCIDINTRIN_HLEINTRIN_RTM

  通过对比VC2010与VC2012的头文件后发现——虽然以前intrin.h支持lzcnt,但它是双下划线版的,而不是Intel所规定的单下划线版。直到VC2012,网站空间,才支持单下划线版lzcnt。  具体修正做法——注释掉以前的INTRIN_LZCNT。检测到是VC2012时,才定义INTRIN_LZCNT。

1.2 增加INTRIN_ALIGN宏(地址对齐)

  在使用SIMD指令时,经常需要地址对齐。例如 MMX要求8字节对齐,SSE要求16字节对齐,AVX要求32字节对齐。  因C语言标准未考虑该问题,VC与GCC的实现方法都不同。于是我定义一个INTRIN_ALIGN宏,用来统一处理地址对齐问题——

INTRIN_ALIGN(n) __attribute__((aligned(n)))INTRIN_ALIGN(n) __declspec(align(n))

  使用时,免备案空间,香港虚拟主机,将该宏写在数据类型的前面。例如——INTRIN_ALIGN(32) uint_16 buf[16];

1.3 增加INTRIN_COMPILER_NAME宏(编译器名称)

  在使用Intrinsics函数时,经常需要得知编译器名称,以方便进行对比分析。于是我定义了INTRIN_COMPILER_NAME宏——

#define INTRIN_MACTOSTR(x) #x#define INTRIN_MACROVALUESTR(x) INTRIN_MACTOSTR(x)#if defined(__ICL) // Intel C++# if defined(__VERSION__)# define INTRIN_COMPILER_NAME __VERSION__# elif defined(__INTEL_COMPILER_BUILD_DATE)# define INTRIN_COMPILER_NAME INTRIN_MACROVALUESTR(__INTEL_COMPILER_BUILD_DATE) # else# define INTRIN_COMPILER_NAME # endif defined(_MSC_VER) // Microsoft VC++# if defined(_MSC_FULL_VER)# define INTRIN_COMPILER_NAME INTRIN_MACROVALUESTR(_MSC_FULL_VER) # elif defined(_MSC_VER)# define INTRIN_COMPILER_NAME INTRIN_MACROVALUESTR(_MSC_VER) # else# define INTRIN_COMPILER_NAME # endif defined(__GNUC__) // GCC# if defined(__CYGWIN__)# define INTRIN_COMPILER_NAME __VERSION__# elif defined(__MINGW32__)# define INTRIN_COMPILER_NAME __VERSION__# else# define INTRIN_COMPILER_NAME __VERSION__# endif # define INTRIN_COMPILER_NAME

  示例——printf(“Compiler: %s\n”, INTRIN_COMPILER_NAME);

二、全部代码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.defined(__GNUC__) INTRIN_ALIGN(n) __attribute__((aligned(n)))INTRIN_ALIGN(n) __declspec(align(n))INTRIN_MACTOSTR(x) #x#define INTRIN_MACROVALUESTR(x) INTRIN_MACTOSTR(x)#if defined(__ICL) // Intel C++# if defined(__VERSION__)# define INTRIN_COMPILER_NAME __VERSION__# elif defined(__INTEL_COMPILER_BUILD_DATE)# define INTRIN_COMPILER_NAME INTRIN_MACROVALUESTR(__INTEL_COMPILER_BUILD_DATE) # else# define INTRIN_COMPILER_NAME # endif defined(_MSC_VER) // Microsoft VC++# if defined(_MSC_FULL_VER)# define INTRIN_COMPILER_NAME INTRIN_MACROVALUESTR(_MSC_FULL_VER) # elif defined(_MSC_VER)# define INTRIN_COMPILER_NAME INTRIN_MACROVALUESTR(_MSC_VER) # else# define INTRIN_COMPILER_NAME # endif defined(__GNUC__) // GCC# if defined(__CYGWIN__)# define INTRIN_COMPILER_NAME __VERSION__# elif defined(__MINGW32__)# define INTRIN_COMPILER_NAME __VERSION__# else# define INTRIN_COMPILER_NAME __VERSION__# endif # define INTRIN_COMPILER_NAME 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))_MSC_VER >=1200 // VC6#include <emmintrin.h> // MMX, SSE, SSE2#include <mm3dnow.h> #include <malloc.h> // _mm_malloc, _mm_free._MSC_VER >=1200 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 _MSC_VER >=1600 INTRIN_AES 1 INTRIN_PCLMUL 1 INTRIN_AVX 1 INTRIN_FMA4 1 INTRIN_XOP 1 INTRIN_LWP 1 _MSC_VER >=1700 INTRIN_AVX2 1 INTRIN_FMA 1 INTRIN_F16C 1 INTRIN_RDRND 1 INTRIN_FSGSBASE 1 INTRIN_TBM 1 INTRIN_LZCNT 1 INTRIN_BMI 1 INTRIN_BMI2 1 INTRIN_INVPCID 1 INTRIN_HLE 1 INTRIN_RTM 1 _MSC_VER <1500 #ifndef _mm_cvtss_f32#define _mm_cvtss_f32(__m128_A) ( *(float*)(void*)&(__m128_A) )defined(_M_ARM)

2.2 testzintrin.c

  全部代码——

向上攀爬的。

[C] zintrin.h: 智能引入intrinsic函数 V1.02版。支持VC2012,增

相关文章:

你感兴趣的文章:

标签云: