简体   繁体   English

我如何真正禁用所有 rustc 优化?

[英]How do I really disable all rustc optimizations?

I'm trying to learn assembly through compiling Rust. I have found a way to compile Rust code to binary machine code and be able to objdump it to view the assembly.我正在尝试通过编译 Rust 来学习汇编。我找到了一种将 Rust 代码编译为二进制机器代码并能够对其进行objdump以查看程序集的方法。 However if I write the following:但是,如果我写以下内容:

#![no_main]

#[link_section = ".text.entry"]
#[no_mangle]
pub extern "C" fn _start() -> ! {
    let a: u64 = 4;
    let b: u64 = 7;
    let c: u64 = a * b;
    
    loop {}
}

The assembly I get is:我得到的程序集是:

0000000000000000 <.data>:
   0:   1101                    addi    sp,sp,-32
   2:   4511                    li      a0,4
   4:   e42a                    sd      a0,8(sp)
   6:   451d                    li      a0,7
   8:   e82a                    sd      a0,16(sp)
   a:   4571                    li      a0,28
   c:   ec2a                    sd      a0,24(sp)
   e:   a009                    j       0x10
  10:   a001                    j       0x10

So it looks like rust is collapsing the mul to a constant.所以看起来 rust 正在将 mul 压缩为一个常数。 I'm using the following compile options:我正在使用以下编译选项:

Cargo.toml:货物.toml:

[profile.dev]
opt-level = 0
mir-opt-level = 0

Is there a way to stop Rust from optimizing this?有没有办法阻止 Rust 对此进行优化?

The LLVM emitted looks like this:发出的 LLVM 如下所示:

; Function Attrs: noreturn nounwind
define dso_local void @_start() unnamed_addr #0 section ".text.entry" !dbg !22 {
start:
  %c.dbg.spill = alloca i64, align 8
  %b.dbg.spill = alloca i64, align 8
  %a.dbg.spill = alloca i64, align 8
  store i64 4, i64* %a.dbg.spill, align 8, !dbg !36
  call void @llvm.dbg.declare(metadata i64* %a.dbg.spill, metadata !28, metadata !DIExpression()), !dbg !37
  store i64 7, i64* %b.dbg.spill, align 8, !dbg !38
  call void @llvm.dbg.declare(metadata i64* %b.dbg.spill, metadata !31, metadata !DIExpression()), !dbg !39
  store i64 28, i64* %c.dbg.spill, align 8, !dbg !40
  call void @llvm.dbg.declare(metadata i64* %c.dbg.spill, metadata !33, metadata !DIExpression()), !dbg !41

So it looks like the optimization is before the LLVM pass.所以看起来优化是在 LLVM 通过之前进行的。

$ rustc --version                                                                                                                                           
rustc 1.60.0-nightly (c5c610aad 2022-02-14)

Command to build:命令构建:

RUSTFLAGS="--emit=llvm-bc" cargo build --target riscv64imac-unknown-none-elf --no-default-features

build.rs构建器.rs

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rustc-link-arg=-Tlink.ld");
}

link.ld链接.ld

ENTRY(_start)
SECTIONS {
  .text : { *(.text); *(.text.*) }
}

There is one compiler pass before the generation of LLVM-IR, which is the generation of MIR , the Rust intermediate representation.在生成 LLVM-IR 之前有一个编译器通道,即MIR的生成,即 Rust 中间表示。 If you emit this for the given code with a command such as this one:如果您使用如下命令为给定代码发出此命令:

cargo rustc -- --emit mir

You will see in the.mir file generated that the optimization already took place there.您将在生成的 .mir 文件中看到优化已经在那里进行。

fn _start() -> ! {
    let mut _0: !;                       // return place in scope 0 at src\main.rs:5:31: 5:32
    let _1: u64;                         // in scope 0 at src\main.rs:6:9: 6:10
    scope 1 {
        debug a => _1;                   // in scope 1 at src\main.rs:6:9: 6:10
        let _2: u64;                     // in scope 1 at src\main.rs:7:9: 7:10
        scope 2 {
            debug b => _2;               // in scope 2 at src\main.rs:7:9: 7:10
            let _3: u64;                 // in scope 2 at src\main.rs:8:9: 8:10
            scope 3 {
                debug c => _3;           // in scope 3 at src\main.rs:8:9: 8:10
            }
        }
    }

    bb0: {
        _1 = const 4_u64;                // scope 0 at src\main.rs:6:18: 6:19
        _2 = const 7_u64;                // scope 1 at src\main.rs:7:18: 7:19
        _3 = const 28_u64;               // scope 2 at src\main.rs:8:18: 8:23
        goto -> bb1;                     // scope 3 at src\main.rs:10:5: 10:12
    }

    bb1: {
        goto -> bb1;                     // scope 3 at src\main.rs:10:5: 10:12
    }
}

This is happening because the mir-opt-level option currently only exists as an unstable compiler option .发生这种情况是因为mir-opt-level选项目前仅作为一个不稳定的编译器选项存在。 It is not available as a profile property in Cargo.不能作为 Cargo 中的配置文件属性使用。 Set it manually on a direct call to the compiler:在直接调用编译器时手动设置它:

