- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
为什么编译器似乎更喜欢将预测试循环优化为检查、条件跳转,然后是 do-while 结构,而不是在 do while 循环内进行无条件跳转?
我写了一个用我描述的第二种风格编写的函数,但是 g++ 和 clang 都撤消了它并将其转换为方法一。 https://godbolt.org/g/2Dvudi
我很困惑,因为编译器似乎为预测试复制了很多指令(对于这个例子来说可能不是那么多)。此外,它无论如何都可能会跳转(尽管可能静态预测不会被采用,并且在一般情况下没什么大不了的),那么为什么不总是进行无条件跳转呢?
这是我的一个想法,但它并不强烈支持任何一种方法:
循环需要对齐,所以可能有空间在不浪费空间的情况下预先复制一些指令,因为它们会被 nops 填充。然而,clang 和 gcc 都为预测试发出了超过 16 字节的代码,并最终在之后插入了一个大的 nop。
编辑:这是来自 godbolt 链接的代码:
typedef unsigned char uchar;
unsigned my_atoi(const uchar *p)//sentinel at end
{
unsigned acm=0u;
unsigned d;
goto LEnter;
do{
acm = acm*10u + d;
LEnter:
d = *p++ - '0';
}while (d<10u);
return acm;
}
clang 5.0 at -O2 发出:
my_atoi(unsigned char const*): # @my_atoi(unsigned char const*)
movzx ecx, byte ptr [rdi]
add ecx, -48
xor eax, eax
cmp ecx, 9
ja .LBB0_3
inc rdi
xor eax, eax
.LBB0_2: # =>This Inner Loop Header: Depth=1
lea eax, [rax + 4*rax]
lea eax, [rcx + 2*rax]
movzx ecx, byte ptr [rdi]
add ecx, -48
inc rdi
cmp ecx, 10
jb .LBB0_2
.LBB0_3:
ret
最佳答案
引用来自 GCC sources 的一些评论相关的优化过程。
Duplicates headers of loops if they are small enough, so that the statements in the loop body are always executed when the loop is entered. This increases effectiveness of code motion optimizations, and reduces the need for loop preconditioning.
即,如果后面的过程找到一些循环不变的代码,他们将有一个地方可以移动该代码,而无需添加检查,循环是否会迭代。
For all loops, copy the condition at the end of the loop body in front of the loop. This is beneficial since it increases efficiency of code motion optimizations. It also saves one jump on entry to the loop.
关于c++ - 为什么 clang 和 gcc 重复代码和分支 vs 无条件跳转到循环内?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46737259/
我想编写一个 SQL 查询,如果没有分配日期时间,我想替换一个可以选择所有日期和时间的字符串。 实际工作原理: SELECT * FROM `entry` WHERE `user` like
表格如下所示: | colA | colB | colC | colD |some other cols ----------------------------- |double|double| i
我有一个 C# 程序经常失败。没关系,我已经创建了程序,它是我的 child ,无论如何我都喜欢它。作为一种支持,我决定围绕它编写一个 AutoHotKey 包装器,它会自动重新启动程序,直到它没有错
我的一位同事向我展示了计算表中记录的数量,以下 View : CREATE VIEW [SPR].[TablesCount] AS SELECT s.name cSchema,
我是一名优秀的程序员,十分优秀!