rust-lang/rust — pull request #15145 by dotdash (2014-06-24 12:32:25+00:00)
Title: Avoid unnecessary temporary on assignments

We only need the temporary when the type needs to be dropped, for other
types, we can use trans_into to directly place the value into the
destination.

This avoids some constructs that LLVM optimizes poorly because of partially
overlapping memcpys. Those currently appear, for example, when inserting a
value into a SmallIntMap.

Code:
```rust
struct S {
x1: int,
x2: int,
x3: int,
x4: int,
x5: int,
}

pub fn assigner(dst: &mut Option, src: &S) {
*dst = Some(*src);
}
```

Before:
```llvm
define void @_ZN8assigner20h188065bb03d68d67taa4v0.0E(%"enum.core::option::Option<[S]>[#3]"* noalias nocapture nonnull, %"struct.S<[]>"* nocapture nonnull readonly) unnamed_addr #0 {
entry-block:
%.sroa.2 = alloca [47 x i8], align 1
%2 = bitcast %"struct.S<[]>"* %1 to i8*
%.sroa.2.8..sroa_idx = getelementptr inbounds [47 x i8]* %.sroa.2, i64 0, i64 7
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %.sroa.2.8..sroa_idx, i8* %2, i64 40, i32 1, i1 false)
%.sroa.0.0..sroa_idx = getelementptr inbounds %"enum.core::option::Option<[S]>[#3]"* %0, i64 0, i32 0
store i8 1, i8* %.sroa.0.0..sroa_idx, align 8
%.sroa.2.0..sroa_idx = getelementptr inbounds %"enum.core::option::Option<[S]>[#3]"* %0, i64 0, i32 1, i64 0
%.sroa.2.0..sroa_idx1 = getelementptr inbounds [47 x i8]* %.sroa.2, i64 0, i64 0
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %.sroa.2.0..sroa_idx, i8* %.sroa.2.0..sroa_idx1, i64 47, i32 1, i1 false)
ret void
}
```

After:
```llvm
define void @_ZN8assigner20h188065bb03d68d67taa4v0.0E(%"enum.core::option::Option<[S]>[#3]"* noalias nocapture nonnull, %"struct.S<[]>"* nocapture nonnull readonly) unnamed_addr #0 {
entry-block:
%2 = bitcast %"struct.S<[]>"* %1 to i8*
%3 = getelementptr inbounds %"enum.core::option::Option<[S]>[#3]"* %0, i64 0, i32 0
store i8 1, i8* %3, align 8
%4 = getelementptr inbounds %"enum.core::option::Option<[S]>[#3]"* %0, i64 0, i32 2
%5 = bitcast [5 x i64]* %4 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %5, i8* %2, i64 40, i32 8, i1 false)
ret void
}
```