optimization - 我可以强制 Rust 不优化单个函数吗?

标签 optimization rust llvm-codegen

我有一个函数,其中 Rust 的/LLVM 的优化失败并导致 panic (在发布版本中),而未优化的代码(调试版本)运行良好。如果我比较生成的汇编代码,我什至无法理解优化器试图完成什么。
(一个原因可能是这个函数使用了内联汇编器。)

有什么方法可以告诉 Rust 在优化期间不理会某些功能,还是我必须关闭所有优化?

下面是具体的功能:

#[naked]
pub extern "C" fn dispatch_svc(){
    Cpu::save_context();
    let mut nr: u32 = 0;
    unsafe {
        asm!("ldr r0, [lr, #-4]
              bic $0, r0, #0xff000000":"=r"(nr)::"r0":"volatile")
    };
    swi_service_routine(nr);
    Cpu::restore_context_and_return();
}

最佳答案

据我所知,除了整个 crate 之外,Rust 没有任何工具可以指定任何东西的优化级别。
您唯一的解决方法是在单独的 crate 中编译此函数,编译它,然后将其作为预编译依赖项包含在内。 (正常的rust-dependency是在depender的优化级别编译的)

但是:为这个单一函数指定不同的优化级别不会解决您的问题!当然,它今天可能会工作,但每次编译器(或优化标志)更改时可能会再次中断。

TL;博士 :裸函数非常不安全(我的敬意,你比我更勇敢!)。
使用它们的唯一可靠方法是只写一个 asm!()块作为整个函数体,没有别的。
混音asm! ,像您正在执行的正常 Rust 和函数调用实际上是未定义行为(在术语的可怕 C/Nasal-Demon 意义上)再多的优化调整也无法改变这一点。

裸函数仍然不稳定,直到 Rust 的作者“把它弄好”。
正如您所发现的,这有许多微妙的问题。稳定跟踪问题 here

naked-fn RFC ,在“动机”下,我们发现:

Because the compiler depends on a function prologue and epilogue to maintain storage for local variable bindings, it is generally unsafe to write anything but inline assembly inside a naked function. The LLVM language reference describes this feature as having "very system-specific consequences", which the programmer must be aware of.



(强调我的)

在 RFC 中稍低一点,在 unresolved questions 下,我们了解到这不仅仅是 Rust 的问题。其他语言也遇到此功能的问题:

.. most compilers supporting similar features either require or strongly recommend that authors write only inline assembly inside naked functions to ensure no code is generated that assumes a particular stack layout.



原因是所有编译器对函数的调用方式做了很多假设(关键字:“调用者保存的寄存器”、“被调用者保存的寄存器”、“调用约定”、“红区”)。裸函数不遵守这些假设,因此编译器生成的任何代码都极有可能是错误的。 “解决方案”是不要让编译器生成任何东西,即在汇编中手工编写整个函数。

因此,您在裸函数中混合“正常”代码( let mut nr: u32 = 0; )、函数调用( swi_service_routine(nr); )和原始汇编程序的方式是 未指明的行为 . (是的,这种东西存在于 Rust 中,但只存在于 Unstable 中)。

裸函数会引起足够多的问题 their own label在 Rust 错误跟踪器中。
在其中一个 A-naked 问题中,我们发现 this comment ,由知识渊博的用户 Tari(其中包括 llvm-sys 的作者)撰写。他解释说:

The actual correctness of non-asm code in naked functions depends on the optimizer and code generator, which in general we cannot make any guarantees about what it will do.



还有说要求unsafe对于裸函数,因为它们破坏了 Rust 的许多正常假设。事实上,他们在所有情况下都不需要这样做 is an open bug

所以,正确的解决方案 你的“优化问题”是完全停止依赖优化。相反,只写一个 asm!()块。

为您 Cpu::save_context()/Cpu::restore_context_and_return()对:我能理解对代码重用的渴望。要获得它,请将它们更改为插入相关 asm!(...) 的宏。 . asm!(...); asm!(...); asm!(...); 的串联应该相当于单个 asm!() .

关于optimization - 我可以强制 Rust 不优化单个函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44137890/

相关文章:

MySQL:优化 GROUP BY 多个键

c++ - 存储一个函数c++,稍后调用

php - PDO查询错误: 2013 Lost connection to MySQL server during query [Need Optimization Help]

rust - 条件语句中的链接是惯用的 rust 迹吗?

string - 如何在 Rust 中索引字符串

module - 为什么这个模块不可见?

optimization - 为什么这段代码生成的汇编比等效的 C++/Clang 多得多?

java - 优化Java中的Draw方法

types - LLVM的整数类型

rust - Rust 的 128 位整数 `i128` 如何在 64 位系统上工作?