unsigned int memcpyx2(unsigned char *dst, unsigned char *src,
                      unsigned int len) {
  int x, y;
  for (x = y = 0; (y < len);) {
    dst[y++] = src[x];
    dst[y++] = src[x++];
  }
  return (len);
}


x86 assembly (clang, -O0):
<memcpyx2>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movl   $0x0,-0x1c(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x1c(%rbp),%eax
cmp    -0x14(%rbp),%eax
jae    1178 <memcpyx2+0x78>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    (%rax,%rcx,1),%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
mov    %ecx,%edx
add    $0x1,%edx
mov    %edx,-0x18(%rbp)
movslq %ecx,%rcx
mov    (%rax,%rcx,1),%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
jmp    111d <memcpyx2+0x1d>
mov    -0x14(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<memcpyx2>:
push   %rbx
mov    %edx,%eax
test   %edx,%edx
je     11f0 <memcpyx2+0xf0>
lea    -0x1(%rax),%ecx
mov    %ecx,%r8d
shr    %r8d
add    $0x1,%r8d
cmp    $0x1e,%ecx
jb     1137 <memcpyx2+0x37>
lea    (%rsi,%r8,1),%rcx
cmp    %rdi,%rcx
jbe    11b0 <memcpyx2+0xb0>
lea    (%rdi,%r8,2),%rcx
cmp    %rsi,%rcx
jbe    11b0 <memcpyx2+0xb0>
xor    %ebx,%ebx
xor    %r10d,%r10d
mov    %rbx,%r9
not    %r9
test   $0x1,%r8b
je     1167 <memcpyx2+0x67>
mov    (%rsi,%rbx,1),%r11b
mov    %r10,%rcx
or     $0x1,%rcx
mov    %r11b,(%rdi,%r10,1)
mov    (%rsi,%rbx,1),%r11b
or     $0x1,%rbx
add    $0x2,%r10
mov    %r11b,(%rdi,%rcx,1)
add    %r8,%r9
je     11f0 <memcpyx2+0xf0>
movzbl (%rsi,%rbx,1),%r9d
mov    %r10,%rcx
or     $0x1,%rcx
mov    %r9b,(%rdi,%r10,1)
movzbl (%rsi,%rbx,1),%edx
mov    %dl,(%rdi,%rcx,1)
movzbl 0x1(%rsi,%rbx,1),%ecx
lea    0x2(%r10),%rdx
or     $0x1,%rdx
mov    %cl,0x2(%rdi,%r10,1)
movzbl 0x1(%rsi,%rbx,1),%ecx
add    $0x2,%rbx
mov    %cl,(%rdi,%rdx,1)
add    $0x4,%r10
cmp    %rbx,%r8
jne    1170 <memcpyx2+0x70>
jmp    11f0 <memcpyx2+0xf0>
mov    %r8d,%ebx
and    $0xfffffff0,%ebx
lea    (%rbx,%rbx,1),%r10
xor    %ecx,%ecx
nopl   0x0(%rax)
movq   (%rsi,%rcx,1),%xmm0
movq   0x8(%rsi,%rcx,1),%xmm1
punpcklbw %xmm0,%xmm0
movdqu %xmm0,(%rdi,%rcx,2)
punpcklbw %xmm1,%xmm1
movdqu %xmm1,0x10(%rdi,%rcx,2)
add    $0x10,%rcx
cmp    %rcx,%rbx
jne    11c0 <memcpyx2+0xc0>
cmp    %r8,%rbx
jne    113c <memcpyx2+0x3c>
pop    %rbx
ret

LLVM IR (-O0):
define i32 @memcpyx2(i8* %0, i8* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
store i8* %0, i8** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
store i32 0, i32* %8
store i32 0, i32* %7
br label %9
9: ; preds = %13, %3
%10 = load i32, i32* %8
%11 = load i32, i32* %6
%12 = icmp ult i32 %10, %11
br i1 %12, label %13, label %35
13: ; preds = %9
%14 = load i8*, i8** %5
%15 = load i32, i32* %7
%16 = sext i32 %15 to i64
%17 = getelementptr inbounds i8, i8* %14, i64 %16
%18 = load i8, i8* %17
%19 = load i8*, i8** %4
%20 = load i32, i32* %8
%21 = add nsw i32 %20, 1
store i32 %21, i32* %8
%22 = sext i32 %20 to i64
%23 = getelementptr inbounds i8, i8* %19, i64 %22
store i8 %18, i8* %23
%24 = load i8*, i8** %5
%25 = load i32, i32* %7
%26 = add nsw i32 %25, 1
store i32 %26, i32* %7
%27 = sext i32 %25 to i64
%28 = getelementptr inbounds i8, i8* %24, i64 %27
%29 = load i8, i8* %28
%30 = load i8*, i8** %4
%31 = load i32, i32* %8
%32 = add nsw i32 %31, 1
store i32 %32, i32* %8
%33 = sext i32 %31 to i64
%34 = getelementptr inbounds i8, i8* %30, i64 %33
store i8 %29, i8* %34
br label %9
35: ; preds = %9
%36 = load i32, i32* %6
ret i32 %36
}

LLVM IR (-O2):
define i32 @memcpyx2(i8* nocapture writeonly %0, i8* nocapture %1, i32 returned %2) {
%4 = icmp eq i32 %2, 0
br i1 %4, label %87, label %5
5: ; preds = %3
%6 = add i32 %2, -1
%7 = lshr i32 %6, 1
%8 = add nuw i32 %7, 1
%9 = zext i32 %8 to i64
%10 = icmp ult i32 %6, 30
br i1 %10, label %47, label %11
11: ; preds = %5
%12 = shl nuw nsw i64 %9, 1
%13 = getelementptr i8, i8* %0, i64 %12
%14 = getelementptr i8, i8* %1, i64 %9
%15 = icmp ugt i8* %14, %0
%16 = icmp ugt i8* %13, %1
%17 = and i1 %15, %16
br i1 %17, label %47, label %18
18: ; preds = %11
%19 = and i64 %9, 4294967280
%20 = shl nuw nsw i64 %19, 1
%21 = getelementptr inbounds i8, i8* %0, i64 -1
%22 = getelementptr inbounds i8, i8* %0, i64 -1
br label %23
23: ; preds = %23, %18
%24 = phi i64 [ 0, %18 ], [ %43, %23 ]
%25 = shl i64 %24, 1
%26 = getelementptr inbounds i8, i8* %1, i64 %24
%27 = bitcast i8* %26 to <8 x i8>*
%28 = load <8 x i8>, <8 x i8>* %27
%29 = getelementptr inbounds i8, i8* %26, i64 8
%30 = bitcast i8* %29 to <8 x i8>*
%31 = load <8 x i8>, <8 x i8>* %30
%32 = or i64 %25, 1
%33 = or i64 %25, 17
%34 = bitcast i8* %26 to <8 x i8>*
%35 = load <8 x i8>, <8 x i8>* %34
%36 = getelementptr inbounds i8, i8* %21, i64 %32
%37 = bitcast i8* %36 to <16 x i8>*
%38 = getelementptr inbounds i8, i8* %22, i64 %33
%39 = bitcast i8* %38 to <16 x i8>*
%40 = shufflevector <8 x i8> %28, <8 x i8> %35, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %40, <16 x i8>* %37
%41 = shufflevector <8 x i8> %31, <8 x i8> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
%42 = shufflevector <16 x i8> %41, <16 x i8> poison, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %42, <16 x i8>* %39
%43 = add nuw i64 %24, 16
%44 = icmp eq i64 %43, %19
br i1 %44, label %45, label %23
45: ; preds = %23
%46 = icmp eq i64 %19, %9
br i1 %46, label %87, label %47
47: ; preds = %11, %5, %45
%48 = phi i64 [ 0, %11 ], [ 0, %5 ], [ %19, %45 ]
%49 = phi i64 [ 0, %11 ], [ 0, %5 ], [ %20, %45 ]
%50 = xor i64 %48, -1
%51 = and i64 %9, 1
%52 = icmp eq i64 %51, 0
br i1 %52, label %62, label %53
53: ; preds = %47
%54 = getelementptr inbounds i8, i8* %1, i64 %48
%55 = load i8, i8* %54
%56 = or i64 %49, 1
%57 = getelementptr inbounds i8, i8* %0, i64 %49
store i8 %55, i8* %57
%58 = or i64 %48, 1
%59 = load i8, i8* %54
%60 = add nuw nsw i64 %49, 2
%61 = getelementptr inbounds i8, i8* %0, i64 %56
store i8 %59, i8* %61
br label %62
62: ; preds = %53, %47
%63 = phi i64 [ %48, %47 ], [ %58, %53 ]
%64 = phi i64 [ %49, %47 ], [ %60, %53 ]
%65 = sub nsw i64 0, %9
%66 = icmp eq i64 %50, %65
br i1 %66, label %87, label %67
67: ; preds = %62, %67
%68 = phi i64 [ %82, %67 ], [ %63, %62 ]
%69 = phi i64 [ %84, %67 ], [ %64, %62 ]
%70 = getelementptr inbounds i8, i8* %1, i64 %68
%71 = load i8, i8* %70
%72 = or i64 %69, 1
%73 = getelementptr inbounds i8, i8* %0, i64 %69
store i8 %71, i8* %73
%74 = add nuw nsw i64 %68, 1
%75 = load i8, i8* %70
%76 = add nuw nsw i64 %69, 2
%77 = getelementptr inbounds i8, i8* %0, i64 %72
store i8 %75, i8* %77
%78 = getelementptr inbounds i8, i8* %1, i64 %74
%79 = load i8, i8* %78
%80 = or i64 %76, 1
%81 = getelementptr inbounds i8, i8* %0, i64 %76
store i8 %79, i8* %81
%82 = add nuw nsw i64 %68, 2
%83 = load i8, i8* %78
%84 = add nuw nsw i64 %69, 4
%85 = getelementptr inbounds i8, i8* %0, i64 %80
store i8 %83, i8* %85
%86 = icmp eq i64 %82, %9
br i1 %86, label %87, label %67
87: ; preds = %62, %67, %45, %3
ret i32 %2
}