Gcc 如何生成sse4.2 popcnt机器指令

Gcc 如何生成sse4.2 popcnt机器指令,gcc,optimization,bit-manipulation,hammingweight,Gcc,Optimization,Bit Manipulation,Hammingweight,使用c程序: int main(int argc , char** argv) { return __builtin_popcountll(0xf0f0f0f0f0f0f0f0); } 以及编译器行(gcc 4.4-英特尔至强L3426): 我没有得到内置的popcnt指令,而是编译器生成一个查找表并以这种方式计算popcnt。生成的二进制文件超过8000字节。(Yuk!) 非常感谢您的帮助。您需要这样做: #include <stdio.h> #include <

使用c程序:

int main(int argc , char** argv)
{

  return  __builtin_popcountll(0xf0f0f0f0f0f0f0f0);

}
以及编译器行(gcc 4.4-英特尔至强L3426):

我没有得到内置的popcnt指令,而是编译器生成一个查找表并以这种方式计算popcnt。生成的二进制文件超过8000字节。(Yuk!)


非常感谢您的帮助。

您需要这样做:

#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
$ 
#包括
#包括
内部主(空)
{
int pop=_mm_popcnt_u64(0xf0f0ull);
printf(“pop=%d\n”,pop);
返回0;
}
$gcc-Wall-m64-msse4.2 popcnt.c-o popcnt
美元/popcnt
pop=32
$ 
编辑


Oops—我刚刚用gcc 4.2和ICC 11.1检查了反汇编输出—而ICC 11.1正确地生成了
popcntl
popcntq
,出于某种原因,gcc没有这样做—它调用
\uuuuuuu popcountdi2
。奇怪的我会尝试一个更新版本的gcc,当我有机会,看看它是否修复。我想唯一的解决办法是使用ICC而不是gcc。

您必须告诉gcc为支持的体系结构生成代码 popcnt指令:

gcc -march=corei7 popcnt.c
或者只启用对popcnt的支持:

gcc -mpopcnt popcnt.c
在您的示例程序中,
\uuuu builtin\u 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
int main(int argc,char**argv)
{
返回内置的popcountll((长-长)argv);
}
$gcc-march=corei7-O popcnt.c&&objdump-d a.out | grep''-a 2
0000000000400454 :
400454:f3 48 0f b8 c6 popcnt%rsi,%rax
400459:c3 retq

对于GCC中的
\uuuu内置\uu popcontll
,您只需添加
-mpopnt

#include <stdlib.h>
int main(int argc, char **argv) {
    return __builtin_popcountll(atoi(argv[1]));
}
-mpopnt
笔记
在使用POPCNTQ之前,请务必检查CPUID功能位的ABM位(位23)

非常感谢Paul对此进行的调查。使用(gcc(ubuntu4.4.3-4ubuntu5)4.4.3)的代码仍然会生成一个大的查找表。我将尝试安装icc。给你的小费真不错!我刚刚从MacPorts尝试了GCC4.4.6,它似乎生成了
popcnt
指令,所以看起来这可能已经在4.4.3和4.4.6之间修复了。所以我的一个朋友插话说,我需要使用objdump而不是x86dis来查找popcnt指令。当使用您的程序和objdump时,我看到:400533:f3 0f b8 45 f8 popcnt-0x8(%rbp),%eax,所以我认为我现在一切都好了。再次非常感谢。好的-我正在使用gcc-S生成asm源代码并查看它。顺便说一下,如果您的应用程序性能非常关键,您可能仍然想考虑ICC。祝你好运您可以只显示取
int
arg的函数的反汇编;它将比这更简短、更清晰。另外,我想你忘了启用优化,因为-O2启用了
-fomit帧指针
Perfect是发货的敌人。
gcc因为至少4.4.7(最旧的锁紧螺栓)启用了
-MPOPNT
作为
-msse4.2
的一部分,即使它们有单独的CPUID功能位。另外,如果您
\uuuuu内置\uupopcountll(argc)
,当您启用优化时,您的程序将不会优化到
返回32
。或者只查看asm中带有int arg的函数,因为您只想查看asm,而不是运行它。但是,如果您打算在本地运行二进制文件,那么,
-march=native
是迄今为止最好的选择,因为它设置了
-mtune
以及启用指令。
#include <stdlib.h>
int main(int argc, char **argv) {
    return __builtin_popcountll(atoi(argv[1]));
}
$ 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
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