void string_utf16(char *dest, char *src, int len) {
  int i;
  for (i = 0; i < len; i++) {
    dest[i * 2] = src[i];
    dest[i * 2 + 1] = 0;
  }
  dest[i * 2] = 0;
  dest[i * 2 + 1] = 0;
}


x86 assembly (clang, -O0):
<string_utf16>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    115f <string_utf16+0x5f>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    (%rax,%rcx,1),%dl
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%ecx
shl    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movb   $0x0,(%rax,%rcx,1)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1116 <string_utf16+0x16>
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%ecx
shl    $0x1,%ecx
movslq %ecx,%rcx
movb   $0x0,(%rax,%rcx,1)
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movb   $0x0,(%rax,%rcx,1)
pop    %rbp
ret

x86 assembly (clang, -O2):
<string_utf16>:
test   %edx,%edx
jle    1178 <string_utf16+0x78>
mov    %edx,%r8d
cmp    $0x10,%edx
jb     111e <string_utf16+0x1e>
lea    (%rsi,%r8,1),%rax
cmp    %rdi,%rax
jbe    117f <string_utf16+0x7f>
lea    (%rdi,%r8,2),%rax
cmp    %rsi,%rax
jbe    117f <string_utf16+0x7f>
xor    %ecx,%ecx
mov    %rcx,%r9
not    %r9
test   $0x1,%r8b
je     113b <string_utf16+0x3b>
mov    (%rsi,%rcx,1),%al
mov    %al,(%rdi,%rcx,2)
movb   $0x0,0x1(%rdi,%rcx,2)
or     $0x1,%rcx
add    %r8,%r9
je     1232 <string_utf16+0x132>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movzbl (%rsi,%rcx,1),%eax
mov    %al,(%rdi,%rcx,2)
movb   $0x0,0x1(%rdi,%rcx,2)
movzbl 0x1(%rsi,%rcx,1),%eax
mov    %al,0x2(%rdi,%rcx,2)
movb   $0x0,0x3(%rdi,%rcx,2)
add    $0x2,%rcx
cmp    %rcx,%r8
jne    1150 <string_utf16+0x50>
jmp    1232 <string_utf16+0x132>
xor    %edx,%edx
jmp    1234 <string_utf16+0x134>
mov    %r8d,%ecx
and    $0xfffffff0,%ecx
lea    -0x10(%rcx),%rax
mov    %rax,%r9
shr    $0x4,%r9
add    $0x1,%r9
test   %rax,%rax
je     1243 <string_utf16+0x143>
mov    %r9,%r10
and    $0xfffffffffffffffe,%r10
xor    %eax,%eax
pxor   %xmm0,%xmm0
nopw   0x0(%rax,%rax,1)
movq   (%rsi,%rax,1),%xmm1
movq   0x8(%rsi,%rax,1),%xmm2
punpcklbw %xmm0,%xmm1
movdqu %xmm1,(%rdi,%rax,2)
punpcklbw %xmm0,%xmm2
movdqu %xmm2,0x10(%rdi,%rax,2)
movq   0x10(%rsi,%rax,1),%xmm1
movq   0x18(%rsi,%rax,1),%xmm2
punpcklbw %xmm0,%xmm1
movdqu %xmm1,0x20(%rdi,%rax,2)
punpcklbw %xmm0,%xmm2
movdqu %xmm2,0x30(%rdi,%rax,2)
add    $0x20,%rax
add    $0xfffffffffffffffe,%r10
jne    11b0 <string_utf16+0xb0>
test   $0x1,%r9b
je     1229 <string_utf16+0x129>
movq   (%rsi,%rax,1),%xmm0
movq   0x8(%rsi,%rax,1),%xmm1
lea    (%rax,%rax,1),%r9
or     $0x11,%r9
pxor   %xmm2,%xmm2
punpcklbw %xmm2,%xmm0
movdqu %xmm0,(%rdi,%rax,2)
punpcklbw %xmm2,%xmm1
movdqu %xmm1,-0x1(%rdi,%r9,1)
cmp    %r8,%rcx
jne    1120 <string_utf16+0x20>
add    %edx,%edx
mov    %edx,%eax
movb   $0x0,(%rdi,%rax,1)
or     $0x1,%rax
movb   $0x0,(%rdi,%rax,1)
ret
xor    %eax,%eax
test   $0x1,%r9b
jne    11fe <string_utf16+0xfe>
jmp    1229 <string_utf16+0x129>

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

