unsigned int makeutf8(char *utf8, const char *utf16, int length) {
  int i;
  unsigned int size;
  unsigned int rem;
  enum { BASE, SURR, ERR } state;
  size = 0;
  rem = 0;
  state = BASE;
  for (i = 0; i < 2 * length; i += 2) {
    switch (state) {
    case BASE:
      if (utf16[i + 1] & 0xf8) {
        if ((utf16[i + 1] & 0xf8) == 0xd8) {
          if (utf16[i + 1] & 4)
            state = ERR;
          else {
            utf8[size++] =
                0xf0 + (utf16[i + 1] & 7) + ((utf16[i] & 0xc0) == 0xc0);
            utf8[size++] = 0x80 + (((utf16[i] + 64) >> 2) & 63);
            rem = utf16[i] & 3;
            state = SURR;
          }
        } else {
          utf8[size++] = 0xe0 + ((utf16[i + 1] >> 4) & 15);
          utf8[size++] =
              0x80 + ((utf16[i + 1] & 15) << 2) + ((utf16[i] >> 6) & 3);
          utf8[size++] = 0x80 + (utf16[i] & 63);
        }
      } else if ((utf16[i] & 0x80) || utf16[i + 1]) {
        utf8[size++] =
            0xc0 + ((utf16[i + 1] & 15) << 2) + ((utf16[i] >> 6) & 3);
        utf8[size++] = 0x80 + (utf16[i] & 63);
      } else
        utf8[size++] = utf16[i];
      break;
    case SURR:
      if ((utf16[i + 1] & 0xfc) == 0xdc) {
        utf8[size++] = 0x80 + (rem << 4) + ((utf16[i + 1] & 3) << 2) +
                       ((utf16[i] >> 6) & 3);
        utf8[size++] = 0x80 + (utf16[i] & 63);
        state = BASE;
      } else
        state = ERR;
      break;
    case ERR:
      break;
    }
  }
  utf8[size] = 0;
  if (state != BASE)
    state = ERR;
  return (state == ERR ? 0 : size);
}


