为了编写编译器优化,我编写了一个简单的C++函数:

bool f1(bool a, bool b) {
    return !a || (a && b);
}

在那之后,我判断了 rust 蚀的等效物:

fn f1(a: bool, b: bool) -> bool {
    !a || (a && b)
}

我用godbolt判断汇编程序的输出.

C++代码的结果(用-O3标记的CLAN编译)如下:

f1(bool, bool):                                # @f1(bool, bool)
    xor     dil, 1
    or      dil, sil
    mov     eax, edi
    ret

rust 当量的结果要长得多:

example::f1:
  push rbp
  mov rbp, rsp
  mov al, sil
  mov cl, dil
  mov dl, cl
  xor dl, -1
  test dl, 1
  mov byte ptr [rbp - 3], al
  mov byte ptr [rbp - 4], cl
  jne .LBB0_1
  jmp .LBB0_3
.LBB0_1:
  mov byte ptr [rbp - 2], 1
  jmp .LBB0_4
.LBB0_2:
  mov byte ptr [rbp - 2], 0
  jmp .LBB0_4
.LBB0_3:
  mov al, byte ptr [rbp - 4]
  test al, 1
  jne .LBB0_7
  jmp .LBB0_6
.LBB0_4:
  mov al, byte ptr [rbp - 2]
  and al, 1
  movzx eax, al
  pop rbp
  ret
.LBB0_5:
  mov byte ptr [rbp - 1], 1
  jmp .LBB0_8
.LBB0_6:
  mov byte ptr [rbp - 1], 0
  jmp .LBB0_8
.LBB0_7:
  mov al, byte ptr [rbp - 3]
  test al, 1
  jne .LBB0_5
  jmp .LBB0_6
.LBB0_8:
  test byte ptr [rbp - 1], 1
  jne .LBB0_1
  jmp .LBB0_2

我也try 了-O选项,但输出是空的(删除了未使用的函数).

我故意不使用任何库来保持输出干净.请注意,clangrustc都使用LLVM作为后端.是什么解释了这种巨大的输出差异?如果只是禁用优化switch 问题,我怎么能看到rustc的优化输出?

推荐答案

使用编译器标志-O(and with an added pub)编译时,我得到以下输出(Link to Godbolt):

push    rbp
mov     rbp, rsp
xor     dil, 1
or      dil, sil
mov     eax, edi
pop     rbp
ret

有几件事:

  • Why is it still longer than the C++ version?

    rust 迹斑斑的版本正好长了三条说明:

    push    rbp
    mov     rbp, rsp
    [...]
    pop     rbp
    

    这些是管理所谓的帧指针或base指针(rbp)的指令.这主要是为了获得好的堆栈跟踪.如果您通过-fno-omit-frame-pointer, you get the same result禁用它的C++版本.请注意,自从I haven't found a comparable option for the clang compiler以来,它使用的是g++而不是clang++.

  • Why doesn't Rust omit frame pointer?

    事实上,的确如此.但是Godbolt为编译器添加了一个选项来保留帧指针.你可以阅读更多关于为什么要这样做的信息.如果使用rustc -O --crate-type=lib foo.rs --emit asm -C "llvm-args=-x86-asm-syntax=intel"在本地编译代码,则会得到以下输出:

    f1:
        xor dil, 1
        or  dil, sil
        mov eax, edi
        ret
    

    它是你的C++版本的exactly.

    你可以在passing -C debuginfo=0 to the compiler之前"撤销"Godbolt的功能.

  • Why 100 instead of 101?

    Godbolt直接使用rustc而不是cargo.--release旗是cargo旗.要在rustc上启用优化,您需要通过-O-C opt-level=3(或0到3之间的任何其他级别).

Rust相关问答推荐

如何定义使用拥有的字符串并返回拥有的Split的Rust函数?

文档示例需要导入相关的 struct ,但仅在运行测试时.这是故意的行为吗?

在Rust中赋值变量有运行时开销吗?

为什么BitVec缺少Serialize trait?

同时从不同线程调用DLL的不同函数会出现分段错误或产生STATUS_STACK_BUFFER_OVERRUN

为什么`AlternateScreen`在读取输入键时需要按Enter键?

失真图像图形捕获Api

为什么RefCell没有与常规引用相同的作用域?

如何执行数组文字的编译时串联?

在使用粗粒度锁访问的数据 struct 中使用 RefCell 是否安全?

带引脚和不带引脚的比较功能

Nom 解析器无法消耗无效输入

中文优化标题:跳出特定循环并返回一个值

如何从 rust 中的同一父目录导入文件

在多核嵌入式 Rust 中,我可以使用静态 mut 进行单向数据共享吗?

push 方法是否取得所有权?

判断对象是 PyDatetime 还是 Pydate 的实例?

从现有系列和 map 值创建新系列

为什么 Rust 编译器在移动不可变值时执行复制?

为什么可以从闭包中返回私有 struct