gpt4 book ai didi

哄骗 GCC 发出 REPE CMPSB

转载 作者:行者123 更新时间:2023-12-01 08:57:14 24 4
gpt4 key购买 nike

如何哄骗 GCC 编译器以纯 C 语言发出 REPE CMPSB 指令,不使用“asm”和“_emit”关键字,调用包含的库和编译器内部函数?

我尝试了一些类似下面列出的 C 代码,但没有成功:

unsigned int repe_cmpsb(unsigned char *esi, unsigned char *edi, unsigned int ecx) {

for (; ((*esi == *edi) && (ecx != 0)); esi++, edi++, ecx--);

return ecx;
}

在此链接查看 GCC 如何编译它:
https://godbolt.org/g/obJbpq

附言
我意识到无法保证编译器以某种方式编译 C 代码,但无论如何我还是想哄它一下,看看它有多聪明。

最佳答案

rep cmps 不快;例如,在 Haswell 上,每个计数吞吐量 >= 2 个周期,加上启动开销。 (http://agner.org/optimize)。即使您必须检查匹配项和 0终结者,如果你写得仔细的话。

InstLatx64 numbers agree :Haswell 可以为 rep cmpsb 管理每个字节 1 个周期,但这是总带宽(即比较每个字符串的 1 个字节需要 2 个周期)。


只有 rep movsrep stos 在当前 x86 CPU 中具有“快速字符串”支持。 (即,当对齐和不重叠允许时,内部使用更广泛的加载/存储的微编码实现。)

现代 CPU 的“聪明”之处在于使用 SSE2 pcmpeqb/pmovmskb。 (但 gcc 和 clang 不知道如何使用在循环进入之前未知的迭代计数来向量化循环;即它们不能向量化搜索循环。但 ICC 可以。)


但是,出于某种原因,gcc 将内联 repz cmpsb 用于 strcmp 针对短的固定字符串。大概它不知道内联 strcmp 的任何更智能的模式,并且启动开销可能仍然比对动态库函数的函数调用的开销要好。也许不是,我没有测试过。无论如何,将某些内容与一堆固定字符串进行比较的代码块中的代码大小并不可怕。

#include <string.h>

int string_equal(const char *s) {
return 0 == strcmp(s, "test1");
}

gcc7.3 -O3 output from Godbolt

.LC0:
.string "test1"
string_cmp:
mov rsi, rdi
mov ecx, 6
mov edi, OFFSET FLAT:.LC0
repz cmpsb
setne al
movzx eax, al
ret

如果您不以某种方式对结果进行 bool 化处理,gcc 会使用 seta/setb/sub/movzx 生成 -1/0/+1 结果。 (在 IvyBridge 之前导致 Intel 上的部分寄存器停顿,以及对其他 CPU 的错误依赖,因为它在 setcc 结果上使用 32 位 sub,/facepalm。幸运的是大多数代码只需要 strcmp 的 2 路结果,而不是 3 路)。

gcc 只对固定长度的字符串常量执行此操作,否则它不知道如何设置 rcx


memcmp 的结果完全不同:gcc 做得很好,在这种情况下使用 DWORD 和 WORD cmp,没有代表字符串说明。

int cmp_mem(const char *s) {
return 0 == memcmp(s, "test1", 6);
}

cmp DWORD PTR [rdi], 1953719668 # 0x74736574
je .L8
.L5:
mov eax, 1
xor eax, 1 # missed optimization here after the memcmp pattern; should just xor eax,eax
ret
.L8:
xor eax, eax
cmp WORD PTR [rdi+4], 49 # check last 2 bytes
jne .L5
xor eax, 1
ret

控制这种行为

The manual-mstringop-strategy=libcall 应该强制调用库,但它不起作用。 asm 输出没有变化。

-mno-inline-stringops-dynamically -mno-inline-all-stringops也没有。

GCC 文档的这一部分似乎已过时。我还没有对更大的字符串文字或固定大小但非常量的字符串或类似的字符串进行进一步调查。

关于哄骗 GCC 发出 REPE CMPSB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49375094/

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