#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef int wchar_t;

/* Variables and functions */
int *malloc(int);
size_t utf8_widen_len(char const *);
wchar_t *utf8_to_utf16(const char utf8[]) {
  size_t size = utf8_widen_len(utf8);
  wchar_t *const utf16 = malloc(sizeof(wchar_t) * (size + 1));
  wchar_t *t = utf16;
  const char *p = utf8;
  unsigned char c;
  while ((c = *p++) != '\0') {
    wchar_t wc;
    if (c < 0x80) {
      wc = c;
    } else if ((c & 0xe0) == 0xc0) {
      wc = ((c & 0x1f) << 6) | ((*p++) & 0x3f);
    } else if ((c & 0xf0) == 0xe0) {
      wc = ((c & 0x0f) << 12) | ((p[0] & 0x3f) << 6) | (p[1] & 0x3f);
      p += 2;
    } else {
      const unsigned int r32 = ((c & 0x07) << 18) | ((p[0] & 0x3f) << 12) |
                               ((p[1] & 0x3f) << 6) | (p[2] & 0x3f);
      p += 3;
      *t++ = 0xd800 | (((r32 - 0x10000) >> 10) & 0x3ff);
      wc = 0xdc00 | (r32 & 0x3ff);
    }
    *t++ = wc;
  }
  *t = 0;
  return utf16;
}


