首页 > 解决方案 > 为什么移动值会生成包含值副本的 LLVM IR?

问题描述

如果我将一个变量(具有没有复制语义的类型)分配给第二个变量,即使第一个变量不能再使用/访问,rustc 也会创建该值的副本。

例如:

#[derive(Debug)]
struct T {
    val: i32,
}
fn main() {
    let v1 = T { val: 123 };
    let v2 = v1;
    // println!("{:?}", v1); error!
    println!("{:?}", v2);
}

这会生成包含两个存储操作的 LLVM IR:

  %v2 = alloca i32, align 4
  %v1 = alloca i32, align 4
  store i32 123, i32* %v1, align 4
  store i32 123, i32* %v2, align 4

如果不能再使用第一个副本,那么使用移动语义复制值是否不必要的工作量?

标签: rustmove

解决方案


LLVM 专门设计用于执行优化。前端将尝试对它所知道的有关 LLVM IR 中正在执行的操作的所有内容进行编码,然后在 LLVM IR 上调用优化。

如果您打开优化,您确实只会得到:

  %v2 = alloca i32, align 4
  %0 = bitcast i32* %v2 to i8*, !dbg !36
  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0), !dbg !36
  store i32 123, i32* %v2, align 4, !dbg !37

%v1已经完全优化掉了。

https://godbolt.org/z/fW9457eEn


推荐阅读