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
-mno-tbm
-mcx16
-msahf
-mmovbe
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
<mmintrin.h> -
#include
<emmintrin.h> -
-
int
main( void) - {
-
//__m64 m64Value1 = _mm_cvtsi32_si64(0x302077fe); MOVD -
//__m64 m64Value2 = _mm_cvtsi32_si64(0x10203040); MOVD -
-
m64Value1 = _mm_insert_pi16(m64Value1, 0xab, 3); -
m64Value2 = _mm_add_pi8(m64Value2, m64Value1); -
m64Value2 = _mm_packs_pu16(m64Value2, m64Value1); -
-
"Theprintf( value ,is 0x%x/n" _mm_cvtsi64_si32(m64Value2)); -
-
_mm_empty(); -
-
return0; - }
还是相同的代码,放到GCC上看看:
-
#include
<stdio.h> -
typedef
char __attribute__((vector_size(8))) v8qi; -
typedef
short __attribute__((vector_size(8))) v4hi; -
typedef
int __attribute__((vector_size(8))) v2si; -
-
int
main() { -
-
v8qi m64Value1 = { 0xfe, 0x77, 0x20, 0x30 }; -
v8qi m64Value2 = { 0x40, 0x30, 0x20, 0x10 }; -
-
m64Value1 = (v8qi)__builtin_ia32_pinsrw((v4hi)m64Value1, 0xab, 3); -
m64Value2 = __builtin_ia32_paddb(m64Value2, m64Value1); -
m64Value2 = __builtin_ia32_packuswb((v4hi)m64Value2, (v4hi)m64Value1); -
-
//这里目前实在没办法使用MOVDreg32, regMMX的方式 -
"Theprintf( value ,is: 0x%x/n" *(unsigned*)&m64Value2); -
-
return0; - }
上述两段代码的输出结果均为0xab00ff00。
VC代码没什么可讲,这里主要谈一下GCC的代码。
首先,最上面的三个类型定义是定义向量数据类型。v8qi表示向量有8个单元,并且每个单元都占用1个字节。这里比较奇怪的是这些基本类型的定义GCC没有默认支持也没有放在某个特定的头文件中。这样要去一个个定义也是比较麻烦的(网上说的)。
然后,由于很多操作所基于的单元大小是不同的,比如说PADDB的每个单元是1个字节,而PADDW就是2个字节,因此在要做其它与变量定义不同的单元个数的操作时需要进行类型转换。可以看到上面有很多类型转换。
另外还有一点比较讨厌的是GCC没有提供MOVD这样的基本操作,使得基本类型与向量类型直接的转换也比较麻烦。这里的做法是直接通过访问变量地址,这样做会带来性能上的降低。不过目前也没有其它什么好的办法。

加载中…