Sebi2020
Sebi2020

Reputation: 2159

Why does moving a value generate LLVM IR that includes a value copy?

If I assign a variable (with a type without copy semantics) to a second one, rustc creates a copy of the value even if the first one cannot be used/accessed anymore.

For example:

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

This generates LLVM IR which contains two store operations:

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

Isn't it unnecessary workload to copy values with move semantics if the first copy cannot be used anymore?

Upvotes: 0

Views: 272

Answers (2)

idmean
idmean

Reputation: 14915

LLVM was specifically designed to perform optimizations. A front-end will try to encode everything it knows about the operations being performed in the LLVM IR and then invoke optimizations upon the LLVM IR.

If you turn on optimizations you'll indeed only get:

  %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 has been optimized away entirely.

https://godbolt.org/z/fW9457eEn

Upvotes: 2

Hauleth
Hauleth

Reputation: 23586

Because copy vs move is language semantics not how it is done in the generated code. Rust always (maybe that have changed?) generates copy and then just logically disallows usage of the moved value. It relies on LLVM ability to remove unneeded copies.

Upvotes: 0

Related Questions