void cheap_ascii2uni(char *src, char *dest, int l) {
  for (; l > 0; l--) {
    *dest++ = *src++;
    *dest++ = 0;
  }
}


x86 assembly (clang, -O0):
<cheap_ascii2uni>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
cmpl   $0x0,-0x14(%rbp)
jle    115b <cheap_ascii2uni+0x5b>
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x8(%rbp)
mov    (%rax),%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
mov    -0x10(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x10(%rbp)
movb   $0x0,(%rax)
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
jmp    110f <cheap_ascii2uni+0xf>
pop    %rbp
ret

x86 assembly (clang, -O2):
<cheap_ascii2uni>:
test   %edx,%edx
jle    1218 <cheap_ascii2uni+0x118>
lea    -0x1(%rdx),%r10d
cmp    $0xf,%r10d
jb     11f6 <cheap_ascii2uni+0xf6>
lea    (%r10,%rdi,1),%rax
add    $0x1,%rax
cmp    %rsi,%rax
jbe    1134 <cheap_ascii2uni+0x34>
lea    (%rsi,%r10,2),%rax
add    $0x2,%rax
cmp    %rdi,%rax
ja     11f6 <cheap_ascii2uni+0xf6>
add    $0x1,%r10
mov    %r10,%r8
and    $0xfffffffffffffff0,%r8
lea    -0x10(%r8),%rax
mov    %rax,%r9
shr    $0x4,%r9
add    $0x1,%r9
test   %rax,%rax
je     1219 <cheap_ascii2uni+0x119>
mov    %r9,%rax
and    $0xfffffffffffffffe,%rax
xor    %ecx,%ecx
pxor   %xmm0,%xmm0
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movq   (%rdi,%rcx,1),%xmm1
movq   0x8(%rdi,%rcx,1),%xmm2
punpcklbw %xmm0,%xmm1
movdqu %xmm1,(%rsi,%rcx,2)
punpcklbw %xmm0,%xmm2
movdqu %xmm2,0x10(%rsi,%rcx,2)
movq   0x10(%rdi,%rcx,1),%xmm1
movq   0x18(%rdi,%rcx,1),%xmm2
punpcklbw %xmm0,%xmm1
movdqu %xmm1,0x20(%rsi,%rcx,2)
punpcklbw %xmm0,%xmm2
movdqu %xmm2,0x30(%rsi,%rcx,2)
add    $0x20,%rcx
add    $0xfffffffffffffffe,%rax
jne    1170 <cheap_ascii2uni+0x70>
test   $0x1,%r9b
je     11e7 <cheap_ascii2uni+0xe7>
lea    (%rcx,%rcx,1),%rax
or     $0x10,%rax
movq   (%rdi,%rcx,1),%xmm0
movq   0x8(%rdi,%rcx,1),%xmm1
pxor   %xmm2,%xmm2
punpcklbw %xmm2,%xmm0
movdqu %xmm0,(%rsi,%rcx,2)
punpcklbw %xmm2,%xmm1
movdqu %xmm1,(%rsi,%rax,1)
cmp    %r8,%r10
je     1218 <cheap_ascii2uni+0x118>
sub    %r8d,%edx
lea    (%rsi,%r8,2),%rsi
add    %r8,%rdi
add    $0x1,%edx
xor    %eax,%eax
nopl   0x0(%rax,%rax,1)
movzbl (%rdi,%rax,1),%ecx
mov    %cl,(%rsi,%rax,2)
movb   $0x0,0x1(%rsi,%rax,2)
add    $0xffffffff,%edx
add    $0x1,%rax
cmp    $0x1,%edx
ja     1200 <cheap_ascii2uni+0x100>
ret
xor    %ecx,%ecx
test   $0x1,%r9b
jne    11be <cheap_ascii2uni+0xbe>
jmp    11e7 <cheap_ascii2uni+0xe7>

LLVM IR (-O0):
define void @cheap_ascii2uni(i8* %0, i8* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i32
store i8* %0, i8** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
br label %7
7: ; preds = %18, %3
%8 = load i32, i32* %6
%9 = icmp sgt i32 %8, 0
br i1 %9, label %10, label %21
10: ; preds = %7
%11 = load i8*, i8** %4
%12 = getelementptr inbounds i8, i8* %11, i32 1
store i8* %12, i8** %4
%13 = load i8, i8* %11
%14 = load i8*, i8** %5
%15 = getelementptr inbounds i8, i8* %14, i32 1
store i8* %15, i8** %5
store i8 %13, i8* %14
%16 = load i8*, i8** %5
%17 = getelementptr inbounds i8, i8* %16, i32 1
store i8* %17, i8** %5
store i8 0, i8* %16
br label %18
18: ; preds = %10
%19 = load i32, i32* %6
%20 = add nsw i32 %19, -1
store i32 %20, i32* %6
br label %7
21: ; preds = %7
ret void
}

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