x86 assembly (clang, -O0):
<makeutf8>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movl   $0x0,-0x1c(%rbp)
movl   $0x0,-0x20(%rbp)
movl   $0x0,-0x24(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
mov    -0x14(%rbp),%ecx
shl    $0x1,%ecx
cmp    %ecx,%eax
jge    14bc <makeutf8+0x3bc>
mov    -0x24(%rbp),%eax
mov    %eax,-0x28(%rbp)
test   %eax,%eax
je     1171 <makeutf8+0x71>
jmp    114f <makeutf8+0x4f>
mov    -0x28(%rbp),%eax
sub    $0x1,%eax
je     13f3 <makeutf8+0x2f3>
jmp    1160 <makeutf8+0x60>
mov    -0x28(%rbp),%eax
sub    $0x2,%eax
je     14a4 <makeutf8+0x3a4>
jmp    14a9 <makeutf8+0x3a9>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0xf8,%eax
cmp    $0x0,%eax
je     1321 <makeutf8+0x221>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0xf8,%eax
cmp    $0xd8,%eax
jne    127a <makeutf8+0x17a>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0x4,%eax
cmp    $0x0,%eax
je     11da <makeutf8+0xda>
movl   $0x2,-0x24(%rbp)
jmp    1275 <makeutf8+0x175>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0x7,%eax
add    $0xf0,%eax
mov    -0x10(%rbp),%rcx
movslq -0x18(%rbp),%rdx
movsbl (%rcx,%rdx,1),%ecx
and    $0xc0,%ecx
cmp    $0xc0,%ecx
sete   %cl
and    $0x1,%cl
movzbl %cl,%ecx
add    %ecx,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movsbl (%rax,%rcx,1),%eax
add    $0x40,%eax
sar    $0x2,%eax
and    $0x3f,%eax
add    $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movsbl (%rax,%rcx,1),%eax
and    $0x3,%eax
mov    %eax,-0x20(%rbp)
movl   $0x1,-0x24(%rbp)
jmp    131c <makeutf8+0x21c>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
sar    $0x4,%eax
and    $0xf,%eax
add    $0xe0,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0xf,%eax
shl    $0x2,%eax
add    $0x80,%eax
mov    -0x10(%rbp),%rcx
movslq -0x18(%rbp),%rdx
movsbl (%rcx,%rdx,1),%ecx
sar    $0x6,%ecx
and    $0x3,%ecx
add    %ecx,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movsbl (%rax,%rcx,1),%eax
and    $0x3f,%eax
add    $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
jmp    13ee <makeutf8+0x2ee>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movsbl (%rax,%rcx,1),%eax
and    $0x80,%eax
cmp    $0x0,%eax
jne    1355 <makeutf8+0x255>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
cmp    $0x0,%eax
je     13ca <makeutf8+0x2ca>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0xf,%eax
shl    $0x2,%eax
add    $0xc0,%eax
mov    -0x10(%rbp),%rcx
movslq -0x18(%rbp),%rdx
movsbl (%rcx,%rdx,1),%ecx
sar    $0x6,%ecx
and    $0x3,%ecx
add    %ecx,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movsbl (%rax,%rcx,1),%eax
and    $0x3f,%eax
add    $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
jmp    13e9 <makeutf8+0x2e9>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    (%rax,%rcx,1),%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
jmp    13ee <makeutf8+0x2ee>
jmp    14a9 <makeutf8+0x3a9>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
and    $0xfc,%eax
cmp    $0xdc,%eax
jne    1498 <makeutf8+0x398>
mov    -0x20(%rbp),%eax
shl    $0x4,%eax
add    $0x80,%eax
mov    -0x10(%rbp),%rcx
mov    -0x18(%rbp),%edx
add    $0x1,%edx
movslq %edx,%rdx
movsbl (%rcx,%rdx,1),%ecx
and    $0x3,%ecx
shl    $0x2,%ecx
add    %ecx,%eax
mov    -0x10(%rbp),%rcx
movslq -0x18(%rbp),%rdx
movsbl (%rcx,%rdx,1),%ecx
sar    $0x6,%ecx
and    $0x3,%ecx
add    %ecx,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movsbl (%rax,%rcx,1),%eax
and    $0x3f,%eax
add    $0x80,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
mov    %ecx,%esi
add    $0x1,%esi
mov    %esi,-0x1c(%rbp)
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
movl   $0x0,-0x24(%rbp)
jmp    149f <makeutf8+0x39f>
movl   $0x2,-0x24(%rbp)
jmp    14a9 <makeutf8+0x3a9>
jmp    14a9 <makeutf8+0x3a9>
jmp    14ae <makeutf8+0x3ae>
mov    -0x18(%rbp),%eax
add    $0x2,%eax
mov    %eax,-0x18(%rbp)
jmp    112b <makeutf8+0x2b>
mov    -0x8(%rbp),%rax
mov    -0x1c(%rbp),%ecx
movb   $0x0,(%rax,%rcx,1)
cmpl   $0x0,-0x24(%rbp)
je     14d8 <makeutf8+0x3d8>
movl   $0x2,-0x24(%rbp)
cmpl   $0x2,-0x24(%rbp)
jne    14ec <makeutf8+0x3ec>
xor    %eax,%eax
mov    %eax,-0x2c(%rbp)
jmp    14f2 <makeutf8+0x3f2>
mov    -0x1c(%rbp),%eax
mov    %eax,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<makeutf8>:
test   %edx,%edx
jle    1262 <makeutf8+0x162>
add    %edx,%edx
movslq %edx,%r10
xor    %edx,%edx
xor    %r11d,%r11d
xor    %r8d,%r8d
xor    %r9d,%r9d
jmp    1169 <makeutf8+0x69>
shr    $0x4,%al
or     $0xe0,%al
lea    0x1(%r9),%r11d
mov    %r9d,%ecx
mov    %al,(%rdi,%rcx,1)
movzbl (%rsi,%rdx,1),%eax
movzbl 0x1(%rsi,%rdx,1),%ecx
shr    $0x6,%al
shl    $0x2,%cl
or     %al,%cl
and    $0x3f,%cl
or     $0x80,%cl
lea    0x2(%r9),%eax
mov    %cl,(%rdi,%r11,1)
movzbl (%rsi,%rdx,1),%ecx
and    $0x3f,%cl
or     $0x80,%cl
add    $0x3,%r9d
mov    %cl,(%rdi,%rax,1)
xor    %r11d,%r11d
add    $0x2,%rdx
cmp    %r10,%rdx
jge    1253 <makeutf8+0x153>
cmp    $0x1,%r11d
je     11d0 <makeutf8+0xd0>
test   %r11d,%r11d
jne    115c <makeutf8+0x5c>
movzbl 0x1(%rsi,%rdx,1),%eax
mov    %eax,%ecx
and    $0xf8,%cl
je     1212 <makeutf8+0x112>
cmp    $0xd8,%cl
jne    111a <makeutf8+0x1a>
mov    $0x2,%r11d
test   $0x4,%al
jne    115c <makeutf8+0x5c>
and    $0x7,%al
cmpb   $0xc0,(%rsi,%rdx,1)
sbb    $0xff,%al
or     $0xf0,%al
lea    0x1(%r9),%r8d
mov    %r9d,%ecx
mov    %al,(%rdi,%rcx,1)
movzbl (%rsi,%rdx,1),%eax
add    $0x40,%al
shr    $0x2,%al
or     $0x80,%al
add    $0x2,%r9d
mov    %al,(%rdi,%r8,1)
movzbl (%rsi,%rdx,1),%r8d
and    $0x3,%r8d
mov    $0x1,%r11d
jmp    115c <makeutf8+0x5c>
nopl   0x0(%rax,%rax,1)
movsbl 0x1(%rsi,%rdx,1),%eax
mov    %eax,%ecx
and    $0xfc,%ecx
mov    $0x2,%r11d
cmp    $0xdc,%ecx
jne    115c <makeutf8+0x5c>
mov    %r8d,%ecx
shl    $0x4,%ecx
and    $0x3,%eax
lea    (%rcx,%rax,4),%eax
movzbl (%rsi,%rdx,1),%ecx
shr    $0x6,%cl
or     %cl,%al
add    $0x80,%al
lea    0x1(%r9),%r11d
mov    %r9d,%ecx
mov    %al,(%rdi,%rcx,1)
jmp    123e <makeutf8+0x13e>
movzbl (%rsi,%rdx,1),%ecx
test   %cl,%cl
js     122a <makeutf8+0x12a>
test   %al,%al
jne    122a <makeutf8+0x12a>
mov    %r9d,%eax
add    $0x1,%r9d
jmp    1156 <makeutf8+0x56>
shr    $0x6,%cl
shl    $0x2,%al
or     %cl,%al
or     $0xc0,%al
lea    0x1(%r9),%r11d
mov    %r9d,%ecx
mov    %al,(%rdi,%rcx,1)
movzbl (%rsi,%rdx,1),%eax
and    $0x3f,%al
or     $0x80,%al
add    $0x2,%r9d
mov    %al,(%rdi,%r11,1)
jmp    1159 <makeutf8+0x59>
mov    %r9d,%eax
movb   $0x0,(%rdi,%rax,1)
xor    %eax,%eax
test   %r11d,%r11d
je     1268 <makeutf8+0x168>
ret
movb   $0x0,(%rdi)
xor    %r9d,%r9d
mov    %r9d,%eax
ret

LLVM IR (-O0):
define i32 @makeutf8(i8* %0, i8* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
%10 = alloca i32
store i8* %0, i8** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
store i32 0, i32* %8
store i32 0, i32* %9
store i32 0, i32* %10
store i32 0, i32* %7
br label %11
11: ; preds = %284, %3
%12 = load i32, i32* %7
%13 = load i32, i32* %6
%14 = mul nsw i32 2, %13
%15 = icmp slt i32 %12, %14
br i1 %15, label %16, label %287
16: ; preds = %11
%17 = load i32, i32* %10
switch i32 %17, label %283 [
i32 0, label %18
i32 1, label %227
i32 2, label %282
]
18: ; preds = %16
%19 = load i8*, i8** %5
%20 = load i32, i32* %7
%21 = add nsw i32 %20, 1
%22 = sext i32 %21 to i64
%23 = getelementptr inbounds i8, i8* %19, i64 %22
%24 = load i8, i8* %23
%25 = sext i8 %24 to i32
%26 = and i32 %25, 248
%27 = icmp ne i32 %26, 0
br i1 %27, label %28, label %156
28: ; preds = %18
%29 = load i8*, i8** %5
%30 = load i32, i32* %7
%31 = add nsw i32 %30, 1
%32 = sext i32 %31 to i64
%33 = getelementptr inbounds i8, i8* %29, i64 %32
%34 = load i8, i8* %33
%35 = sext i8 %34 to i32
%36 = and i32 %35, 248
%37 = icmp eq i32 %36, 216
br i1 %37, label %38, label %99
38: ; preds = %28
%39 = load i8*, i8** %5
%40 = load i32, i32* %7
%41 = add nsw i32 %40, 1
%42 = sext i32 %41 to i64
%43 = getelementptr inbounds i8, i8* %39, i64 %42
%44 = load i8, i8* %43
%45 = sext i8 %44 to i32
%46 = and i32 %45, 4
%47 = icmp ne i32 %46, 0
br i1 %47, label %48, label %49
48: ; preds = %38
store i32 2, i32* %10
br label %98
49: ; preds = %38
%50 = load i8*, i8** %5
%51 = load i32, i32* %7
%52 = add nsw i32 %51, 1
%53 = sext i32 %52 to i64
%54 = getelementptr inbounds i8, i8* %50, i64 %53
%55 = load i8, i8* %54
%56 = sext i8 %55 to i32
%57 = and i32 %56, 7
%58 = add nsw i32 240, %57
%59 = load i8*, i8** %5
%60 = load i32, i32* %7
%61 = sext i32 %60 to i64
%62 = getelementptr inbounds i8, i8* %59, i64 %61
%63 = load i8, i8* %62
%64 = sext i8 %63 to i32
%65 = and i32 %64, 192
%66 = icmp eq i32 %65, 192
%67 = zext i1 %66 to i32
%68 = add nsw i32 %58, %67
%69 = trunc i32 %68 to i8
%70 = load i8*, i8** %4
%71 = load i32, i32* %8
%72 = add i32 %71, 1
store i32 %72, i32* %8
%73 = zext i32 %71 to i64
%74 = getelementptr inbounds i8, i8* %70, i64 %73
store i8 %69, i8* %74
%75 = load i8*, i8** %5
%76 = load i32, i32* %7
%77 = sext i32 %76 to i64
%78 = getelementptr inbounds i8, i8* %75, i64 %77
%79 = load i8, i8* %78
%80 = sext i8 %79 to i32
%81 = add nsw i32 %80, 64
%82 = ashr i32 %81, 2
%83 = and i32 %82, 63
%84 = add nsw i32 128, %83
%85 = trunc i32 %84 to i8
%86 = load i8*, i8** %4
%87 = load i32, i32* %8
%88 = add i32 %87, 1
store i32 %88, i32* %8
%89 = zext i32 %87 to i64
%90 = getelementptr inbounds i8, i8* %86, i64 %89
store i8 %85, i8* %90
%91 = load i8*, i8** %5
%92 = load i32, i32* %7
%93 = sext i32 %92 to i64
%94 = getelementptr inbounds i8, i8* %91, i64 %93
%95 = load i8, i8* %94
%96 = sext i8 %95 to i32
%97 = and i32 %96, 3
store i32 %97, i32* %9
store i32 1, i32* %10
br label %98
98: ; preds = %49, %48
br label %155
99: ; preds = %28
%100 = load i8*, i8** %5
%101 = load i32, i32* %7
%102 = add nsw i32 %101, 1
%103 = sext i32 %102 to i64
%104 = getelementptr inbounds i8, i8* %100, i64 %103
%105 = load i8, i8* %104
%106 = sext i8 %105 to i32
%107 = ashr i32 %106, 4
%108 = and i32 %107, 15
%109 = add nsw i32 224, %108
%110 = trunc i32 %109 to i8
%111 = load i8*, i8** %4
%112 = load i32, i32* %8
%113 = add i32 %112, 1
store i32 %113, i32* %8
%114 = zext i32 %112 to i64
%115 = getelementptr inbounds i8, i8* %111, i64 %114
store i8 %110, i8* %115
%116 = load i8*, i8** %5
%117 = load i32, i32* %7
%118 = add nsw i32 %117, 1
%119 = sext i32 %118 to i64
%120 = getelementptr inbounds i8, i8* %116, i64 %119
%121 = load i8, i8* %120
%122 = sext i8 %121 to i32
%123 = and i32 %122, 15
%124 = shl i32 %123, 2
%125 = add nsw i32 128, %124
%126 = load i8*, i8** %5
%127 = load i32, i32* %7
%128 = sext i32 %127 to i64
%129 = getelementptr inbounds i8, i8* %126, i64 %128
%130 = load i8, i8* %129
%131 = sext i8 %130 to i32
%132 = ashr i32 %131, 6
%133 = and i32 %132, 3
%134 = add nsw i32 %125, %133
%135 = trunc i32 %134 to i8
%136 = load i8*, i8** %4
%137 = load i32, i32* %8
%138 = add i32 %137, 1
store i32 %138, i32* %8
%139 = zext i32 %137 to i64
%140 = getelementptr inbounds i8, i8* %136, i64 %139
store i8 %135, i8* %140
%141 = load i8*, i8** %5
%142 = load i32, i32* %7
%143 = sext i32 %142 to i64
%144 = getelementptr inbounds i8, i8* %141, i64 %143
%145 = load i8, i8* %144
%146 = sext i8 %145 to i32
%147 = and i32 %146, 63
%148 = add nsw i32 128, %147
%149 = trunc i32 %148 to i8
%150 = load i8*, i8** %4
%151 = load i32, i32* %8
%152 = add i32 %151, 1
store i32 %152, i32* %8
%153 = zext i32 %151 to i64
%154 = getelementptr inbounds i8, i8* %150, i64 %153
store i8 %149, i8* %154
br label %155
155: ; preds = %99, %98
br label %226
156: ; preds = %18
%157 = load i8*, i8** %5
%158 = load i32, i32* %7
%159 = sext i32 %158 to i64
%160 = getelementptr inbounds i8, i8* %157, i64 %159
%161 = load i8, i8* %160
%162 = sext i8 %161 to i32
%163 = and i32 %162, 128
%164 = icmp ne i32 %163, 0
br i1 %164, label %174, label %165
165: ; preds = %156
%166 = load i8*, i8** %5
%167 = load i32, i32* %7
%168 = add nsw i32 %167, 1
%169 = sext i32 %168 to i64
%170 = getelementptr inbounds i8, i8* %166, i64 %169
%171 = load i8, i8* %170
%172 = sext i8 %171 to i32
%173 = icmp ne i32 %172, 0
br i1 %173, label %174, label %214
174: ; preds = %165, %156
%175 = load i8*, i8** %5
%176 = load i32, i32* %7
%177 = add nsw i32 %176, 1
%178 = sext i32 %177 to i64
%179 = getelementptr inbounds i8, i8* %175, i64 %178
%180 = load i8, i8* %179
%181 = sext i8 %180 to i32
%182 = and i32 %181, 15
%183 = shl i32 %182, 2
%184 = add nsw i32 192, %183
%185 = load i8*, i8** %5
%186 = load i32, i32* %7
%187 = sext i32 %186 to i64
%188 = getelementptr inbounds i8, i8* %185, i64 %187
%189 = load i8, i8* %188
%190 = sext i8 %189 to i32
%191 = ashr i32 %190, 6
%192 = and i32 %191, 3
%193 = add nsw i32 %184, %192
%194 = trunc i32 %193 to i8
%195 = load i8*, i8** %4
%196 = load i32, i32* %8
%197 = add i32 %196, 1
store i32 %197, i32* %8
%198 = zext i32 %196 to i64
%199 = getelementptr inbounds i8, i8* %195, i64 %198
store i8 %194, i8* %199
%200 = load i8*, i8** %5
%201 = load i32, i32* %7
%202 = sext i32 %201 to i64
%203 = getelementptr inbounds i8, i8* %200, i64 %202
%204 = load i8, i8* %203
%205 = sext i8 %204 to i32
%206 = and i32 %205, 63
%207 = add nsw i32 128, %206
%208 = trunc i32 %207 to i8
%209 = load i8*, i8** %4
%210 = load i32, i32* %8
%211 = add i32 %210, 1
store i32 %211, i32* %8
%212 = zext i32 %210 to i64
%213 = getelementptr inbounds i8, i8* %209, i64 %212
store i8 %208, i8* %213
br label %225
214: ; preds = %165
%215 = load i8*, i8** %5
%216 = load i32, i32* %7
%217 = sext i32 %216 to i64
%218 = getelementptr inbounds i8, i8* %215, i64 %217
%219 = load i8, i8* %218
%220 = load i8*, i8** %4
%221 = load i32, i32* %8
%222 = add i32 %221, 1
store i32 %222, i32* %8
%223 = zext i32 %221 to i64
%224 = getelementptr inbounds i8, i8* %220, i64 %223
store i8 %219, i8* %224
br label %225
225: ; preds = %214, %174
br label %226
226: ; preds = %225, %155
br label %283
227: ; preds = %16
%228 = load i8*, i8** %5
%229 = load i32, i32* %7
%230 = add nsw i32 %229, 1
%231 = sext i32 %230 to i64
%232 = getelementptr inbounds i8, i8* %228, i64 %231
%233 = load i8, i8* %232
%234 = sext i8 %233 to i32
%235 = and i32 %234, 252
%236 = icmp eq i32 %235, 220
br i1 %236, label %237, label %280
237: ; preds = %227
%238 = load i32, i32* %9
%239 = shl i32 %238, 4
%240 = add i32 128, %239
%241 = load i8*, i8** %5
%242 = load i32, i32* %7
%243 = add nsw i32 %242, 1
%244 = sext i32 %243 to i64
%245 = getelementptr inbounds i8, i8* %241, i64 %244
%246 = load i8, i8* %245
%247 = sext i8 %246 to i32
%248 = and i32 %247, 3
%249 = shl i32 %248, 2
%250 = add i32 %240, %249
%251 = load i8*, i8** %5
%252 = load i32, i32* %7
%253 = sext i32 %252 to i64
%254 = getelementptr inbounds i8, i8* %251, i64 %253
%255 = load i8, i8* %254
%256 = sext i8 %255 to i32
%257 = ashr i32 %256, 6
%258 = and i32 %257, 3
%259 = add i32 %250, %258
%260 = trunc i32 %259 to i8
%261 = load i8*, i8** %4
%262 = load i32, i32* %8
%263 = add i32 %262, 1
store i32 %263, i32* %8
%264 = zext i32 %262 to i64
%265 = getelementptr inbounds i8, i8* %261, i64 %264
store i8 %260, i8* %265
%266 = load i8*, i8** %5
%267 = load i32, i32* %7
%268 = sext i32 %267 to i64
%269 = getelementptr inbounds i8, i8* %266, i64 %268
%270 = load i8, i8* %269
%271 = sext i8 %270 to i32
%272 = and i32 %271, 63
%273 = add nsw i32 128, %272
%274 = trunc i32 %273 to i8
%275 = load i8*, i8** %4
%276 = load i32, i32* %8
%277 = add i32 %276, 1
store i32 %277, i32* %8
%278 = zext i32 %276 to i64
%279 = getelementptr inbounds i8, i8* %275, i64 %278
store i8 %274, i8* %279
store i32 0, i32* %10
br label %281
280: ; preds = %227
store i32 2, i32* %10
br label %281
281: ; preds = %280, %237
br label %283
282: ; preds = %16
br label %283
283: ; preds = %16, %282, %281, %226
br label %284
284: ; preds = %283
%285 = load i32, i32* %7
%286 = add nsw i32 %285, 2
store i32 %286, i32* %7
br label %11
287: ; preds = %11
%288 = load i8*, i8** %4
%289 = load i32, i32* %8
%290 = zext i32 %289 to i64
%291 = getelementptr inbounds i8, i8* %288, i64 %290
store i8 0, i8* %291
%292 = load i32, i32* %10
%293 = icmp ne i32 %292, 0
br i1 %293, label %294, label %295
294: ; preds = %287
store i32 2, i32* %10
br label %295
295: ; preds = %294, %287
%296 = load i32, i32* %10
%297 = icmp eq i32 %296, 2
br i1 %297, label %298, label %299
298: ; preds = %295
br label %301
299: ; preds = %295
%300 = load i32, i32* %8
br label %301
301: ; preds = %299, %298
%302 = phi i32 [ 0, %298 ], [ %300, %299 ]
ret i32 %302
}

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