LLVM IR (-O2):
define void @string_utf16(i8* nocapture writeonly %0, i8* nocapture %1, i32 %2) {
%4 = icmp sgt i32 %2, 0
br i1 %4, label %5, label %127
5: ; preds = %3
%6 = zext i32 %2 to i64
%7 = icmp ult i32 %2, 16
br i1 %7, label %91, label %8
8: ; preds = %5
%9 = shl nuw nsw i64 %6, 1
%10 = getelementptr i8, i8* %0, i64 %9
%11 = getelementptr i8, i8* %1, i64 %6
%12 = icmp ugt i8* %11, %0
%13 = icmp ugt i8* %10, %1
%14 = and i1 %12, %13
br i1 %14, label %91, label %15
15: ; preds = %8
%16 = and i64 %6, 4294967280
%17 = add nsw i64 %16, -16
%18 = lshr exact i64 %17, 4
%19 = add nuw nsw i64 %18, 1
%20 = and i64 %19, 1
%21 = icmp eq i64 %17, 0
br i1 %21, label %67, label %22
22: ; preds = %15
%23 = and i64 %19, 2305843009213693950
%24 = getelementptr inbounds i8, i8* %0, i64 -1
%25 = getelementptr inbounds i8, i8* %0, i64 -1
%26 = getelementptr inbounds i8, i8* %0, i64 -1
%27 = getelementptr inbounds i8, i8* %0, i64 -1
br label %28
28: ; preds = %28, %22
%29 = phi i64 [ 0, %22 ], [ %64, %28 ]
%30 = phi i64 [ 0, %22 ], [ %65, %28 ]
%31 = getelementptr inbounds i8, i8* %1, i64 %29
%32 = bitcast i8* %31 to <8 x i8>*
%33 = load <8 x i8>, <8 x i8>* %32
%34 = getelementptr inbounds i8, i8* %31, i64 8
%35 = bitcast i8* %34 to <8 x i8>*
%36 = load <8 x i8>, <8 x i8>* %35
%37 = shl nuw nsw i64 %29, 1
%38 = shl i64 %29, 1
%39 = or i64 %37, 1
%40 = or i64 %38, 17
%41 = getelementptr inbounds i8, i8* %24, i64 %39
%42 = bitcast i8* %41 to <16 x i8>*
%43 = getelementptr inbounds i8, i8* %25, i64 %40
%44 = bitcast i8* %43 to <16 x i8>*
%45 = shufflevector <8 x i8> %33, <8 x i8> zeroinitializer, <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> %45, <16 x i8>* %42
%46 = shufflevector <8 x i8> %36, <8 x i8> zeroinitializer, <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> %46, <16 x i8>* %44
%47 = or i64 %29, 16
%48 = getelementptr inbounds i8, i8* %1, i64 %47
%49 = bitcast i8* %48 to <8 x i8>*
%50 = load <8 x i8>, <8 x i8>* %49
%51 = getelementptr inbounds i8, i8* %48, i64 8
%52 = bitcast i8* %51 to <8 x i8>*
%53 = load <8 x i8>, <8 x i8>* %52
%54 = shl nuw nsw i64 %47, 1
%55 = shl i64 %47, 1
%56 = or i64 %54, 1
%57 = or i64 %55, 17
%58 = getelementptr inbounds i8, i8* %26, i64 %56
%59 = bitcast i8* %58 to <16 x i8>*
%60 = getelementptr inbounds i8, i8* %27, i64 %57
%61 = bitcast i8* %60 to <16 x i8>*
%62 = shufflevector <8 x i8> %50, <8 x i8> zeroinitializer, <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> %62, <16 x i8>* %59
%63 = shufflevector <8 x i8> %53, <8 x i8> zeroinitializer, <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> %63, <16 x i8>* %61
%64 = add nuw i64 %29, 32
%65 = add i64 %30, 2
%66 = icmp eq i64 %65, %23
br i1 %66, label %67, label %28
67: ; preds = %28, %15
%68 = phi i64 [ 0, %15 ], [ %64, %28 ]
%69 = icmp eq i64 %20, 0
br i1 %69, label %89, label %70
70: ; preds = %67
%71 = getelementptr inbounds i8, i8* %1, i64 %68
%72 = bitcast i8* %71 to <8 x i8>*
%73 = load <8 x i8>, <8 x i8>* %72
%74 = getelementptr inbounds i8, i8* %71, i64 8
%75 = bitcast i8* %74 to <8 x i8>*
%76 = load <8 x i8>, <8 x i8>* %75
%77 = shl nuw nsw i64 %68, 1
%78 = shl i64 %68, 1
%79 = or i64 %77, 1
%80 = or i64 %78, 17
%81 = getelementptr inbounds i8, i8* %0, i64 -1
%82 = getelementptr inbounds i8, i8* %0, i64 -1
%83 = getelementptr inbounds i8, i8* %81, i64 %79
%84 = bitcast i8* %83 to <16 x i8>*
%85 = getelementptr inbounds i8, i8* %82, i64 %80
%86 = bitcast i8* %85 to <16 x i8>*
%87 = shufflevector <8 x i8> %73, <8 x i8> zeroinitializer, <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> %87, <16 x i8>* %84
%88 = shufflevector <8 x i8> %76, <8 x i8> zeroinitializer, <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> %88, <16 x i8>* %86
br label %89
89: ; preds = %67, %70
%90 = icmp eq i64 %16, %6
br i1 %90, label %125, label %91
91: ; preds = %8, %5, %89
%92 = phi i64 [ 0, %8 ], [ 0, %5 ], [ %16, %89 ]
%93 = xor i64 %92, -1
%94 = and i64 %6, 1
%95 = icmp eq i64 %94, 0
br i1 %95, label %104, label %96
96: ; preds = %91
%97 = getelementptr inbounds i8, i8* %1, i64 %92
%98 = load i8, i8* %97
%99 = shl nuw nsw i64 %92, 1
%100 = getelementptr inbounds i8, i8* %0, i64 %99
store i8 %98, i8* %100
%101 = or i64 %99, 1
%102 = getelementptr inbounds i8, i8* %0, i64 %101
store i8 0, i8* %102
%103 = or i64 %92, 1
br label %104
104: ; preds = %96, %91
%105 = phi i64 [ %92, %91 ], [ %103, %96 ]
%106 = sub nsw i64 0, %6
%107 = icmp eq i64 %93, %106
br i1 %107, label %125, label %108
108: ; preds = %104, %108
%109 = phi i64 [ %123, %108 ], [ %105, %104 ]
%110 = getelementptr inbounds i8, i8* %1, i64 %109
%111 = load i8, i8* %110
%112 = shl nuw nsw i64 %109, 1
%113 = getelementptr inbounds i8, i8* %0, i64 %112
store i8 %111, i8* %113
%114 = or i64 %112, 1
%115 = getelementptr inbounds i8, i8* %0, i64 %114
store i8 0, i8* %115
%116 = add nuw nsw i64 %109, 1
%117 = getelementptr inbounds i8, i8* %1, i64 %116
%118 = load i8, i8* %117
%119 = shl nuw nsw i64 %116, 1
%120 = getelementptr inbounds i8, i8* %0, i64 %119
store i8 %118, i8* %120
%121 = or i64 %119, 1
%122 = getelementptr inbounds i8, i8* %0, i64 %121
store i8 0, i8* %122
%123 = add nuw nsw i64 %109, 2
%124 = icmp eq i64 %123, %6
br i1 %124, label %125, label %108
125: ; preds = %104, %108, %89
%126 = shl i32 %2, 1
br label %127
127: ; preds = %125, %3
%128 = phi i32 [ 0, %3 ], [ %126, %125 ]
%129 = zext i32 %128 to i64
%130 = getelementptr inbounds i8, i8* %0, i64 %129
store i8 0, i8* %130
%131 = or i32 %128, 1
%132 = zext i32 %131 to i64
%133 = getelementptr inbounds i8, i8* %0, i64 %132
store i8 0, i8* %133
ret void
}