x86 assembly (clang, -O0):
<utf8_to_utf16>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x8(%rbp)
mov    -0x8(%rbp),%rdi
call   1030 <utf8_widen_len@plt>
mov    %rax,-0x10(%rbp)
mov    -0x10(%rbp),%rax
add    $0x1,%rax
shl    $0x2,%rax
mov    %eax,%edi
call   1040 <malloc@plt>
mov    %rax,-0x18(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x28(%rbp)
mov    (%rax),%al
mov    %al,-0x29(%rbp)
movzbl %al,%eax
cmp    $0x0,%eax
je     12c7 <utf8_to_utf16+0x1a7>
movzbl -0x29(%rbp),%eax
cmp    $0x80,%eax
jge    119b <utf8_to_utf16+0x7b>
movzbl -0x29(%rbp),%eax
mov    %eax,-0x30(%rbp)
jmp    12ae <utf8_to_utf16+0x18e>
movzbl -0x29(%rbp),%eax
and    $0xe0,%eax
cmp    $0xc0,%eax
jne    11d8 <utf8_to_utf16+0xb8>
movzbl -0x29(%rbp),%eax
and    $0x1f,%eax
shl    $0x6,%eax
mov    -0x28(%rbp),%rcx
mov    %rcx,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
movsbl (%rcx),%ecx
and    $0x3f,%ecx
or     %ecx,%eax
mov    %eax,-0x30(%rbp)
jmp    12a9 <utf8_to_utf16+0x189>
movzbl -0x29(%rbp),%eax
and    $0xf0,%eax
cmp    $0xe0,%eax
jne    1226 <utf8_to_utf16+0x106>
movzbl -0x29(%rbp),%eax
and    $0xf,%eax
shl    $0xc,%eax
mov    -0x28(%rbp),%rcx
movsbl (%rcx),%ecx
and    $0x3f,%ecx
shl    $0x6,%ecx
or     %ecx,%eax
mov    -0x28(%rbp),%rcx
movsbl 0x1(%rcx),%ecx
and    $0x3f,%ecx
or     %ecx,%eax
mov    %eax,-0x30(%rbp)
mov    -0x28(%rbp),%rax
add    $0x2,%rax
mov    %rax,-0x28(%rbp)
jmp    12a4 <utf8_to_utf16+0x184>
movzbl -0x29(%rbp),%eax
and    $0x7,%eax
shl    $0x12,%eax
mov    -0x28(%rbp),%rcx
movsbl (%rcx),%ecx
and    $0x3f,%ecx
shl    $0xc,%ecx
or     %ecx,%eax
mov    -0x28(%rbp),%rcx
movsbl 0x1(%rcx),%ecx
and    $0x3f,%ecx
shl    $0x6,%ecx
or     %ecx,%eax
mov    -0x28(%rbp),%rcx
movsbl 0x2(%rcx),%ecx
and    $0x3f,%ecx
or     %ecx,%eax
mov    %eax,-0x34(%rbp)
mov    -0x28(%rbp),%rax
add    $0x3,%rax
mov    %rax,-0x28(%rbp)
mov    -0x34(%rbp),%ecx
sub    $0x10000,%ecx
shr    $0xa,%ecx
and    $0x3ff,%ecx
or     $0xd800,%ecx
mov    -0x20(%rbp),%rax
mov    %rax,%rdx
add    $0x4,%rdx
mov    %rdx,-0x20(%rbp)
mov    %ecx,(%rax)
mov    -0x34(%rbp),%eax
and    $0x3ff,%eax
or     $0xdc00,%eax
mov    %eax,-0x30(%rbp)
jmp    12a9 <utf8_to_utf16+0x189>
jmp    12ae <utf8_to_utf16+0x18e>
mov    -0x30(%rbp),%ecx
mov    -0x20(%rbp),%rax
mov    %rax,%rdx
add    $0x4,%rdx
mov    %rdx,-0x20(%rbp)
mov    %ecx,(%rax)
jmp    1160 <utf8_to_utf16+0x40>
mov    -0x20(%rbp),%rax
movl   $0x0,(%rax)
mov    -0x18(%rbp),%rax
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<utf8_to_utf16>:
push   %rbx
mov    %rdi,%rbx
call   1030 <utf8_widen_len@plt>
lea    0x4(,%rax,4),%edi
call   1040 <malloc@plt>
mov    (%rbx),%dl
mov    %rax,%rcx
test   %dl,%dl
je     1216 <utf8_to_utf16+0xf6>
mov    %rax,%rcx
jmp    1165 <utf8_to_utf16+0x45>
nopw   0x0(%rax,%rax,1)
add    $0x1,%rbx
mov    %edx,(%rcx)
add    $0x4,%rcx
movzbl (%rbx),%edx
test   %dl,%dl
je     1216 <utf8_to_utf16+0xf6>
movzbl %dl,%edx
test   %dl,%dl
jns    1150 <utf8_to_utf16+0x30>
mov    %edx,%esi
and    $0xffffffe0,%esi
cmp    $0xc0,%esi
jne    118e <utf8_to_utf16+0x6e>
and    $0x1f,%edx
shl    $0x6,%edx
movzbl 0x1(%rbx),%esi
add    $0x2,%rbx
and    $0x3f,%esi
or     %esi,%edx
jmp    1154 <utf8_to_utf16+0x34>
mov    %edx,%esi
and    $0xfffffff0,%esi
cmp    $0xe0,%esi
jne    11bc <utf8_to_utf16+0x9c>
shl    $0xc,%edx
movzwl %dx,%edx
movzbl 0x1(%rbx),%esi
and    $0x3f,%esi
shl    $0x6,%esi
or     %edx,%esi
movzbl 0x2(%rbx),%edx
and    $0x3f,%edx
or     %esi,%edx
add    $0x3,%rbx
jmp    1154 <utf8_to_utf16+0x34>
and    $0x7,%edx
shl    $0x12,%edx
movzbl 0x1(%rbx),%esi
and    $0x3f,%esi
shl    $0xc,%esi
or     %edx,%esi
movzbl 0x2(%rbx),%edi
and    $0x3f,%edi
shl    $0x6,%edi
or     %esi,%edi
movzbl 0x3(%rbx),%esi
and    $0x3f,%esi
lea    (%rdi,%rsi,1),%edx
add    $0x4,%rbx
add    %edi,%esi
add    $0xf0000,%esi
shr    $0xa,%esi
and    $0x3ff,%esi
or     $0xd800,%esi
mov    %esi,(%rcx)
add    $0x4,%rcx
and    $0x3ff,%edx
or     $0xdc00,%edx
jmp    1154 <utf8_to_utf16+0x34>
movl   $0x0,(%rcx)
pop    %rbx
ret

LLVM IR (-O0):
define i32* @utf8_to_utf16(i8* %0) {
%2 = alloca i8*
%3 = alloca i64
%4 = alloca i32*
%5 = alloca i32*
%6 = alloca i8*
%7 = alloca i8
%8 = alloca i32
%9 = alloca i32
store i8* %0, i8** %2
%10 = load i8*, i8** %2
%11 = call i64 @utf8_widen_len(i8* %10)
store i64 %11, i64* %3
%12 = load i64, i64* %3
%13 = add i64 %12, 1
%14 = mul i64 4, %13
%15 = trunc i64 %14 to i32
%16 = call i32* @malloc(i32 %15)
store i32* %16, i32** %4
%17 = load i32*, i32** %4
store i32* %17, i32** %5
%18 = load i8*, i8** %2
store i8* %18, i8** %6
br label %19
19: ; preds = %112, %1
%20 = load i8*, i8** %6
%21 = getelementptr inbounds i8, i8* %20, i32 1
store i8* %21, i8** %6
%22 = load i8, i8* %20
store i8 %22, i8* %7
%23 = zext i8 %22 to i32
%24 = icmp ne i32 %23, 0
br i1 %24, label %25, label %116
25: ; preds = %19
%26 = load i8, i8* %7
%27 = zext i8 %26 to i32
%28 = icmp slt i32 %27, 128
br i1 %28, label %29, label %32
29: ; preds = %25
%30 = load i8, i8* %7
%31 = zext i8 %30 to i32
store i32 %31, i32* %8
br label %112
32: ; preds = %25
%33 = load i8, i8* %7
%34 = zext i8 %33 to i32
%35 = and i32 %34, 224
%36 = icmp eq i32 %35, 192
br i1 %36, label %37, label %48
37: ; preds = %32
%38 = load i8, i8* %7
%39 = zext i8 %38 to i32
%40 = and i32 %39, 31
%41 = shl i32 %40, 6
%42 = load i8*, i8** %6
%43 = getelementptr inbounds i8, i8* %42, i32 1
store i8* %43, i8** %6
%44 = load i8, i8* %42
%45 = sext i8 %44 to i32
%46 = and i32 %45, 63
%47 = or i32 %41, %46
store i32 %47, i32* %8
br label %111
48: ; preds = %32
%49 = load i8, i8* %7
%50 = zext i8 %49 to i32
%51 = and i32 %50, 240
%52 = icmp eq i32 %51, 224
br i1 %52, label %53, label %73
53: ; preds = %48
%54 = load i8, i8* %7
%55 = zext i8 %54 to i32
%56 = and i32 %55, 15
%57 = shl i32 %56, 12
%58 = load i8*, i8** %6
%59 = getelementptr inbounds i8, i8* %58, i64 0
%60 = load i8, i8* %59
%61 = sext i8 %60 to i32
%62 = and i32 %61, 63
%63 = shl i32 %62, 6
%64 = or i32 %57, %63
%65 = load i8*, i8** %6
%66 = getelementptr inbounds i8, i8* %65, i64 1
%67 = load i8, i8* %66
%68 = sext i8 %67 to i32
%69 = and i32 %68, 63
%70 = or i32 %64, %69
store i32 %70, i32* %8
%71 = load i8*, i8** %6
%72 = getelementptr inbounds i8, i8* %71, i64 2
store i8* %72, i8** %6
br label %110
73: ; preds = %48
%74 = load i8, i8* %7
%75 = zext i8 %74 to i32
%76 = and i32 %75, 7
%77 = shl i32 %76, 18
%78 = load i8*, i8** %6
%79 = getelementptr inbounds i8, i8* %78, i64 0
%80 = load i8, i8* %79
%81 = sext i8 %80 to i32
%82 = and i32 %81, 63
%83 = shl i32 %82, 12
%84 = or i32 %77, %83
%85 = load i8*, i8** %6
%86 = getelementptr inbounds i8, i8* %85, i64 1
%87 = load i8, i8* %86
%88 = sext i8 %87 to i32
%89 = and i32 %88, 63
%90 = shl i32 %89, 6
%91 = or i32 %84, %90
%92 = load i8*, i8** %6
%93 = getelementptr inbounds i8, i8* %92, i64 2
%94 = load i8, i8* %93
%95 = sext i8 %94 to i32
%96 = and i32 %95, 63
%97 = or i32 %91, %96
store i32 %97, i32* %9
%98 = load i8*, i8** %6
%99 = getelementptr inbounds i8, i8* %98, i64 3
store i8* %99, i8** %6
%100 = load i32, i32* %9
%101 = sub i32 %100, 65536
%102 = lshr i32 %101, 10
%103 = and i32 %102, 1023
%104 = or i32 55296, %103
%105 = load i32*, i32** %5
%106 = getelementptr inbounds i32, i32* %105, i32 1
store i32* %106, i32** %5
store i32 %104, i32* %105
%107 = load i32, i32* %9
%108 = and i32 %107, 1023
%109 = or i32 56320, %108
store i32 %109, i32* %8
br label %110
110: ; preds = %73, %53
br label %111
111: ; preds = %110, %37
br label %112
112: ; preds = %111, %29
%113 = load i32, i32* %8
%114 = load i32*, i32** %5
%115 = getelementptr inbounds i32, i32* %114, i32 1
store i32* %115, i32** %5
store i32 %113, i32* %114
br label %19
116: ; preds = %19
%117 = load i32*, i32** %5
store i32 0, i32* %117
%118 = load i32*, i32** %4
ret i32* %118
}

LLVM IR (-O2):
define noalias i32* @utf8_to_utf16(i8* %0) {
%2 = tail call i64 @utf8_widen_len(i8* %0)
%3 = trunc i64 %2 to i32
%4 = shl i32 %3, 2
%5 = add i32 %4, 4
%6 = tail call i32* @malloc(i32 %5)
%7 = load i8, i8* %0
%8 = icmp eq i8 %7, 0
br i1 %8, label %78, label %9
9: ; preds = %1, %71
%10 = phi i8 [ %76, %71 ], [ %7, %1 ]
%11 = phi i32* [ %75, %71 ], [ %6, %1 ]
%12 = phi i8* [ %72, %71 ], [ %0, %1 ]
%13 = getelementptr inbounds i8, i8* %12, i64 1
%14 = zext i8 %10 to i32
%15 = icmp sgt i8 %10, -1
br i1 %15, label %71, label %16
16: ; preds = %9
%17 = and i32 %14, 224
%18 = icmp eq i32 %17, 192
br i1 %18, label %19, label %27
19: ; preds = %16
%20 = shl nuw nsw i32 %14, 6
%21 = and i32 %20, 1984
%22 = getelementptr inbounds i8, i8* %12, i64 2
%23 = load i8, i8* %13
%24 = and i8 %23, 63
%25 = zext i8 %24 to i32
%26 = or i32 %21, %25
br label %71
27: ; preds = %16
%28 = and i32 %14, 240
%29 = icmp eq i32 %28, 224
br i1 %29, label %30, label %44
30: ; preds = %27
%31 = shl nuw nsw i32 %14, 12
%32 = and i32 %31, 61440
%33 = load i8, i8* %13
%34 = and i8 %33, 63
%35 = zext i8 %34 to i32
%36 = shl nuw nsw i32 %35, 6
%37 = or i32 %36, %32
%38 = getelementptr inbounds i8, i8* %12, i64 2
%39 = load i8, i8* %38
%40 = and i8 %39, 63
%41 = zext i8 %40 to i32
%42 = or i32 %37, %41
%43 = getelementptr inbounds i8, i8* %12, i64 3
br label %71
44: ; preds = %27
%45 = shl nuw nsw i32 %14, 18
%46 = and i32 %45, 1835008
%47 = load i8, i8* %13
%48 = and i8 %47, 63
%49 = zext i8 %48 to i32
%50 = shl nuw nsw i32 %49, 12
%51 = or i32 %50, %46
%52 = getelementptr inbounds i8, i8* %12, i64 2
%53 = load i8, i8* %52
%54 = and i8 %53, 63
%55 = zext i8 %54 to i32
%56 = shl nuw nsw i32 %55, 6
%57 = or i32 %51, %56
%58 = getelementptr inbounds i8, i8* %12, i64 3
%59 = load i8, i8* %58
%60 = and i8 %59, 63
%61 = zext i8 %60 to i32
%62 = or i32 %57, %61
%63 = getelementptr inbounds i8, i8* %12, i64 4
%64 = add nuw nsw i32 %62, 983040
%65 = lshr i32 %64, 10
%66 = and i32 %65, 1023
%67 = or i32 %66, 55296
%68 = getelementptr inbounds i32, i32* %11, i64 1
store i32 %67, i32* %11
%69 = and i32 %62, 1023
%70 = or i32 %69, 56320
br label %71
71: ; preds = %9, %19, %44, %30
%72 = phi i8* [ %22, %19 ], [ %43, %30 ], [ %63, %44 ], [ %13, %9 ]
%73 = phi i32 [ %26, %19 ], [ %42, %30 ], [ %70, %44 ], [ %14, %9 ]
%74 = phi i32* [ %11, %19 ], [ %11, %30 ], [ %68, %44 ], [ %11, %9 ]
%75 = getelementptr inbounds i32, i32* %74, i64 1
store i32 %73, i32* %74
%76 = load i8, i8* %72
%77 = icmp eq i8 %76, 0
br i1 %77, label %78, label %9
78: ; preds = %71, %1
%79 = phi i32* [ %6, %1 ], [ %75, %71 ]
store i32 0, i32* %79
ret i32* %6
}