#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 scalar_t__ wchar_t;

/* Variables and functions */
char *malloc(size_t const);
size_t utf8_narrowed_len(scalar_t__ const *);
char *utf8_from_utf16(const wchar_t utf16[]) {
  const size_t size = utf8_narrowed_len(utf16);
  char *const utf8 = malloc(size + 1);
  const wchar_t *p = utf16;
  char *t = utf8;
  unsigned short int c;
  while ((c = *p++) != 0) {
    if (c < 0x80) {
      *t++ = (char)c;
    } else if (c < 0x0800) {
      *t++ = (char)(0xc0 | (c >> 6));
      *t++ = (char)(0x80 | (c & 0x3f));
    } else if ((c & 0xf8) != 0xd8) {
      *t++ = (char)(0xe0 | (c >> 12));
      *t++ = (char)(0x80 | ((c >> 6) & 0x3f));
      *t++ = (char)(0x80 | (c & 0x3f));
    } else {
      const unsigned short int c1 = (*p ? *p++ : 0xdc);
      const unsigned int d = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;
      *t++ = (char)(0xf0 | ((d >> 18) & 0x7));
      *t++ = (char)(0x80 | ((d >> 12) & 0x3f));
      *t++ = (char)(0x80 | ((d >> 6) & 0x3f));
      *t++ = (char)(0x80 | (d & 0x3f));
    }
  }
  *t = '\0';
  return utf8;
}


