这样的功能是否会对性能产生负面影响?
fn:
cmp rdi, 0
je lbl0
...
ret
lbl0:
...
ret
call fn
还有这个?
fn0:
... ; no ret, fall through
fn1:
...
ret
Fall through是您可以执行的最有效的操作;这只是正常的执行。 CPU甚至不知道“ 2个不同的功能”与一个功能中的标签之间的区别。全部都是机器代码。标签为零宽度,只是给您一种从其他地方引用该地址的方法。
[从高层次看,您可以将其视为第二个函数的优化尾调用,就像使用jmp fn1
而不是call fn1; ret
,然后当然优化掉jmp +0
,因为跳转到下一条指令是在结构上是nop
。
对于第一个,这就是所谓的“尾巴重复”优化,其中函数中的多个路径会复制任何必要的清除操作(pop rbx
或其他任何操作)和一个ret
,而不是运行额外的[ C0]以获取清理的单个副本。
尾部复制会占用代码足迹(静态代码大小),但会导致每个调用执行的动态指令更少。通常,它不会影响分支预测; jmp
由类似于ret
与ret
的堆栈状预测器预测(即,假设call
将返回到执行的最后一个ret
。)只要这仍然是正确的(在这里),您没有问题。您可以通过多种方法来使用该函数,但是每次调用它时,都会运行其中一种。
您还可以执行循环尾部复制,其中您在循环内分支,并且分支的每一侧分别具有call
(带有任何必需的dec ecx / jnz .top_of_loop
或循环外的任何内容。]