gpt4 book ai didi

c - Intrinsic __lzcnt64 使用不同的编译选项返回不同的值

转载 作者:太空狗 更新时间:2023-10-29 16:07:46 28 4
gpt4 key购买 nike

我有以下代码:

#include <stdint.h>
#include <stdio.h>
#include <x86intrin.h>

long long lzcnt(long long l)
{
return __lzcnt64(l);
}

int main(int argc, char** argv)
{
printf("%lld\n", lzcnt(atoll(argv[1])));
return 0;
}

使用不同的编译器和选项运行我得到(显示的程序集):

clang

$ clang -Wall src/test.c -D__LZCNT__ && ./a.out 2047
53

0000000000400560 <lzcnt>:
400560: 55 push %rbp
400561: 48 89 e5 mov %rsp,%rbp
400564: 48 89 7d f0 mov %rdi,-0x10(%rbp)
400568: 48 8b 7d f0 mov -0x10(%rbp),%rdi
40056c: 48 89 7d f8 mov %rdi,-0x8(%rbp)
400570: 48 8b 7d f8 mov -0x8(%rbp),%rdi
400574: 48 0f bd ff bsr %rdi,%rdi
400578: 48 83 f7 3f xor $0x3f,%rdi
40057c: 89 f8 mov %edi,%eax
40057e: 48 63 c0 movslq %eax,%rax
400581: 5d pop %rbp
400582: c3 retq
400583: 66 66 66 66 2e 0f 1f data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)
40058a: 84 00 00 00 00 00

没有 -mlzcnt 的 GCC

$ gcc -Wall src/test.c -D__LZCNT__ && ./a.out 2047
53

0000000000400580 <lzcnt>:
400580: 55 push %rbp
400581: 48 89 e5 mov %rsp,%rbp
400584: 48 89 7d e8 mov %rdi,-0x18(%rbp)
400588: 48 8b 45 e8 mov -0x18(%rbp),%rax
40058c: 48 89 45 f8 mov %rax,-0x8(%rbp)
400590: 48 0f bd 45 f8 bsr -0x8(%rbp),%rax
400595: 48 83 f0 3f xor $0x3f,%rax
400599: 48 98 cltq
40059b: 5d pop %rbp
40059c: c3 retq

GCC 与 -mlzcnt

$ gcc -Wall src/test.c -D__LZCNT__ -mlzcnt && ./a.out 2047
10

0000000000400580 <lzcnt>:
400580: 55 push %rbp
400581: 48 89 e5 mov %rsp,%rbp
400584: 48 89 7d e8 mov %rdi,-0x18(%rbp)
400588: 48 8b 45 e8 mov -0x18(%rbp),%rax
40058c: 48 89 45 f8 mov %rax,-0x8(%rbp)
400590: f3 48 0f bd 45 f8 lzcnt -0x8(%rbp),%rax
400596: 48 98 cltq
400598: 5d pop %rbp
400599: c3 retq

没有 -mlzcnt 的 G++

$ g++ -Wall src/test.c -D__LZCNT__ && ./a.out 2047
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/immintrin.h:64:0,
from /usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/x86intrin.h:62,
from src/test.c:3:
/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/lzcntintrin.h: In function ‘short unsigned int __lzcnt16(short unsigned int)’:
/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/lzcntintrin.h:38:29: error: ‘__builtin_clzs’ was not declared in this scope
return __builtin_clzs (__X);

G++ 与 -mlzcnt

$ g++ -Wall src/test.c -D__LZCNT__ -mlzcnt  && ./a.out 2047
10

0000000000400640 <_Z5lzcntx>:
400640: 55 push %rbp
400641: 48 89 e5 mov %rsp,%rbp
400644: 48 89 7d e8 mov %rdi,-0x18(%rbp)
400648: 48 8b 45 e8 mov -0x18(%rbp),%rax
40064c: 48 89 45 f8 mov %rax,-0x8(%rbp)
400650: f3 48 0f bd 45 f8 lzcnt -0x8(%rbp),%rax
400656: 48 98 cltq
400658: 5d pop %rbp
400659: c3 retq

区别很明显是 -mlzcnt 的使用,但是我实际上是在 C++ 中工作,没有这个选项它不会在 g++ 上编译(clang++ 很好)。看起来当使用 -mlzcnt 时结果是 63-(没有 -mlzct 的结果)。是否有任何关于 gcc 的 -mlzcnt 选项的文档(我查看了信息文件,但找不到任何东西)?除了选择 lzcnt 指令之外,它还有什么作用吗?

最佳答案

首先,我能够使用 clang 3.3 和 gcc 4.8.1 完美地复制您的问题。

这是我的想法……我只完成了大约 50%。

  • LZCNT 是您的计算机可能不支持的指令。
  • Wikipedia建议 LZCNT 需要 Haswell 支持
  • 我们可以尝试使用 Linux 应用程序验证此信息 cpuid . (包含在 Debian、RHEL 等中)。
  • 维基百科再次建议“通过 CPUID.80000001H:ECX.ABM[Bit 5] 标志表示支持”。

让我们看看我的系统(Xeon X3430,Lynnfield,Nehalem)。

[4:48pm][wlynch@apple /tmp] sudo cpuid -1ir | grep 80000001
0x80000001 0x00: eax=0x00000000 ebx=0x00000000 ecx=0x00000001 edx=0x28100800

因此,ECX 的第 23 位不正确。所以我的系统不支持 LZCNT。

看起来我的机器恰好将不受支持的 LZCNT 解释为 BSR。

关于c - Intrinsic __lzcnt64 使用不同的编译选项返回不同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19678547/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com