如何解决为什么移动值会生成包含值副本的 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,i32* %v2,align 4
如果不能再使用第一个副本,那么使用移动语义复制值不是不必要的工作量吗?
解决方法
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
,因为复制与移动是语言语义,而不是在生成的代码中是如何完成的。 Rust 总是(也许已经改变了?)生成副本,然后在逻辑上禁止使用移动的值。它依赖于 LLVM 删除不需要的副本的能力。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。