Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid unnecessary temporary on assignments #15145

Closed
wants to merge 1 commit into from

Conversation

dotdash
Copy link
Contributor

@dotdash dotdash commented Jun 24, 2014

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:

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

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

Before:

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:

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
}

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.
@dotdash dotdash deleted the assign_into branch February 4, 2015 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants