[英]How to generate a sse4.2 popcnt machine instruction
使用c程序:
int main(int argc , char** argv)
{
return __builtin_popcountll(0xf0f0f0f0f0f0f0f0);
}
和編譯器行(gcc 4.4 - Intel Xeon L3426):
gcc -msse4.2 poptest.c -o poptest
我沒有得到內置的popcnt insruction,而是編譯器生成一個查找表並以這種方式計算popcount。 生成的二進制文件超過8000個字節。 (東旭!)
非常感謝您的幫助。
您必須告訴GCC為支持popcnt指令的體系結構生成代碼:
gcc -march=corei7 popcnt.c
或者只是啟用popcnt支持:
gcc -mpopcnt popcnt.c
在您的示例程序的參數__builtin_popcountll
是一個常數,因此編譯器可能會做計算在編譯的時候,從來沒有發出指令POPCNT。 即使沒有要求優化程序,GCC也會這樣做。
所以嘗試傳遞它在編譯時無法知道的東西:
int main (int argc, char** argv)
{
return __builtin_popcountll ((long long) argv);
}
$ gcc -march=corei7 -O popcnt.c && objdump -d a.out | grep '<main>' -A 2
0000000000400454 <main>:
400454: f3 48 0f b8 c6 popcnt %rsi,%rax
400459: c3 retq
你需要這樣做:
#include <stdio.h>
#include <smmintrin.h>
int main(void)
{
int pop = _mm_popcnt_u64(0xf0f0f0f0f0f0f0f0ULL);
printf("pop = %d\n", pop);
return 0;
}
$ gcc -Wall -m64 -msse4.2 popcnt.c -o popcnt
$ ./popcnt
pop = 32
$
編輯
糟糕 - 我剛用gcc 4.2和ICC 11.1檢查了反匯編輸出 - 而ICC 11.1正確生成了popcntl
或popcntq
,由於某些原因gcc沒有 - 它調用了___popcountdi2
。 奇怪的。 我有機會嘗試更新版本的gcc,看看它是否已修復。 我想唯一的解決方法是使用ICC而不是gcc。
對於GCC中的__builtin_popcountll
,您需要做的就是添加-mpopcnt
#include <stdlib.h>
int main(int argc, char **argv) {
return __builtin_popcountll(atoi(argv[1]));
}
-mpopcnt
$ otool -tvV a.out
a.out:
(__TEXT,__text) section
_main:
0000000100000f66 pushq %rbp
0000000100000f67 movq %rsp, %rbp
0000000100000f6a subq $0x10, %rsp
0000000100000f6e movq %rdi, -0x8(%rbp)
0000000100000f72 movq -0x8(%rbp), %rax
0000000100000f76 addq $0x8, %rax
0000000100000f7a movq (%rax), %rax
0000000100000f7d movq %rax, %rdi
0000000100000f80 callq 0x100000f8e ## symbol stub for: _atoi
0000000100000f85 cltq
0000000100000f87 popcntq %rax, %rax
0000000100000f8c leave
0000000100000f8d retq
-mpopcnt
a.out:
(__TEXT,__text) section
_main:
0000000100000f55 pushq %rbp
0000000100000f56 movq %rsp, %rbp
0000000100000f59 subq $0x10, %rsp
0000000100000f5d movq %rdi, -0x8(%rbp)
0000000100000f61 movq -0x8(%rbp), %rax
0000000100000f65 addq $0x8, %rax
0000000100000f69 movq (%rax), %rax
0000000100000f6c movq %rax, %rdi
0000000100000f6f callq 0x100000f86 ## symbol stub for: _atoi
0000000100000f74 cltq
0000000100000f76 movq %rax, %rdi
0000000100000f79 callq 0x100000f80 ## symbol stub for: ___popcountdi2
0000000100000f7e leave
0000000100000f7f retq
在使用POPCNTQ之前,請務必檢查CPUID功能位的ABM位(第23位)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.