x86 assembly (clang, -O0):
<utf8_from_utf16>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x8(%rbp)
mov    -0x8(%rbp),%rdi
call   1030 <utf8_narrowed_len@plt>
mov    %rax,-0x10(%rbp)
mov    -0x10(%rbp),%rdi
add    $0x1,%rdi
call   1040 <malloc@plt>
mov    %rax,-0x18(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x20(%rbp),%rax
mov    %rax,%rcx
add    $0x8,%rcx
mov    %rcx,-0x20(%rbp)
mov    (%rax),%rax
mov    %ax,-0x2a(%rbp)
movzwl %ax,%eax
cmp    $0x0,%eax
je     1361 <utf8_from_utf16+0x241>
movzwl -0x2a(%rbp),%eax
cmp    $0x80,%eax
jge    11a7 <utf8_from_utf16+0x87>
mov    -0x2a(%rbp),%ax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,(%rax)
jmp    135c <utf8_from_utf16+0x23c>
movzwl -0x2a(%rbp),%eax
cmp    $0x800,%eax
jge    11f9 <utf8_from_utf16+0xd9>
movzwl -0x2a(%rbp),%eax
sar    $0x6,%eax
or     $0xc0,%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,(%rax)
movzwl -0x2a(%rbp),%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,(%rax)
jmp    1357 <utf8_from_utf16+0x237>
movzwl -0x2a(%rbp),%eax
and    $0xf8,%eax
cmp    $0xd8,%eax
je     1272 <utf8_from_utf16+0x152>
movzwl -0x2a(%rbp),%eax
sar    $0xc,%eax
or     $0xe0,%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,(%rax)
movzwl -0x2a(%rbp),%eax
sar    $0x6,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,(%rax)
movzwl -0x2a(%rbp),%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,(%rax)
jmp    1352 <utf8_from_utf16+0x232>
mov    -0x20(%rbp),%rax
cmpq   $0x0,(%rax)
je     129b <utf8_from_utf16+0x17b>
mov    -0x20(%rbp),%rax
mov    %rax,%rcx
add    $0x8,%rcx
mov    %rcx,-0x20(%rbp)
mov    (%rax),%rax
mov    %rax,-0x38(%rbp)
jmp    12a9 <utf8_from_utf16+0x189>
mov    $0xdc,%eax
mov    %rax,-0x38(%rbp)
jmp    12a9 <utf8_from_utf16+0x189>
mov    -0x38(%rbp),%rax
mov    %ax,-0x2c(%rbp)
movzwl -0x2a(%rbp),%eax
and    $0x3ff,%eax
shl    $0xa,%eax
movzwl -0x2c(%rbp),%ecx
and    $0x3ff,%ecx
or     %ecx,%eax
add    $0x10000,%eax
mov    %eax,-0x30(%rbp)
mov    -0x30(%rbp),%eax
shr    $0x12,%eax
and    $0x7,%eax
or     $0xf0,%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,(%rax)
mov    -0x30(%rbp),%eax
shr    $0xc,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,(%rax)
mov    -0x30(%rbp),%eax
shr    $0x6,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,(%rax)
mov    -0x30(%rbp),%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,(%rax)
jmp    1357 <utf8_from_utf16+0x237>
jmp    135c <utf8_from_utf16+0x23c>
jmp    115a <utf8_from_utf16+0x3a>
mov    -0x28(%rbp),%rax
movb   $0x0,(%rax)
mov    -0x18(%rbp),%rax
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<utf8_from_utf16>:
push   %rbx
mov    %rdi,%rbx
call   1030 <utf8_narrowed_len@plt>
lea    0x1(%rax),%rdi
call   1040 <malloc@plt>
mov    (%rbx),%rdi
mov    %edi,%edx
mov    %rax,%rcx
and    $0xffff,%edx
je     1257 <utf8_from_utf16+0x137>
mov    $0xdc,%r8d
mov    %rax,%rcx
jmp    117b <utf8_from_utf16+0x5b>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
mov    %dil,(%rcx)
add    $0x1,%rcx
mov    (%r9),%rdi
mov    %edi,%edx
mov    %r9,%rbx
and    $0xffff,%edx
je     1257 <utf8_from_utf16+0x137>
lea    0x8(%rbx),%r9
cmp    $0x7f,%edx
jbe    1160 <utf8_from_utf16+0x40>
cmp    $0x7ff,%edx
ja     11b0 <utf8_from_utf16+0x90>
mov    %rdi,%rdx
shr    $0x6,%rdx
or     $0xc0,%dl
mov    %dl,(%rcx)
and    $0x3f,%dil
or     $0x80,%dil
mov    %dil,0x1(%rcx)
add    $0x2,%rcx
jmp    1167 <utf8_from_utf16+0x47>
nopw   0x0(%rax,%rax,1)
mov    %edi,%esi
and    $0xf8,%esi
cmp    $0xd8,%esi
jne    122a <utf8_from_utf16+0x10a>
mov    0x8(%rbx),%rdx
add    $0x10,%rbx
test   %rdx,%rdx
cmovne %rbx,%r9
cmove  %r8,%rdx
shl    $0xa,%edi
and    $0xffc00,%edi
mov    %edx,%esi
and    $0x3ff,%esi
add    %edi,%esi
add    $0x10000,%esi
mov    %esi,%edi
shr    $0x12,%edi
or     $0xf0,%dil
mov    %dil,(%rcx)
mov    %esi,%edi
shr    $0xc,%edi
and    $0x3f,%dil
or     $0x80,%dil
mov    %dil,0x1(%rcx)
shr    $0x6,%esi
and    $0x3f,%sil
or     $0x80,%sil
mov    %sil,0x2(%rcx)
and    $0x3f,%dl
or     $0x80,%dl
mov    %dl,0x3(%rcx)
add    $0x4,%rcx
jmp    1167 <utf8_from_utf16+0x47>
shr    $0xc,%edx
or     $0xe0,%dl
mov    %dl,(%rcx)
mov    %rdi,%rdx
shr    $0x6,%rdx
and    $0x3f,%dl
or     $0x80,%dl
mov    %dl,0x1(%rcx)
and    $0x3f,%dil
or     $0x80,%dil
mov    %dil,0x2(%rcx)
add    $0x3,%rcx
jmp    1167 <utf8_from_utf16+0x47>
movb   $0x0,(%rcx)
pop    %rbx
ret

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

LLVM IR (-O2):
define noalias i8* @utf8_from_utf16(i64* %0) {
%2 = tail call i64 @utf8_narrowed_len(i64* %0)
%3 = add i64 %2, 1
%4 = tail call i8* @malloc(i64 %3)
%5 = load i64, i64* %0
%6 = trunc i64 %5 to i32
%7 = and i32 %6, 65535
%8 = icmp eq i32 %7, 0
br i1 %8, label %85, label %9
9: ; preds = %1, %78
%10 = phi i32 [ %83, %78 ], [ %7, %1 ]
%11 = phi i32 [ %82, %78 ], [ %6, %1 ]
%12 = phi i64 [ %81, %78 ], [ %5, %1 ]
%13 = phi i64* [ %80, %78 ], [ %0, %1 ]
%14 = phi i8* [ %79, %78 ], [ %4, %1 ]
%15 = getelementptr inbounds i64, i64* %13, i64 1
%16 = icmp ult i32 %10, 128
br i1 %16, label %17, label %20
17: ; preds = %9
%18 = trunc i64 %12 to i8
%19 = getelementptr inbounds i8, i8* %14, i64 1
store i8 %18, i8* %14
br label %78
20: ; preds = %9
%21 = icmp ult i32 %10, 2048
br i1 %21, label %22, label %31
22: ; preds = %20
%23 = lshr i64 %12, 6
%24 = trunc i64 %23 to i8
%25 = or i8 %24, -64
%26 = getelementptr inbounds i8, i8* %14, i64 1
store i8 %25, i8* %14
%27 = trunc i64 %12 to i8
%28 = and i8 %27, 63
%29 = or i8 %28, -128
%30 = getelementptr inbounds i8, i8* %14, i64 2
store i8 %29, i8* %26
br label %78
31: ; preds = %20
%32 = and i32 %11, 248
%33 = icmp eq i32 %32, 216
br i1 %33, label %48, label %34
34: ; preds = %31
%35 = lshr i32 %10, 12
%36 = trunc i32 %35 to i8
%37 = or i8 %36, -32
%38 = getelementptr inbounds i8, i8* %14, i64 1
store i8 %37, i8* %14
%39 = lshr i64 %12, 6
%40 = trunc i64 %39 to i8
%41 = and i8 %40, 63
%42 = or i8 %41, -128
%43 = getelementptr inbounds i8, i8* %14, i64 2
store i8 %42, i8* %38
%44 = trunc i64 %12 to i8
%45 = and i8 %44, 63
%46 = or i8 %45, -128
%47 = getelementptr inbounds i8, i8* %14, i64 3
store i8 %46, i8* %43
br label %78
48: ; preds = %31
%49 = load i64, i64* %15
%50 = icmp eq i64 %49, 0
%51 = getelementptr inbounds i64, i64* %13, i64 2
%52 = select i1 %50, i64* %15, i64* %51
%53 = select i1 %50, i64 220, i64 %49
%54 = trunc i64 %53 to i32
%55 = shl i32 %11, 10
%56 = and i32 %55, 1047552
%57 = and i32 %54, 1023
%58 = or i32 %57, %56
%59 = add nuw nsw i32 %58, 65536
%60 = lshr i32 %59, 18
%61 = trunc i32 %60 to i8
%62 = or i8 %61, -16
%63 = getelementptr inbounds i8, i8* %14, i64 1
store i8 %62, i8* %14
%64 = lshr i32 %59, 12
%65 = trunc i32 %64 to i8
%66 = and i8 %65, 63
%67 = or i8 %66, -128
%68 = getelementptr inbounds i8, i8* %14, i64 2
store i8 %67, i8* %63
%69 = lshr i32 %59, 6
%70 = trunc i32 %69 to i8
%71 = and i8 %70, 63
%72 = or i8 %71, -128
%73 = getelementptr inbounds i8, i8* %14, i64 3
store i8 %72, i8* %68
%74 = trunc i64 %53 to i8
%75 = and i8 %74, 63
%76 = or i8 %75, -128
%77 = getelementptr inbounds i8, i8* %14, i64 4
store i8 %76, i8* %73
br label %78
78: ; preds = %22, %48, %34, %17
%79 = phi i8* [ %19, %17 ], [ %30, %22 ], [ %47, %34 ], [ %77, %48 ]
%80 = phi i64* [ %15, %17 ], [ %15, %22 ], [ %15, %34 ], [ %52, %48 ]
%81 = load i64, i64* %80
%82 = trunc i64 %81 to i32
%83 = and i32 %82, 65535
%84 = icmp eq i32 %83, 0
br i1 %84, label %85, label %9
85: ; preds = %78, %1
%86 = phi i8* [ %4, %1 ], [ %79, %78 ]
store i8 0, i8* %86
ret i8* %4
}