【问题标题】:Are tail calls on diverging functions optimized in Rust?是否在 Rust 中优化了对不同函数的尾调用?
【发布时间】:2021-08-31 09:03:48
【问题描述】:

如果我有以下功能:

fn a() -> ! {
    b()
}

fn b() -> ! {
    loop {}
}

Rust 是否优化了对简单跳转的此类调用?

我查看了Playground 来显示程序集,但a 似乎只是callq b 函数。

总是这样吗?

【问题讨论】:

  • 正如您在操场输出中看到的那样,程序集是在没有优化的情况下生成的:[unoptimized + debuginfo]
  • 在使用优化编译操场示例时,a()b() 都内联到 main 中,并且汇编代码简单地变为 .LBB5_1: jmp .LBB5_1
  • 请注意,您很少能保证优化器将要做什么。除非您遇到实际的性能问题,否则我建议不要在意。
  • 顺便说一句,为什么您希望这种优化只针对尾调用?
  • .LBB0_1: jmp .LBB0_1 => play.rust-lang.org/…

标签: function rust calling-convention tail-call-optimization tail-call


【解决方案1】:

首先,您可以使用#[inline] 告诉编译器内联函数:从技术上讲,这不能保证内联,但它应该在合理的情况下工作。我会推荐使用这个。

其次,如 cmets 中所述,您必须进行优化构建才能看到这种内联。也许一个更好的工具是编译器资源管理器。 Here 是对您的示例的轻微修改(请注意编译器选项中的 -O 标志)。可以看到,所有的东西都内联在一个无限循环中,如果编译器能证明它是无用的,甚至可以消除循环中所做的一些工作。

总的来说,除非您使用#[inline],否则结果将取决于ab 的内容。因此,我建议您使用 ab 创建某种最小可行的实现,然后在 Compiler Explorer 中对其进行测试。

【讨论】:

    猜你喜欢
    • 2016-09-10
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 2017-04-18
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多