具有多个 returns 时对性能的影响
Impact on performance when having multiple returns
看看下面的场景。
;some code
test reg1,reg2
je jump1
;do something
add rsp,20
pop rdx
ret
jump1:
;do something
cmp reg2,reg3
jg jump2
add rsp,20
pop rdx
ret
jump2:
;do something
add rsp,20
pop rdx
ret
类似的汇编在反汇编代码中并不常见。也许编译器可以有效地处理这些问题。
多个 return 语句会影响性能吗?
与上述相比,使用单个 return 和 jmp
可能产生的性能结果是什么?
这称为"tail duplication"优化。有些编译器有时会这样做。例如LLVM blog post about it
当你的函数尾声很小(只有 1 个 pop)时,这通常是一件好事,所以它不会花费太多,特别是在具有大缓存和良好代码密度的现代 x86 上(ret
和 pop
是单字节)。虽然如果只有一条路径通过该函数预计是 "hot",但最好让另一条路径跳转到热路径以节省少量 uop-cache space.
它保存了一个 jmp
在函数之外的路径上。这对性能的影响取决于周围的代码,对于深度流水线超标量无序来说总是如此 CPU!
如果根据您的函数的使用方式,通过一个函数的多个路径可能很热,那么它们可以 both/all 完全有效。
您也可以为循环内部有分支的循环执行此操作:复制 dec/jcc
或循环底部的任何内容,而不是跳转到公共 dec/jcc
。 (不要忘记在两种/所有情况下处理掉落路径!)
看看下面的场景。
;some code
test reg1,reg2
je jump1
;do something
add rsp,20
pop rdx
ret
jump1:
;do something
cmp reg2,reg3
jg jump2
add rsp,20
pop rdx
ret
jump2:
;do something
add rsp,20
pop rdx
ret
类似的汇编在反汇编代码中并不常见。也许编译器可以有效地处理这些问题。
多个 return 语句会影响性能吗?
与上述相比,使用单个 return 和 jmp
可能产生的性能结果是什么?
这称为"tail duplication"优化。有些编译器有时会这样做。例如LLVM blog post about it
当你的函数尾声很小(只有 1 个 pop)时,这通常是一件好事,所以它不会花费太多,特别是在具有大缓存和良好代码密度的现代 x86 上(ret
和 pop
是单字节)。虽然如果只有一条路径通过该函数预计是 "hot",但最好让另一条路径跳转到热路径以节省少量 uop-cache space.
它保存了一个 jmp
在函数之外的路径上。这对性能的影响取决于周围的代码,对于深度流水线超标量无序来说总是如此 CPU!
如果根据您的函数的使用方式,通过一个函数的多个路径可能很热,那么它们可以 both/all 完全有效。
您也可以为循环内部有分支的循环执行此操作:复制 dec/jcc
或循环底部的任何内容,而不是跳转到公共 dec/jcc
。 (不要忘记在两种/所有情况下处理掉落路径!)