【发布时间】:2018-08-28 17:29:47
【问题描述】:
如何诱使 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 代码,但无论如何我还是想哄它一下,看看它有多聪明。
【问题讨论】:
-
大概不使用
asm? -
正确 - 不使用 asm 指令 ;)
-
rep cmpsb不快;例如,在 Haswell 上,每字节吞吐量 >= 2 个周期。 (agner.org/optimize)。当前 x86 CPU 中只有rep movs和rep stos支持“快速字符串”。现代 CPU 的“聪明”之处是使用 SSE2pcmpeqb。 (但是 gcc 和 clang 不知道如何使用在循环进入之前未知的迭代计数来向量化循环;即它们不能向量化搜索循环。但 ICC 可以。) -
@PeterCordes 有趣的是 instlatx64 says Haswell 可以做 1 bye / cycle,不知道哪个是对的?
-
@harold:这就是说 L1D 中的带宽。所以它们意味着每个字符串的 1 个字节有 2 个周期。 Agner 将其描述为每
n = ecx的周期数,即每次比较的周期数(这就是我所说的每字节的意思;我没有意识到歧义)。 InstLatx64 将rep lodsb带宽列为 0.5 字节/周期,这与 Agner 的~2n数字为rep lods吞吐量一致。
标签: c performance gcc assembly x86