加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

GCC 的内建函数(build in function)的使用

(2013-02-27 15:33:05)
标签:

it

分类: Linux

一、Built in 相关的 compiler options:

 

-fbuiltin:

这是默认选项,用于通过名字来识别内建函数

 

-fno-builtin:

除非利用前缀 __builtin_ 进行引用,否则不识别所有内建函数。例如,为了获得内建版本,应该调用 __builtin_strcpy() 而不是名为 strcpy() 的函数。

 

-fno-builtin-xxx(例如:-fno-builtin-sqrt):

想使用除sqrt() 之外的所有内建函数

 

-msse:

the compiler could use the extended instruction sets even if the built-ins are not used explicitly in the program.

 

-msse2:

-msse3

-mssse3

-msse4

-msse4.1

-msse4.2

-mavx

-mavx2

-maes

-mmmx

-mpclmul:

-mfsgsbase:

-mrdrnd

-msse4a

-mxop

-mfma4

-mlwp

-m3dnow and -march=athlon

 -mtbm

-mno-tbm

-mcx16

-msahf

-mmovbe

 

 二、gcc 下使用多媒体指令集(MMX, SSE)函数

http://blog.csdn.net/zenny_chen/article/details/4226989

 

在VC2005以上版本(包括2005)有非常丰富的针对x86架构处理器指令集的内建函数,包括典型的BFS、RDTSC、以及MMX、3DNOW!(+)、SSE、SSE2。到VC2008以后又支持了SSE3、SSSE3、以及SSE4A、SSE4.1和SSE4.2。

然而,当这些搬到GCC上时用起来就显得十分麻烦。下面我就先举一个VC2008上的例子:

 
     #include <stdio.h>   
  1. #include <mmintrin.h>   
  2. #include <emmintrin.h>   
  3.   
  4. int main(void 
  5.  
  6.     __m64 m64Value1 _mm_cvtsi32_si64(0x302077fe); // MOVD   
  7.     __m64 m64Value2 _mm_cvtsi32_si64(0x10203040); // MOVD   
  8.   
  9.     m64Value1 _mm_insert_pi16(m64Value1, 0xab, 3);  
  10.     m64Value2 _mm_add_pi8(m64Value2, m64Value1);  
  11.     m64Value2 _mm_packs_pu16(m64Value2, m64Value1);  
  12.   
  13.     printf("The value is 0x%x/n"_mm_cvtsi64_si32(m64Value2));  
  14.   
  15.     _mm_empty();  
  16.   
  17.     return 0;  
  18.  

还是相同的代码,放到GCC上看看:

  1. #include <stdio.h>  
  2. typedef char __attribute__((vector_size(8)))    v8qi;  
  3. typedef short __attribute__((vector_size(8)))   v4hi;  
  4. typedef int __attribute__((vector_size(8)))     v2si;  
  5.   
  6. int main()  
  7.   
  8.     v8qi m64Value1 0xfe, 0x77, 0x20, 0x30 };  
  9.     v8qi m64Value2 0x40, 0x30, 0x20, 0x10 };  
  10.   
  11.     m64Value1 (v8qi)__builtin_ia32_pinsrw((v4hi)m64Value1, 0xab, 3);  
  12.     m64Value2 __builtin_ia32_paddb(m64Value2, m64Value1);  
  13.     m64Value2 __builtin_ia32_packuswb((v4hi)m64Value2, (v4hi)m64Value1);  
  14.   
  15.     //这里目前实在没办法使用MOVD reg32, regMMX的方式   
  16.     printf("The value is: 0x%x/n"*(unsigned*)&m64Value2);  
  17.   
  18.     return 0;  
  19.  

上述两段代码的输出结果均为0xab00ff00。

 

VC代码没什么可讲,这里主要谈一下GCC的代码。

首先,最上面的三个类型定义是定义向量数据类型。v8qi表示向量有8个单元,并且每个单元都占用1个字节。这里比较奇怪的是这些基本类型的定义GCC没有默认支持也没有放在某个特定的头文件中。这样要去一个个定义也是比较麻烦的(网上说的)。

然后,由于很多操作所基于的单元大小是不同的,比如说PADDB的每个单元是1个字节,而PADDW就是2个字节,因此在要做其它与变量定义不同的单元个数的操作时需要进行类型转换。可以看到上面有很多类型转换。

另外还有一点比较讨厌的是GCC没有提供MOVD这样的基本操作,使得基本类型与向量类型直接的转换也比较麻烦。这里的做法是直接通过访问变量地址,这样做会带来性能上的降低。不过目前也没有其它什么好的办法。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有