#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 */

/* Variables and functions */
int utf16_to_utf8(char *d, short *s, int maxlen) {
  int i, j;
  unsigned short *u;
  if (maxlen < 0)
    maxlen = 4096;
  u = (unsigned short *)s;
  for (i = j = 0; j < maxlen - 1 && u[i] != 0; i++) {
    unsigned int u32;
    if (u[i] >= 0xd800 && u[i] <= 0xdbff && u[i + 1] != 0) {
      i++;
      u32 = (u[i - 1] << 10) + u[i] - 0x35fdc00;
    } else
      u32 = u[i];
    if (u32 <= 0x7f) {
      if (d != NULL)
        d[j] = u32;
      j++;
    } else if (u32 <= 0x7ff) {
      if (j >= maxlen - 2)
        break;
      if (d != NULL) {
        d[j] = 0xc0 | ((u32 >> 6) & 0x1f);
        d[j + 1] = 0x80 | (u32 & 0x3f);
      }
      j += 2;
    } else if (u32 <= 0xffff) {
      if (j >= maxlen - 3)
        break;
      if (d != NULL) {
        d[j] = 0xe0 | ((u32 >> 12) & 0xf);
        d[j + 1] = 0x80 | ((u32 >> 6) & 0x3f);
        d[j + 2] = 0x80 | (u32 & 0x3f);
      }
      j += 3;
    } else if (u32 <= 0x1fffff) {
      if (j >= maxlen - 4)
        break;
      if (d != NULL) {
        d[j] = 0xf0 | ((u32 >> 18) & 0x7);
        d[j + 1] = 0x80 | ((u32 >> 12) & 0x3f);
        d[j + 2] = 0x80 | ((u32 >> 6) & 0x3f);
        d[j + 3] = 0x80 | (u32 & 0x3f);
      }
      j += 4;
    } else if (u32 <= 0x3ffffff) {
      if (j >= maxlen - 5)
        break;
      if (d != NULL) {
        d[j] = 0xf8 | ((u32 >> 24) & 0x3);
        d[j + 1] = 0x80 | ((u32 >> 18) & 0x3f);
        d[j + 2] = 0x80 | ((u32 >> 12) & 0x3f);
        d[j + 3] = 0x80 | ((u32 >> 6) & 0x3f);
        d[j + 4] = 0x80 | (u32 & 0x3f);
      }
      j += 5;
    } else {
      if (j >= maxlen - 6)
        break;
      if (d != NULL) {
        d[j] = 0xf8 | ((u32 >> 30) & 0x1);
        d[j + 1] = 0x80 | ((u32 >> 24) & 0x3f);
        d[j + 2] = 0x80 | ((u32 >> 18) & 0x3f);
        d[j + 3] = 0x80 | ((u32 >> 12) & 0x3f);
        d[j + 4] = 0x80 | ((u32 >> 6) & 0x3f);
        d[j + 5] = 0x80 | (u32 & 0x3f);
      }
      j += 6;
    }
  }
  if (d != NULL)
    d[j] = '\0';
  j++;
  return (j);
}