cargo rustc -- -Z mir-opt-level=0 --emir mir

And this optimization will disappear:而这种优化将消失:

fn _start() -> ! {
    let mut _0: !;                       // return place in scope 0 at src\main.rs:5:31: 5:32
    let mut _1: !;                       // in scope 0 at src\main.rs:5:33: 11:2
    let _2: u64;                         // in scope 0 at src\main.rs:6:9: 6:10
    let mut _5: u64;                     // in scope 0 at src\main.rs:8:18: 8:19
    let mut _6: u64;                     // in scope 0 at src\main.rs:8:22: 8:23
    let mut _7: (u64, bool);             // in scope 0 at src\main.rs:8:18: 8:23
    let mut _8: !;                       // in scope 0 at src\main.rs:10:5: 10:12
    let mut _9: ();                      // in scope 0 at src\main.rs:5:1: 11:2
    scope 1 {
        debug a => _2;                   // in scope 1 at src\main.rs:6:9: 6:10
        let _3: u64;                     // in scope 1 at src\main.rs:7:9: 7:10
        scope 2 {
            debug b => _3;               // in scope 2 at src\main.rs:7:9: 7:10
            let _4: u64;                 // in scope 2 at src\main.rs:8:9: 8:10
            scope 3 {
                debug c => _4;           // in scope 3 at src\main.rs:8:9: 8:10
            }
        }
    }

    bb0: {
        StorageLive(_1);                 // scope 0 at src\main.rs:5:33: 11:2
        StorageLive(_2);                 // scope 0 at src\main.rs:6:9: 6:10
        _2 = const 4_u64;                // scope 0 at src\main.rs:6:18: 6:19
        StorageLive(_3);                 // scope 1 at src\main.rs:7:9: 7:10
        _3 = const 7_u64;                // scope 1 at src\main.rs:7:18: 7:19
        StorageLive(_4);                 // scope 2 at src\main.rs:8:9: 8:10
        StorageLive(_5);                 // scope 2 at src\main.rs:8:18: 8:19
        _5 = _2;                         // scope 2 at src\main.rs:8:18: 8:19
        StorageLive(_6);                 // scope 2 at src\main.rs:8:22: 8:23
        _6 = _3;                         // scope 2 at src\main.rs:8:22: 8:23
        _7 = CheckedMul(_5, _6);         // scope 2 at src\main.rs:8:18: 8:23
        assert(!move (_7.1: bool), "attempt to compute `{} * {}`, which would overflow", move _5, move _6) -> bb1; // scope 2 at src\main.rs:8:18: 8:23
    }

    bb1: {
        _4 = move (_7.0: u64);           // scope 2 at src\main.rs:8:18: 8:23
        StorageDead(_6);                 // scope 2 at src\main.rs:8:22: 8:23
        StorageDead(_5);                 // scope 2 at src\main.rs:8:22: 8:23
        StorageLive(_8);                 // scope 3 at src\main.rs:10:5: 10:12
        goto -> bb2;                     // scope 3 at src\main.rs:10:5: 10:12
    }

    bb2: {
        _9 = const ();                   // scope 3 at src\main.rs:10:10: 10:12
        goto -> bb2;                     // scope 3 at src\main.rs:10:5: 10:12
    }
}

And this is probably as far as you can go without touching LLVM directly.这可能是您在不直接接触 LLVM 的情况下所能达到的最大程度 go。 Some optimisations in specific parts of the code can also be prevented through constructs such as black_box .代码特定部分的一些优化也可以通过诸如black_box类的结构来阻止。

See also:也可以看看:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何更改默认的 rustc / Cargo 链接器? - How do I change the default rustc / Cargo linker? 我们如何为同一台 linux 机器上的所有用户安装 rustc、cargo? - How do we install rustc, cargo for all the users in the same linux machine? 如何配置SublimeLinter-contrib-rustc以找到“活塞”箱? - How do I configure SublimeLinter-contrib-rustc to find the “piston” crate? 如何相对于项目位置进行 rustc-link-search? - How do I make rustc-link-search relative to the project location? 如何指定交叉编译rustc时要使用的编译器? - How do I specify the compiler to use when cross-compiling rustc? 使用 rustc 编译代码时如何指定要使用的版本? - How do I specify the edition to use when compiling code using rustc? 我如何查询主机三元组的 rustc? - How can I query rustc for the host triple? "<i>Can compilers (specifically rustc) really simplify triangle-summation to avoid a loop?<\/i>编译器(特别是 rustc)真的可以简化三角求和以避免循环吗?<\/b> <i>How?<\/i>如何?<\/b>" - Can compilers (specifically rustc) really simplify triangle-summation to avoid a loop? How? 我应该如何更新 Rustup 的版本? 不更新 rustc 或 cargo 的版本 - How should I update the version of Rustup? not updating the version of rustc or cargo 如何使用 `rustc` 板条箱? - How to use `rustc` crate?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM