如何防止函数调用被优化掉?

时间:2017-03-19 19:17:03

标签: rust llvm compiler-optimization

如何确保没有副作用的功能被执行并且在稳定的Rust中没有被优化?

我可以使用属性组合,还是必须调用另一个带副作用的函数?在需要函数调用的情况下,Rust标准库是否提供了保证不被优化的廉价函数?

2 个答案:

答案 0 :(得分:3)

#[no_mangle]目前会执行此操作,但may change

#[no_mangle]
pub fn do_what_i_say_dammit(x: i64) -> i64 { x*x }

澄清(从那篇文章):

  

我的心理模型是默认情况下符号由rustc拥有(例如,   如果符号是私有的,则rustc可以发出不同类型的符号   "精氨酸 - 促进"符号而不是预期的符号,只要它   处理它正确),#[no_mangle]转移所有权   程序员的象征。

     

现在,因为所有权转移给了程序员,所以   不能使用未指定的符号修改方案,因此符号为   留下了无耻的。

     

拥有一个没有咒骂的rustc拥有的符号几乎没有任何意义(你   实际上不能使用它,因为编译器拥有它) - 所以#[no_mangle]   暗示#[linker_owned]。没有松散#[linker_owned]因为   没有人实现它。

编辑:这是一个简单的例子。 no_mangle description

答案 1 :(得分:1)

test::black_box()(链接到旧文档)仍然不稳定(整个test包)。此函数采用任意类型的值并再次返回相同的值。所以它基本上是身份功能。 "哦,好吧,现在非常有用isn't it?"你可能会讽刺地问。

但是有一些特别之处:传递的值是从LLVM中隐藏的(现在几乎所有优化都在Rust中)!它真的是一个黑盒子,因为LLVM对一段代码一无所知。并且在不知道任何事情的情况下,LLVM无法证明优化不会改变程序的行为。因此:没有优化。

它是如何做到的?让我们来看看定义:

pub fn black_box<T>(dummy: T) -> T {
    // we need to "use" the argument in some way LLVM can't
    // introspect.
    unsafe { asm!("" : : "r"(&dummy)) }
    dummy
}

如果我假装我完全理解这段代码,我会撒谎,但它就是这样的:我们插入空的内联汇编(不是单个指令),但告诉Rust(告诉LLVM)这段程序集使用变量dummy。这使得优化器无法推断变量。 Stupid compiler,很容易欺骗,muhahahaha!如果你想要另一个解释,Chandler Carruth explained the dark magic参加CppCon 2015。

那么你现在如何使用它?只需将它用于某种价值......需要计算经过black_box()的任何事情。这样的事情怎么样?

black_box(my_function());

需要计算my_function()的返回值,因为编译器无法证明它是无用的!因此函数调用不会被删除。但请注意,您必须使用不稳定的功能(test crate或inline asm自行编写函数)或使用FFI。我当然不会在生产库中发布这种代码,但它对于测试目的肯定有用!