x86 assembly (clang, -O0):
<utf16_to_utf8>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
cmpl   $0x0,-0x14(%rbp)
jge    1120 <utf16_to_utf8+0x20>
movl   $0x1000,-0x14(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x28(%rbp)
movl   $0x0,-0x1c(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x1c(%rbp),%ecx
mov    -0x14(%rbp),%edx
sub    $0x1,%edx
xor    %eax,%eax
cmp    %edx,%ecx
mov    %al,-0x2d(%rbp)
jge    1161 <utf16_to_utf8+0x61>
mov    -0x28(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzwl (%rax,%rcx,2),%eax
cmp    $0x0,%eax
setne  %al
mov    %al,-0x2d(%rbp)
mov    -0x2d(%rbp),%al
test   $0x1,%al
jne    1171 <utf16_to_utf8+0x71>
jmp    15cc <utf16_to_utf8+0x4cc>
mov    -0x28(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzwl (%rax,%rcx,2),%eax
cmp    $0xd800,%eax
jl     11f1 <utf16_to_utf8+0xf1>
mov    -0x28(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzwl (%rax,%rcx,2),%eax
cmp    $0xdbff,%eax
jg     11f1 <utf16_to_utf8+0xf1>
mov    -0x28(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movzwl (%rax,%rcx,2),%eax
cmp    $0x0,%eax
je     11f1 <utf16_to_utf8+0xf1>
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
mov    -0x28(%rbp),%rax
mov    -0x18(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
movzwl (%rax,%rcx,2),%eax
shl    $0xa,%eax
mov    -0x28(%rbp),%rcx
movslq -0x18(%rbp),%rdx
movzwl (%rcx,%rdx,2),%ecx
add    %ecx,%eax
sub    $0x35fdc00,%eax
mov    %eax,-0x2c(%rbp)
jmp    1200 <utf16_to_utf8+0x100>
mov    -0x28(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzwl (%rax,%rcx,2),%eax
mov    %eax,-0x2c(%rbp)
cmpl   $0x7f,-0x2c(%rbp)
ja     1233 <utf16_to_utf8+0x133>
cmpq   $0x0,-0x8(%rbp)
je     1225 <utf16_to_utf8+0x125>
mov    -0x2c(%rbp),%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
movslq -0x1c(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    15b9 <utf16_to_utf8+0x4b9>
cmpl   $0x7ff,-0x2c(%rbp)
ja     12a7 <utf16_to_utf8+0x1a7>
mov    -0x1c(%rbp),%eax
mov    -0x14(%rbp),%ecx
sub    $0x2,%ecx
cmp    %ecx,%eax
jl     1256 <utf16_to_utf8+0x156>
jmp    15cc <utf16_to_utf8+0x4cc>
cmpq   $0x0,-0x8(%rbp)
je     1299 <utf16_to_utf8+0x199>
mov    -0x2c(%rbp),%eax
shr    $0x6,%eax
and    $0x1f,%eax
or     $0xc0,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
movslq -0x1c(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
add    $0x2,%eax
mov    %eax,-0x1c(%rbp)
jmp    15b4 <utf16_to_utf8+0x4b4>
cmpl   $0xffff,-0x2c(%rbp)
ja     133b <utf16_to_utf8+0x23b>
mov    -0x1c(%rbp),%eax
mov    -0x14(%rbp),%ecx
sub    $0x3,%ecx
cmp    %ecx,%eax
jl     12ca <utf16_to_utf8+0x1ca>
jmp    15cc <utf16_to_utf8+0x4cc>
cmpq   $0x0,-0x8(%rbp)
je     132d <utf16_to_utf8+0x22d>
mov    -0x2c(%rbp),%eax
shr    $0xc,%eax
and    $0xf,%eax
or     $0xe0,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
movslq -0x1c(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
shr    $0x6,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
add    $0x3,%eax
mov    %eax,-0x1c(%rbp)
jmp    15af <utf16_to_utf8+0x4af>
cmpl   $0x1fffff,-0x2c(%rbp)
ja     13ef <utf16_to_utf8+0x2ef>
mov    -0x1c(%rbp),%eax
mov    -0x14(%rbp),%ecx
sub    $0x4,%ecx
cmp    %ecx,%eax
jl     135e <utf16_to_utf8+0x25e>
jmp    15cc <utf16_to_utf8+0x4cc>
cmpq   $0x0,-0x8(%rbp)
je     13e1 <utf16_to_utf8+0x2e1>
mov    -0x2c(%rbp),%eax
shr    $0x12,%eax
and    $0x7,%eax
or     $0xf0,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
movslq -0x1c(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
shr    $0xc,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
shr    $0x6,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x3,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
add    $0x4,%eax
mov    %eax,-0x1c(%rbp)
jmp    15aa <utf16_to_utf8+0x4aa>
cmpl   $0x3ffffff,-0x2c(%rbp)
ja     14c3 <utf16_to_utf8+0x3c3>
mov    -0x1c(%rbp),%eax
mov    -0x14(%rbp),%ecx
sub    $0x5,%ecx
cmp    %ecx,%eax
jl     1412 <utf16_to_utf8+0x312>
jmp    15cc <utf16_to_utf8+0x4cc>
cmpq   $0x0,-0x8(%rbp)
je     14b5 <utf16_to_utf8+0x3b5>
mov    -0x2c(%rbp),%eax
shr    $0x18,%eax
and    $0x3,%eax
or     $0xf8,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
movslq -0x1c(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
shr    $0x12,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
shr    $0xc,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
shr    $0x6,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x3,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x4,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
add    $0x5,%eax
mov    %eax,-0x1c(%rbp)
jmp    15a5 <utf16_to_utf8+0x4a5>
mov    -0x1c(%rbp),%eax
mov    -0x14(%rbp),%ecx
sub    $0x6,%ecx
cmp    %ecx,%eax
jl     14d9 <utf16_to_utf8+0x3d9>
jmp    15cc <utf16_to_utf8+0x4cc>
cmpq   $0x0,-0x8(%rbp)
je     159c <utf16_to_utf8+0x49c>
mov    -0x2c(%rbp),%eax
shr    $0x1e,%eax
and    $0x1,%eax
or     $0xf8,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
movslq -0x1c(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
shr    $0x18,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
shr    $0x12,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
shr    $0xc,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x3,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
shr    $0x6,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x4,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x5,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
add    $0x6,%eax
mov    %eax,-0x1c(%rbp)
jmp    15aa <utf16_to_utf8+0x4aa>
jmp    15af <utf16_to_utf8+0x4af>
jmp    15b4 <utf16_to_utf8+0x4b4>
jmp    15b9 <utf16_to_utf8+0x4b9>
jmp    15be <utf16_to_utf8+0x4be>
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1136 <utf16_to_utf8+0x36>
cmpq   $0x0,-0x8(%rbp)
je     15e3 <utf16_to_utf8+0x4e3>
mov    -0x8(%rbp),%rax
movslq -0x1c(%rbp),%rcx
movb   $0x0,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<utf16_to_utf8>:
push   %rbp
push   %rbx
test   %edx,%edx
mov    $0x1000,%r11d
cmovns %edx,%r11d
xor    %eax,%eax
cmp    $0x2,%r11d
jb     1286 <utf16_to_utf8+0x186>
lea    -0x4(%r11),%r8d
lea    -0x3(%r11),%r9d
lea    -0x2(%r11),%r10d
add    $0xffffffff,%r11d
xor    %eax,%eax
xor    %edx,%edx
jmp    1160 <utf16_to_utf8+0x60>
mov    %ecx,%ebx
shr    $0x6,%ebx
or     $0xc0,%bl
movslq %eax,%rbp
mov    %bl,(%rdi,%rbp,1)
and    $0x3f,%cl
or     $0x80,%cl
lea    0x1(%rax),%ebp
mov    $0x2,%ebx
movslq %ebp,%rbp
mov    %cl,(%rdi,%rbp,1)
add    %ebx,%eax
add    $0x1,%edx
cmp    %r11d,%eax
jge    1286 <utf16_to_utf8+0x186>
movslq %edx,%rbx
movzwl (%rsi,%rbx,2),%ecx
test   %ecx,%ecx
je     1286 <utf16_to_utf8+0x186>
mov    %ecx,%ebp
and    $0xfc00,%ebp
cmp    $0xd800,%ebp
jne    1196 <utf16_to_utf8+0x96>
movzwl 0x2(%rsi,%rbx,2),%ebx
test   %ebx,%ebx
je     1196 <utf16_to_utf8+0x96>
add    $0x1,%edx
shl    $0xa,%ecx
add    %ebx,%ecx
add    $0xfca02400,%ecx
cmp    $0x7f,%ecx
ja     11b0 <utf16_to_utf8+0xb0>
mov    $0x1,%ebx
test   %rdi,%rdi
je     1152 <utf16_to_utf8+0x52>
mov    %eax,%ebp
jmp    114c <utf16_to_utf8+0x4c>
nopl   0x0(%rax)
cmp    $0x7ff,%ecx
ja     11e0 <utf16_to_utf8+0xe0>
cmp    %r10d,%eax
jge    1286 <utf16_to_utf8+0x186>
test   %rdi,%rdi
jne    1130 <utf16_to_utf8+0x30>
mov    $0x2,%ebx
jmp    1152 <utf16_to_utf8+0x52>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
cmp    $0xffff,%ecx
ja     1226 <utf16_to_utf8+0x126>
cmp    %r9d,%eax
jge    1286 <utf16_to_utf8+0x186>
test   %rdi,%rdi
je     1272 <utf16_to_utf8+0x172>
mov    %ecx,%ebx
shr    $0xc,%ebx
or     $0xe0,%bl
movslq %eax,%rbp
mov    %bl,(%rdi,%rbp,1)
mov    %ecx,%ebx
shr    $0x6,%ebx
and    $0x3f,%bl
or     $0x80,%bl
mov    %bl,0x1(%rdi,%rbp,1)
and    $0x3f,%cl
or     $0x80,%cl
lea    0x2(%rax),%ebp
mov    $0x3,%ebx
jmp    114c <utf16_to_utf8+0x4c>
cmp    %r8d,%eax
jge    1286 <utf16_to_utf8+0x186>
test   %rdi,%rdi
je     127c <utf16_to_utf8+0x17c>
mov    %ecx,%ebx
shr    $0x12,%ebx
and    $0x7,%bl
or     $0xf0,%bl
movslq %eax,%rbp
mov    %bl,(%rdi,%rbp,1)
mov    %ecx,%ebx
shr    $0xc,%ebx
and    $0x3f,%bl
or     $0x80,%bl
mov    %bl,0x1(%rdi,%rbp,1)
mov    %ecx,%ebx
shr    $0x6,%ebx
and    $0x3f,%bl
or     $0x80,%bl
mov    %bl,0x2(%rdi,%rbp,1)
and    $0x3f,%cl
or     $0x80,%cl
lea    0x3(%rax),%ebp
mov    $0x4,%ebx
jmp    114c <utf16_to_utf8+0x4c>
mov    $0x3,%ebx
jmp    1152 <utf16_to_utf8+0x52>
mov    $0x4,%ebx
jmp    1152 <utf16_to_utf8+0x52>
test   %rdi,%rdi
je     1292 <utf16_to_utf8+0x192>
movslq %eax,%rcx
movb   $0x0,(%rdi,%rcx,1)
add    $0x1,%eax
pop    %rbx
pop    %rbp
ret

LLVM IR (-O0):
define i32 @utf16_to_utf8(i8* %0, i16* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i16*
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i16*
%10 = alloca i32
store i8* %0, i8** %4
store i16* %1, i16** %5
store i32 %2, i32* %6
%11 = load i32, i32* %6
%12 = icmp slt i32 %11, 0
br i1 %12, label %13, label %14
13: ; preds = %3
store i32 4096, i32* %6
br label %14
14: ; preds = %13, %3
%15 = load i16*, i16** %5
store i16* %15, i16** %9
store i32 0, i32* %8
store i32 0, i32* %7
br label %16
16: ; preds = %370, %14
%17 = load i32, i32* %8
%18 = load i32, i32* %6
%19 = sub nsw i32 %18, 1
%20 = icmp slt i32 %17, %19
br i1 %20, label %21, label %29
21: ; preds = %16
%22 = load i16*, i16** %9
%23 = load i32, i32* %7
%24 = sext i32 %23 to i64
%25 = getelementptr inbounds i16, i16* %22, i64 %24
%26 = load i16, i16* %25
%27 = zext i16 %26 to i32
%28 = icmp ne i32 %27, 0
br label %29
29: ; preds = %21, %16
%30 = phi i1 [ false, %16 ], [ %28, %21 ]
br i1 %30, label %31, label %373
31: ; preds = %29
%32 = load i16*, i16** %9
%33 = load i32, i32* %7
%34 = sext i32 %33 to i64
%35 = getelementptr inbounds i16, i16* %32, i64 %34
%36 = load i16, i16* %35
%37 = zext i16 %36 to i32
%38 = icmp sge i32 %37, 55296
br i1 %38, label %39, label %75
39: ; preds = %31
%40 = load i16*, i16** %9
%41 = load i32, i32* %7
%42 = sext i32 %41 to i64
%43 = getelementptr inbounds i16, i16* %40, i64 %42
%44 = load i16, i16* %43
%45 = zext i16 %44 to i32
%46 = icmp sle i32 %45, 56319
br i1 %46, label %47, label %75
47: ; preds = %39
%48 = load i16*, i16** %9
%49 = load i32, i32* %7
%50 = add nsw i32 %49, 1
%51 = sext i32 %50 to i64
%52 = getelementptr inbounds i16, i16* %48, i64 %51
%53 = load i16, i16* %52
%54 = zext i16 %53 to i32
%55 = icmp ne i32 %54, 0
br i1 %55, label %56, label %75
56: ; preds = %47
%57 = load i32, i32* %7
%58 = add nsw i32 %57, 1
store i32 %58, i32* %7
%59 = load i16*, i16** %9
%60 = load i32, i32* %7
%61 = sub nsw i32 %60, 1
%62 = sext i32 %61 to i64
%63 = getelementptr inbounds i16, i16* %59, i64 %62
%64 = load i16, i16* %63
%65 = zext i16 %64 to i32
%66 = shl i32 %65, 10
%67 = load i16*, i16** %9
%68 = load i32, i32* %7
%69 = sext i32 %68 to i64
%70 = getelementptr inbounds i16, i16* %67, i64 %69
%71 = load i16, i16* %70
%72 = zext i16 %71 to i32
%73 = add nsw i32 %66, %72
%74 = sub nsw i32 %73, 56613888
store i32 %74, i32* %10
br label %82
75: ; preds = %47, %39, %31
%76 = load i16*, i16** %9
%77 = load i32, i32* %7
%78 = sext i32 %77 to i64
%79 = getelementptr inbounds i16, i16* %76, i64 %78
%80 = load i16, i16* %79
%81 = zext i16 %80 to i32
store i32 %81, i32* %10
br label %82
82: ; preds = %75, %56
%83 = load i32, i32* %10
%84 = icmp ule i32 %83, 127
br i1 %84, label %85, label %98
85: ; preds = %82
%86 = load i8*, i8** %4
%87 = icmp ne i8* %86, null
br i1 %87, label %88, label %95
88: ; preds = %85
%89 = load i32, i32* %10
%90 = trunc i32 %89 to i8
%91 = load i8*, i8** %4
%92 = load i32, i32* %8
%93 = sext i32 %92 to i64
%94 = getelementptr inbounds i8, i8* %91, i64 %93
store i8 %90, i8* %94
br label %95
95: ; preds = %88, %85
%96 = load i32, i32* %8
%97 = add nsw i32 %96, 1
store i32 %97, i32* %8
br label %369
98: ; preds = %82
%99 = load i32, i32* %10
%100 = icmp ule i32 %99, 2047
br i1 %100, label %101, label %132
101: ; preds = %98
%102 = load i32, i32* %8
%103 = load i32, i32* %6
%104 = sub nsw i32 %103, 2
%105 = icmp sge i32 %102, %104
br i1 %105, label %106, label %107
106: ; preds = %101
br label %373
107: ; preds = %101
%108 = load i8*, i8** %4
%109 = icmp ne i8* %108, null
br i1 %109, label %110, label %129
110: ; preds = %107
%111 = load i32, i32* %10
%112 = lshr i32 %111, 6
%113 = and i32 %112, 31
%114 = or i32 192, %113
%115 = trunc i32 %114 to i8
%116 = load i8*, i8** %4
%117 = load i32, i32* %8
%118 = sext i32 %117 to i64
%119 = getelementptr inbounds i8, i8* %116, i64 %118
store i8 %115, i8* %119
%120 = load i32, i32* %10
%121 = and i32 %120, 63
%122 = or i32 128, %121
%123 = trunc i32 %122 to i8
%124 = load i8*, i8** %4
%125 = load i32, i32* %8
%126 = add nsw i32 %125, 1
%127 = sext i32 %126 to i64
%128 = getelementptr inbounds i8, i8* %124, i64 %127
store i8 %123, i8* %128
br label %129
129: ; preds = %110, %107
%130 = load i32, i32* %8
%131 = add nsw i32 %130, 2
store i32 %131, i32* %8
br label %368
132: ; preds = %98
%133 = load i32, i32* %10
%134 = icmp ule i32 %133, 65535
br i1 %134, label %135, label %176
135: ; preds = %132
%136 = load i32, i32* %8
%137 = load i32, i32* %6
%138 = sub nsw i32 %137, 3
%139 = icmp sge i32 %136, %138
br i1 %139, label %140, label %141
140: ; preds = %135
br label %373
141: ; preds = %135
%142 = load i8*, i8** %4
%143 = icmp ne i8* %142, null
br i1 %143, label %144, label %173
144: ; preds = %141
%145 = load i32, i32* %10
%146 = lshr i32 %145, 12
%147 = and i32 %146, 15
%148 = or i32 224, %147
%149 = trunc i32 %148 to i8
%150 = load i8*, i8** %4
%151 = load i32, i32* %8
%152 = sext i32 %151 to i64
%153 = getelementptr inbounds i8, i8* %150, i64 %152
store i8 %149, i8* %153
%154 = load i32, i32* %10
%155 = lshr i32 %154, 6
%156 = and i32 %155, 63
%157 = or i32 128, %156
%158 = trunc i32 %157 to i8
%159 = load i8*, i8** %4
%160 = load i32, i32* %8
%161 = add nsw i32 %160, 1
%162 = sext i32 %161 to i64
%163 = getelementptr inbounds i8, i8* %159, i64 %162
store i8 %158, i8* %163
%164 = load i32, i32* %10
%165 = and i32 %164, 63
%166 = or i32 128, %165
%167 = trunc i32 %166 to i8
%168 = load i8*, i8** %4
%169 = load i32, i32* %8
%170 = add nsw i32 %169, 2
%171 = sext i32 %170 to i64
%172 = getelementptr inbounds i8, i8* %168, i64 %171
store i8 %167, i8* %172
br label %173
173: ; preds = %144, %141
%174 = load i32, i32* %8
%175 = add nsw i32 %174, 3
store i32 %175, i32* %8
br label %367
176: ; preds = %132
%177 = load i32, i32* %10
%178 = icmp ule i32 %177, 2097151
br i1 %178, label %179, label %230
179: ; preds = %176
%180 = load i32, i32* %8
%181 = load i32, i32* %6
%182 = sub nsw i32 %181, 4
%183 = icmp sge i32 %180, %182
br i1 %183, label %184, label %185
184: ; preds = %179
br label %373
185: ; preds = %179
%186 = load i8*, i8** %4
%187 = icmp ne i8* %186, null
br i1 %187, label %188, label %227
188: ; preds = %185
%189 = load i32, i32* %10
%190 = lshr i32 %189, 18
%191 = and i32 %190, 7
%192 = or i32 240, %191
%193 = trunc i32 %192 to i8
%194 = load i8*, i8** %4
%195 = load i32, i32* %8
%196 = sext i32 %195 to i64
%197 = getelementptr inbounds i8, i8* %194, i64 %196
store i8 %193, i8* %197
%198 = load i32, i32* %10
%199 = lshr i32 %198, 12
%200 = and i32 %199, 63
%201 = or i32 128, %200
%202 = trunc i32 %201 to i8
%203 = load i8*, i8** %4
%204 = load i32, i32* %8
%205 = add nsw i32 %204, 1
%206 = sext i32 %205 to i64
%207 = getelementptr inbounds i8, i8* %203, i64 %206
store i8 %202, i8* %207
%208 = load i32, i32* %10
%209 = lshr i32 %208, 6
%210 = and i32 %209, 63
%211 = or i32 128, %210
%212 = trunc i32 %211 to i8
%213 = load i8*, i8** %4
%214 = load i32, i32* %8
%215 = add nsw i32 %214, 2
%216 = sext i32 %215 to i64
%217 = getelementptr inbounds i8, i8* %213, i64 %216
store i8 %212, i8* %217
%218 = load i32, i32* %10
%219 = and i32 %218, 63
%220 = or i32 128, %219
%221 = trunc i32 %220 to i8
%222 = load i8*, i8** %4
%223 = load i32, i32* %8
%224 = add nsw i32 %223, 3
%225 = sext i32 %224 to i64
%226 = getelementptr inbounds i8, i8* %222, i64 %225
store i8 %221, i8* %226
br label %227
227: ; preds = %188, %185
%228 = load i32, i32* %8
%229 = add nsw i32 %228, 4
store i32 %229, i32* %8
br label %366
230: ; preds = %176
%231 = load i32, i32* %10
%232 = icmp ule i32 %231, 67108863
br i1 %232, label %233, label %294
233: ; preds = %230
%234 = load i32, i32* %8
%235 = load i32, i32* %6
%236 = sub nsw i32 %235, 5
%237 = icmp sge i32 %234, %236
br i1 %237, label %238, label %239
238: ; preds = %233
br label %373
239: ; preds = %233
%240 = load i8*, i8** %4
%241 = icmp ne i8* %240, null
br i1 %241, label %242, label %291
242: ; preds = %239
%243 = load i32, i32* %10
%244 = lshr i32 %243, 24
%245 = and i32 %244, 3
%246 = or i32 248, %245
%247 = trunc i32 %246 to i8
%248 = load i8*, i8** %4
%249 = load i32, i32* %8
%250 = sext i32 %249 to i64
%251 = getelementptr inbounds i8, i8* %248, i64 %250
store i8 %247, i8* %251
%252 = load i32, i32* %10
%253 = lshr i32 %252, 18
%254 = and i32 %253, 63
%255 = or i32 128, %254
%256 = trunc i32 %255 to i8
%257 = load i8*, i8** %4
%258 = load i32, i32* %8
%259 = add nsw i32 %258, 1
%260 = sext i32 %259 to i64
%261 = getelementptr inbounds i8, i8* %257, i64 %260
store i8 %256, i8* %261
%262 = load i32, i32* %10
%263 = lshr i32 %262, 12
%264 = and i32 %263, 63
%265 = or i32 128, %264
%266 = trunc i32 %265 to i8
%267 = load i8*, i8** %4
%268 = load i32, i32* %8
%269 = add nsw i32 %268, 2
%270 = sext i32 %269 to i64
%271 = getelementptr inbounds i8, i8* %267, i64 %270
store i8 %266, i8* %271
%272 = load i32, i32* %10
%273 = lshr i32 %272, 6
%274 = and i32 %273, 63
%275 = or i32 128, %274
%276 = trunc i32 %275 to i8
%277 = load i8*, i8** %4
%278 = load i32, i32* %8
%279 = add nsw i32 %278, 3
%280 = sext i32 %279 to i64
%281 = getelementptr inbounds i8, i8* %277, i64 %280
store i8 %276, i8* %281
%282 = load i32, i32* %10
%283 = and i32 %282, 63
%284 = or i32 128, %283
%285 = trunc i32 %284 to i8
%286 = load i8*, i8** %4
%287 = load i32, i32* %8
%288 = add nsw i32 %287, 4
%289 = sext i32 %288 to i64
%290 = getelementptr inbounds i8, i8* %286, i64 %289
store i8 %285, i8* %290
br label %291
291: ; preds = %242, %239
%292 = load i32, i32* %8
%293 = add nsw i32 %292, 5
store i32 %293, i32* %8
br label %365
294: ; preds = %230
%295 = load i32, i32* %8
%296 = load i32, i32* %6
%297 = sub nsw i32 %296, 6
%298 = icmp sge i32 %295, %297
br i1 %298, label %299, label %300
299: ; preds = %294
br label %373
300: ; preds = %294
%301 = load i8*, i8** %4
%302 = icmp ne i8* %301, null
br i1 %302, label %303, label %362
303: ; preds = %300
%304 = load i32, i32* %10
%305 = lshr i32 %304, 30
%306 = and i32 %305, 1
%307 = or i32 248, %306
%308 = trunc i32 %307 to i8
%309 = load i8*, i8** %4
%310 = load i32, i32* %8
%311 = sext i32 %310 to i64
%312 = getelementptr inbounds i8, i8* %309, i64 %311
store i8 %308, i8* %312
%313 = load i32, i32* %10
%314 = lshr i32 %313, 24
%315 = and i32 %314, 63
%316 = or i32 128, %315
%317 = trunc i32 %316 to i8
%318 = load i8*, i8** %4
%319 = load i32, i32* %8
%320 = add nsw i32 %319, 1
%321 = sext i32 %320 to i64
%322 = getelementptr inbounds i8, i8* %318, i64 %321
store i8 %317, i8* %322
%323 = load i32, i32* %10
%324 = lshr i32 %323, 18
%325 = and i32 %324, 63
%326 = or i32 128, %325
%327 = trunc i32 %326 to i8
%328 = load i8*, i8** %4
%329 = load i32, i32* %8
%330 = add nsw i32 %329, 2
%331 = sext i32 %330 to i64
%332 = getelementptr inbounds i8, i8* %328, i64 %331
store i8 %327, i8* %332
%333 = load i32, i32* %10
%334 = lshr i32 %333, 12
%335 = and i32 %334, 63
%336 = or i32 128, %335
%337 = trunc i32 %336 to i8
%338 = load i8*, i8** %4
%339 = load i32, i32* %8
%340 = add nsw i32 %339, 3
%341 = sext i32 %340 to i64
%342 = getelementptr inbounds i8, i8* %338, i64 %341
store i8 %337, i8* %342
%343 = load i32, i32* %10
%344 = lshr i32 %343, 6
%345 = and i32 %344, 63
%346 = or i32 128, %345
%347 = trunc i32 %346 to i8
%348 = load i8*, i8** %4
%349 = load i32, i32* %8
%350 = add nsw i32 %349, 4
%351 = sext i32 %350 to i64
%352 = getelementptr inbounds i8, i8* %348, i64 %351
store i8 %347, i8* %352
%353 = load i32, i32* %10
%354 = and i32 %353, 63
%355 = or i32 128, %354
%356 = trunc i32 %355 to i8
%357 = load i8*, i8** %4
%358 = load i32, i32* %8
%359 = add nsw i32 %358, 5
%360 = sext i32 %359 to i64
%361 = getelementptr inbounds i8, i8* %357, i64 %360
store i8 %356, i8* %361
br label %362
362: ; preds = %303, %300
%363 = load i32, i32* %8
%364 = add nsw i32 %363, 6
store i32 %364, i32* %8
br label %365
365: ; preds = %362, %291
br label %366
366: ; preds = %365, %227
br label %367
367: ; preds = %366, %173
br label %368
368: ; preds = %367, %129
br label %369
369: ; preds = %368, %95
br label %370
370: ; preds = %369
%371 = load i32, i32* %7
%372 = add nsw i32 %371, 1
store i32 %372, i32* %7
br label %16
373: ; preds = %299, %238, %184, %140, %106, %29
%374 = load i8*, i8** %4
%375 = icmp ne i8* %374, null
br i1 %375, label %376, label %381
376: ; preds = %373
%377 = load i8*, i8** %4
%378 = load i32, i32* %8
%379 = sext i32 %378 to i64
%380 = getelementptr inbounds i8, i8* %377, i64 %379
store i8 0, i8* %380
br label %381
381: ; preds = %376, %373
%382 = load i32, i32* %8
%383 = add nsw i32 %382, 1
store i32 %383, i32* %8
%384 = load i32, i32* %8
ret i32 %384
}

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