int opa_unicode_decode_utf8(const char *in, int i, int len, int *olen) {
  if (i >= len) {
    return -1;
  }
  unsigned char c0 = in[i];
  if ((c0 & 0b10000000) == 0) {
    *olen = 1;
    return (int)c0;
  }
  if ((c0 & 0b11100000) == 0b11000000) {
    if ((i + 1) >= len) {
      return -1;
    }
    if (c0 == 0xc0 || c0 == 0xc1) {
      return -1;
    }
    unsigned char c1 = in[i + 1];
    if (!(c1 >= 0x80 && c1 <= 0xbf)) {
      return -1;
    }
    *olen = 2;
    return (int)(c0 & 0b00011111) << 6 | (int)(c1 & 0b00111111);
  }
  if ((c0 & 0b11110000) == 0b11100000) {
    if ((i + 2) >= len) {
      return -1;
    }
    unsigned char c1 = in[i + 1];
    unsigned char c2 = in[i + 2];
    if (!((c0 == 0xe0 && c1 >= 0xa0 && c1 <= 0xbf && c2 >= 0x80 &&
           c2 <= 0xbf) ||
          (c0 >= 0xe1 && c0 <= 0xec && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 &&
           c2 <= 0xbf) ||
          (c0 == 0xed && c1 >= 0x80 && c1 <= 0x9f && c2 >= 0x80 &&
           c2 <= 0xbf) ||
          (c0 >= 0xee && c0 <= 0xef && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 &&
           c2 <= 0xbf))) {
      return -1;
    }
    *olen = 3;
    return (int)(c0 & 0b00001111) << 12 | (int)(c1 & 0b00111111) << 6 |
           (int)(c2 & 0b00111111);
  }
  if ((c0 & 0b11111000) == 0b11110000) {
    if ((i + 3) >= len) {
      return -1;
    }
    unsigned char c1 = in[i + 1];
    unsigned char c2 = in[i + 2];
    unsigned char c3 = in[i + 3];
    if (!((c0 == 0xf0 && c1 >= 0x90 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf &&
           c3 >= 0x80 && c3 <= 0xbf) ||
          (c0 >= 0xf1 && c0 <= 0xf3 && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 &&
           c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) ||
          (c0 == 0xf4 && c1 >= 0x80 && c1 <= 0x8f && c2 >= 0x80 && c2 <= 0xbf &&
           c3 >= 0x80 && c3 <= 0xbf))) {
      return -1;
    }
    *olen = 4;
    return (int)(c0 & 0b00000111) << 18 | (int)(c1 & 0b00111111) << 12 |
           (int)(c2 & 0b00111111) << 6 | (int)(c3 & 0b00111111);
  }
  return -1;
}


x86 assembly (clang, -O0):
<opa_unicode_decode_utf8>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    %edx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    -0x14(%rbp),%eax
cmp    -0x18(%rbp),%eax
jl     112a <opa_unicode_decode_utf8+0x2a>
movl   $0xffffffff,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
mov    (%rax,%rcx,1),%al
mov    %al,-0x21(%rbp)
movzbl -0x21(%rbp),%eax
and    $0x80,%eax
cmp    $0x0,%eax
jne    1160 <opa_unicode_decode_utf8+0x60>
mov    -0x20(%rbp),%rax
movl   $0x1,(%rax)
movzbl -0x21(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
movzbl -0x21(%rbp),%eax
and    $0xe0,%eax
cmp    $0xc0,%eax
jne    121b <opa_unicode_decode_utf8+0x11b>
mov    -0x14(%rbp),%eax
add    $0x1,%eax
cmp    -0x18(%rbp),%eax
jl     118f <opa_unicode_decode_utf8+0x8f>
movl   $0xffffffff,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
movzbl -0x21(%rbp),%eax
cmp    $0xc0,%eax
je     11ad <opa_unicode_decode_utf8+0xad>
movzbl -0x21(%rbp),%eax
cmp    $0xc1,%eax
jne    11b9 <opa_unicode_decode_utf8+0xb9>
movl   $0xffffffff,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
mov    -0x10(%rbp),%rax
mov    -0x14(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,1),%al
mov    %al,-0x22(%rbp)
movzbl -0x22(%rbp),%eax
cmp    $0x80,%eax
jl     11ea <opa_unicode_decode_utf8+0xea>
movzbl -0x22(%rbp),%eax
cmp    $0xbf,%eax
jle    11f6 <opa_unicode_decode_utf8+0xf6>
movl   $0xffffffff,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
mov    -0x20(%rbp),%rax
movl   $0x2,(%rax)
movzbl -0x21(%rbp),%eax
and    $0x1f,%eax
shl    $0x6,%eax
movzbl -0x22(%rbp),%ecx
and    $0x3f,%ecx
or     %ecx,%eax
mov    %eax,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
movzbl -0x21(%rbp),%eax
and    $0xf0,%eax
cmp    $0xe0,%eax
jne    13f7 <opa_unicode_decode_utf8+0x2f7>
mov    -0x14(%rbp),%eax
add    $0x2,%eax
cmp    -0x18(%rbp),%eax
jl     124a <opa_unicode_decode_utf8+0x14a>
movl   $0xffffffff,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
mov    -0x10(%rbp),%rax
mov    -0x14(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,1),%al
mov    %al,-0x23(%rbp)
mov    -0x10(%rbp),%rax
mov    -0x14(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,1),%al
mov    %al,-0x24(%rbp)
movzbl -0x21(%rbp),%eax
cmp    $0xe0,%eax
jne    12bb <opa_unicode_decode_utf8+0x1bb>
movzbl -0x23(%rbp),%eax
cmp    $0xa0,%eax
jl     12bb <opa_unicode_decode_utf8+0x1bb>
movzbl -0x23(%rbp),%eax
cmp    $0xbf,%eax
jg     12bb <opa_unicode_decode_utf8+0x1bb>
movzbl -0x24(%rbp),%eax
cmp    $0x80,%eax
jl     12bb <opa_unicode_decode_utf8+0x1bb>
movzbl -0x24(%rbp),%eax
cmp    $0xbf,%eax
jle    13c6 <opa_unicode_decode_utf8+0x2c6>
movzbl -0x21(%rbp),%eax
cmp    $0xe1,%eax
jl     1315 <opa_unicode_decode_utf8+0x215>
movzbl -0x21(%rbp),%eax
cmp    $0xec,%eax
jg     1315 <opa_unicode_decode_utf8+0x215>
movzbl -0x23(%rbp),%eax
cmp    $0x80,%eax
jl     1315 <opa_unicode_decode_utf8+0x215>
movzbl -0x23(%rbp),%eax
cmp    $0xbf,%eax
jg     1315 <opa_unicode_decode_utf8+0x215>
movzbl -0x24(%rbp),%eax
cmp    $0x80,%eax
jl     1315 <opa_unicode_decode_utf8+0x215>
movzbl -0x24(%rbp),%eax
cmp    $0xbf,%eax
jle    13c6 <opa_unicode_decode_utf8+0x2c6>
movzbl -0x21(%rbp),%eax
cmp    $0xed,%eax
jne    1360 <opa_unicode_decode_utf8+0x260>
movzbl -0x23(%rbp),%eax
cmp    $0x80,%eax
jl     1360 <opa_unicode_decode_utf8+0x260>
movzbl -0x23(%rbp),%eax
cmp    $0x9f,%eax
jg     1360 <opa_unicode_decode_utf8+0x260>
movzbl -0x24(%rbp),%eax
cmp    $0x80,%eax
jl     1360 <opa_unicode_decode_utf8+0x260>
movzbl -0x24(%rbp),%eax
cmp    $0xbf,%eax
jle    13c6 <opa_unicode_decode_utf8+0x2c6>
movzbl -0x21(%rbp),%eax
cmp    $0xee,%eax
jl     13ba <opa_unicode_decode_utf8+0x2ba>
movzbl -0x21(%rbp),%eax
cmp    $0xef,%eax
jg     13ba <opa_unicode_decode_utf8+0x2ba>
movzbl -0x23(%rbp),%eax
cmp    $0x80,%eax
jl     13ba <opa_unicode_decode_utf8+0x2ba>
movzbl -0x23(%rbp),%eax
cmp    $0xbf,%eax
jg     13ba <opa_unicode_decode_utf8+0x2ba>
movzbl -0x24(%rbp),%eax
cmp    $0x80,%eax
jl     13ba <opa_unicode_decode_utf8+0x2ba>
movzbl -0x24(%rbp),%eax
cmp    $0xbf,%eax
jle    13c6 <opa_unicode_decode_utf8+0x2c6>
movl   $0xffffffff,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
mov    -0x20(%rbp),%rax
movl   $0x3,(%rax)
movzbl -0x21(%rbp),%eax
and    $0xf,%eax
shl    $0xc,%eax
movzbl -0x23(%rbp),%ecx
and    $0x3f,%ecx
shl    $0x6,%ecx
or     %ecx,%eax
movzbl -0x24(%rbp),%ecx
and    $0x3f,%ecx
or     %ecx,%eax
mov    %eax,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
movzbl -0x21(%rbp),%eax
and    $0xf8,%eax
cmp    $0xf0,%eax
jne    15f2 <opa_unicode_decode_utf8+0x4f2>
mov    -0x14(%rbp),%eax
add    $0x3,%eax
cmp    -0x18(%rbp),%eax
jl     1426 <opa_unicode_decode_utf8+0x326>
movl   $0xffffffff,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
mov    -0x10(%rbp),%rax
mov    -0x14(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,1),%al
mov    %al,-0x25(%rbp)
mov    -0x10(%rbp),%rax
mov    -0x14(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,1),%al
mov    %al,-0x26(%rbp)
mov    -0x10(%rbp),%rax
mov    -0x14(%rbp),%ecx
add    $0x3,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,1),%al
mov    %al,-0x27(%rbp)
movzbl -0x21(%rbp),%eax
cmp    $0xf0,%eax
jne    14c8 <opa_unicode_decode_utf8+0x3c8>
movzbl -0x25(%rbp),%eax
cmp    $0x90,%eax
jl     14c8 <opa_unicode_decode_utf8+0x3c8>
movzbl -0x25(%rbp),%eax
cmp    $0xbf,%eax
jg     14c8 <opa_unicode_decode_utf8+0x3c8>
movzbl -0x26(%rbp),%eax
cmp    $0x80,%eax
jl     14c8 <opa_unicode_decode_utf8+0x3c8>
movzbl -0x26(%rbp),%eax
cmp    $0xbf,%eax
jg     14c8 <opa_unicode_decode_utf8+0x3c8>
movzbl -0x27(%rbp),%eax
cmp    $0x80,%eax
jl     14c8 <opa_unicode_decode_utf8+0x3c8>
movzbl -0x27(%rbp),%eax
cmp    $0xbf,%eax
jle    15b5 <opa_unicode_decode_utf8+0x4b5>
movzbl -0x21(%rbp),%eax
cmp    $0xf1,%eax
jl     1540 <opa_unicode_decode_utf8+0x440>
movzbl -0x21(%rbp),%eax
cmp    $0xf3,%eax
jg     1540 <opa_unicode_decode_utf8+0x440>
movzbl -0x25(%rbp),%eax
cmp    $0x80,%eax
jl     1540 <opa_unicode_decode_utf8+0x440>
movzbl -0x25(%rbp),%eax
cmp    $0xbf,%eax
jg     1540 <opa_unicode_decode_utf8+0x440>
movzbl -0x26(%rbp),%eax
cmp    $0x80,%eax
jl     1540 <opa_unicode_decode_utf8+0x440>
movzbl -0x26(%rbp),%eax
cmp    $0xbf,%eax
jg     1540 <opa_unicode_decode_utf8+0x440>
movzbl -0x27(%rbp),%eax
cmp    $0x80,%eax
jl     1540 <opa_unicode_decode_utf8+0x440>
movzbl -0x27(%rbp),%eax
cmp    $0xbf,%eax
jle    15b5 <opa_unicode_decode_utf8+0x4b5>
movzbl -0x21(%rbp),%eax
cmp    $0xf4,%eax
jne    15a9 <opa_unicode_decode_utf8+0x4a9>
movzbl -0x25(%rbp),%eax
cmp    $0x80,%eax
jl     15a9 <opa_unicode_decode_utf8+0x4a9>
movzbl -0x25(%rbp),%eax
cmp    $0x8f,%eax
jg     15a9 <opa_unicode_decode_utf8+0x4a9>
movzbl -0x26(%rbp),%eax
cmp    $0x80,%eax
jl     15a9 <opa_unicode_decode_utf8+0x4a9>
movzbl -0x26(%rbp),%eax
cmp    $0xbf,%eax
jg     15a9 <opa_unicode_decode_utf8+0x4a9>
movzbl -0x27(%rbp),%eax
cmp    $0x80,%eax
jl     15a9 <opa_unicode_decode_utf8+0x4a9>
movzbl -0x27(%rbp),%eax
cmp    $0xbf,%eax
jle    15b5 <opa_unicode_decode_utf8+0x4b5>
movl   $0xffffffff,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
mov    -0x20(%rbp),%rax
movl   $0x4,(%rax)
movzbl -0x21(%rbp),%eax
and    $0x7,%eax
shl    $0x12,%eax
movzbl -0x25(%rbp),%ecx
and    $0x3f,%ecx
shl    $0xc,%ecx
or     %ecx,%eax
movzbl -0x26(%rbp),%ecx
and    $0x3f,%ecx
shl    $0x6,%ecx
or     %ecx,%eax
movzbl -0x27(%rbp),%ecx
and    $0x3f,%ecx
or     %ecx,%eax
mov    %eax,-0x4(%rbp)
jmp    15f9 <opa_unicode_decode_utf8+0x4f9>
movl   $0xffffffff,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<opa_unicode_decode_utf8>:
mov    $0xffffffff,%eax
cmp    %edx,%esi
jge    131e <opa_unicode_decode_utf8+0x21e>
movslq %esi,%r11
movzbl (%rdi,%r11,1),%r9d
test   $0x80,%r9b
jne    1125 <opa_unicode_decode_utf8+0x25>
movl   $0x1,(%rcx)
mov    %r9d,%eax
ret
mov    %r9d,%esi
and    $0xffffffe0,%esi
cmp    $0xc0,%esi
jne    1174 <opa_unicode_decode_utf8+0x74>
add    $0x1,%r11
cmp    %edx,%r11d
jge    131e <opa_unicode_decode_utf8+0x21e>
mov    %r9d,%edx
and    $0xfe,%dl
cmp    $0xc0,%dl
je     131e <opa_unicode_decode_utf8+0x21e>
movzbl (%rdi,%r11,1),%edx
cmp    $0xbf,%dl
jg     131e <opa_unicode_decode_utf8+0x21e>
movl   $0x2,(%rcx)
and    $0x1f,%r9d
shl    $0x6,%r9d
and    $0x3f,%edx
or     %r9d,%edx
mov    %edx,%eax
ret
mov    %r9d,%esi
and    $0xfffffff0,%esi
cmp    $0xe0,%esi
jne    124e <opa_unicode_decode_utf8+0x14e>
lea    0x2(%r11),%r8
cmp    %edx,%r8d
jge    131e <opa_unicode_decode_utf8+0x21e>
mov    0x1(%r11,%rdi,1),%r10b
mov    (%rdi,%r8,1),%dil
cmp    $0xe0,%r9b
jne    11b9 <opa_unicode_decode_utf8+0xb9>
cmp    $0xa0,%r10b
jb     11b9 <opa_unicode_decode_utf8+0xb9>
cmp    $0xbf,%r10b
ja     11b9 <opa_unicode_decode_utf8+0xb9>
test   %dil,%dil
jns    11b9 <opa_unicode_decode_utf8+0xb9>
cmp    $0xc0,%dil
jb     122a <opa_unicode_decode_utf8+0x12a>
lea    0x1f(%r9),%esi
cmp    $0xb,%sil
ja     11d9 <opa_unicode_decode_utf8+0xd9>
test   %r10b,%r10b
jns    11d9 <opa_unicode_decode_utf8+0xd9>
cmp    $0xbf,%r10b
ja     11d9 <opa_unicode_decode_utf8+0xd9>
test   %dil,%dil
jns    11d9 <opa_unicode_decode_utf8+0xd9>
cmp    $0xc0,%dil
jb     122a <opa_unicode_decode_utf8+0x12a>
cmp    $0xed,%r9b
jne    11f5 <opa_unicode_decode_utf8+0xf5>
test   %r10b,%r10b
jns    11f5 <opa_unicode_decode_utf8+0xf5>
cmp    $0x9f,%r10b
ja     11f5 <opa_unicode_decode_utf8+0xf5>
test   %dil,%dil
jns    11f5 <opa_unicode_decode_utf8+0xf5>
cmp    $0xc0,%dil
jb     122a <opa_unicode_decode_utf8+0x12a>
mov    %r9d,%edx
and    $0xfe,%dl
cmp    $0xee,%dl
jne    131e <opa_unicode_decode_utf8+0x21e>
test   %r10b,%r10b
jns    131e <opa_unicode_decode_utf8+0x21e>
cmp    $0xbf,%r10b
ja     131e <opa_unicode_decode_utf8+0x21e>
test   %dil,%dil
jns    131e <opa_unicode_decode_utf8+0x21e>
cmp    $0xbf,%dil
ja     131e <opa_unicode_decode_utf8+0x21e>
movzbl %r10b,%edx
movzbl %dil,%eax
movl   $0x3,(%rcx)
shl    $0xc,%r9d
movzwl %r9w,%ecx
and    $0x3f,%edx
shl    $0x6,%edx
or     %ecx,%edx
and    $0x3f,%eax
or     %edx,%eax
ret
mov    %r9d,%esi
and    $0xfffffff8,%esi
cmp    $0xf0,%esi
jne    131e <opa_unicode_decode_utf8+0x21e>
lea    0x3(%r11),%r10
cmp    %edx,%r10d
jge    131e <opa_unicode_decode_utf8+0x21e>
mov    0x1(%r11,%rdi,1),%dl
mov    0x2(%r11,%rdi,1),%r8b
mov    (%rdi,%r10,1),%dil
cmp    $0xf0,%r9b
jne    12a1 <opa_unicode_decode_utf8+0x1a1>
cmp    $0x90,%dl
jb     12a1 <opa_unicode_decode_utf8+0x1a1>
cmp    $0xbf,%dl
ja     12a1 <opa_unicode_decode_utf8+0x1a1>
test   %r8b,%r8b
jns    12a1 <opa_unicode_decode_utf8+0x1a1>
cmp    $0xbf,%r8b
ja     12a1 <opa_unicode_decode_utf8+0x1a1>
test   %dil,%dil
jns    12a1 <opa_unicode_decode_utf8+0x1a1>
cmp    $0xc0,%dil
jb     12ef <opa_unicode_decode_utf8+0x1ef>
lea    0xf(%r9),%esi
cmp    $0x2,%sil
ja     12ca <opa_unicode_decode_utf8+0x1ca>
test   %dl,%dl
jns    12ca <opa_unicode_decode_utf8+0x1ca>
cmp    $0xbf,%dl
ja     12ca <opa_unicode_decode_utf8+0x1ca>
test   %r8b,%r8b
jns    12ca <opa_unicode_decode_utf8+0x1ca>
cmp    $0xbf,%r8b
ja     12ca <opa_unicode_decode_utf8+0x1ca>
test   %dil,%dil
jns    12ca <opa_unicode_decode_utf8+0x1ca>
cmp    $0xc0,%dil
jb     12ef <opa_unicode_decode_utf8+0x1ef>
cmp    $0xf4,%r9b
jne    131e <opa_unicode_decode_utf8+0x21e>
test   %dl,%dl
jns    131e <opa_unicode_decode_utf8+0x21e>
cmp    $0x8f,%dl
ja     131e <opa_unicode_decode_utf8+0x21e>
test   %r8b,%r8b
jns    131e <opa_unicode_decode_utf8+0x21e>
cmp    $0xbf,%r8b
ja     131e <opa_unicode_decode_utf8+0x21e>
test   %dil,%dil
jns    131e <opa_unicode_decode_utf8+0x21e>
cmp    $0xbf,%dil
ja     131e <opa_unicode_decode_utf8+0x21e>
movzbl %dl,%edx
movzbl %r8b,%esi
movzbl %dil,%eax
movl   $0x4,(%rcx)
and    $0x7,%r9d
shl    $0x12,%r9d
and    $0x3f,%edx
shl    $0xc,%edx
or     %r9d,%edx
and    $0x3f,%esi
shl    $0x6,%esi
or     %edx,%esi
and    $0x3f,%eax
or     %esi,%eax
ret

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

LLVM IR (-O2):
define i32 @opa_unicode_decode_utf8(i8* nocapture %0, i32 %1, i32 %2, i32* nocapture writeonly %3) {
%5 = icmp slt i32 %1, %2
br i1 %5, label %6, label %153
6: ; preds = %4
%7 = sext i32 %1 to i64
%8 = getelementptr inbounds i8, i8* %0, i64 %7
%9 = load i8, i8* %8
%10 = zext i8 %9 to i32
%11 = and i32 %10, 128
%12 = icmp eq i32 %11, 0
br i1 %12, label %13, label %14
13: ; preds = %6
store i32 1, i32* %3
br label %153
14: ; preds = %6
%15 = and i32 %10, 224
%16 = icmp eq i32 %15, 192
br i1 %16, label %17, label %34
17: ; preds = %14
%18 = add nsw i32 %1, 1
%19 = icmp sge i32 %18, %2
%20 = and i8 %9, -2
%21 = icmp eq i8 %20, -64
%22 = select i1 %19, i1 true, i1 %21
br i1 %22, label %153, label %23
23: ; preds = %17
%24 = sext i32 %18 to i64
%25 = getelementptr inbounds i8, i8* %0, i64 %24
%26 = load i8, i8* %25
%27 = icmp slt i8 %26, -64
br i1 %27, label %28, label %153
28: ; preds = %23
store i32 2, i32* %3
%29 = shl nuw nsw i32 %10, 6
%30 = and i32 %29, 1984
%31 = and i8 %26, 63
%32 = zext i8 %31 to i32
%33 = or i32 %30, %32
br label %153
34: ; preds = %14
%35 = and i32 %10, 240
%36 = icmp eq i32 %35, 224
br i1 %36, label %37, label %89
37: ; preds = %34
%38 = add nsw i32 %1, 2
%39 = icmp slt i32 %38, %2
br i1 %39, label %40, label %153
40: ; preds = %37
%41 = add nsw i32 %1, 1
%42 = sext i32 %41 to i64
%43 = getelementptr inbounds i8, i8* %0, i64 %42
%44 = load i8, i8* %43
%45 = sext i32 %38 to i64
%46 = getelementptr inbounds i8, i8* %0, i64 %45
%47 = load i8, i8* %46
%48 = icmp eq i8 %9, -32
%49 = icmp ugt i8 %44, -97
%50 = select i1 %48, i1 %49, i1 false
%51 = icmp ult i8 %44, -64
%52 = select i1 %50, i1 %51, i1 false
%53 = icmp slt i8 %47, 0
%54 = select i1 %52, i1 %53, i1 false
%55 = icmp ult i8 %47, -64
%56 = select i1 %54, i1 %55, i1 false
br i1 %56, label %79, label %57
57: ; preds = %40
%58 = add i8 %9, 31
%59 = icmp ult i8 %58, 12
%60 = icmp slt i8 %44, 0
%61 = select i1 %59, i1 %60, i1 false
%62 = select i1 %61, i1 %51, i1 false
%63 = select i1 %62, i1 %53, i1 false
%64 = select i1 %63, i1 %55, i1 false
br i1 %64, label %79, label %65
65: ; preds = %57
%66 = icmp eq i8 %9, -19
%67 = select i1 %66, i1 %60, i1 false
%68 = icmp ult i8 %44, -96
%69 = select i1 %67, i1 %68, i1 false
%70 = select i1 %69, i1 %53, i1 false
%71 = select i1 %70, i1 %55, i1 false
br i1 %71, label %79, label %72
72: ; preds = %65
%73 = and i8 %9, -2
%74 = icmp eq i8 %73, -18
%75 = select i1 %74, i1 %60, i1 false
%76 = select i1 %75, i1 %51, i1 false
%77 = select i1 %76, i1 %53, i1 false
%78 = select i1 %77, i1 %55, i1 false
br i1 %78, label %79, label %153
79: ; preds = %72, %65, %57, %40
store i32 3, i32* %3
%80 = shl nuw nsw i32 %10, 12
%81 = and i32 %80, 61440
%82 = and i8 %44, 63
%83 = zext i8 %82 to i32
%84 = shl nuw nsw i32 %83, 6
%85 = or i32 %84, %81
%86 = and i8 %47, 63
%87 = zext i8 %86 to i32
%88 = or i32 %85, %87
br label %153
89: ; preds = %34
%90 = and i32 %10, 248
%91 = icmp eq i32 %90, 240
br i1 %91, label %92, label %153
92: ; preds = %89
%93 = add nsw i32 %1, 3
%94 = icmp slt i32 %93, %2
br i1 %94, label %95, label %153
95: ; preds = %92
%96 = add nsw i32 %1, 1
%97 = sext i32 %96 to i64
%98 = getelementptr inbounds i8, i8* %0, i64 %97
%99 = load i8, i8* %98
%100 = add nsw i32 %1, 2
%101 = sext i32 %100 to i64
%102 = getelementptr inbounds i8, i8* %0, i64 %101
%103 = load i8, i8* %102
%104 = sext i32 %93 to i64
%105 = getelementptr inbounds i8, i8* %0, i64 %104
%106 = load i8, i8* %105
%107 = icmp eq i8 %9, -16
%108 = icmp ugt i8 %99, -113
%109 = select i1 %107, i1 %108, i1 false
%110 = icmp ult i8 %99, -64
%111 = select i1 %109, i1 %110, i1 false
%112 = icmp slt i8 %103, 0
%113 = select i1 %111, i1 %112, i1 false
%114 = icmp ult i8 %103, -64
%115 = select i1 %113, i1 %114, i1 false
%116 = icmp slt i8 %106, 0
%117 = select i1 %115, i1 %116, i1 false
%118 = icmp ult i8 %106, -64
%119 = select i1 %117, i1 %118, i1 false
br i1 %119, label %139, label %120
120: ; preds = %95
%121 = add i8 %9, 15
%122 = icmp ult i8 %121, 3
%123 = icmp slt i8 %99, 0
%124 = select i1 %122, i1 %123, i1 false
%125 = select i1 %124, i1 %110, i1 false
%126 = select i1 %125, i1 %112, i1 false
%127 = select i1 %126, i1 %114, i1 false
%128 = select i1 %127, i1 %116, i1 false
%129 = select i1 %128, i1 %118, i1 false
br i1 %129, label %139, label %130
130: ; preds = %120
%131 = icmp eq i8 %9, -12
%132 = select i1 %131, i1 %123, i1 false
%133 = icmp ult i8 %99, -112
%134 = select i1 %132, i1 %133, i1 false
%135 = select i1 %134, i1 %112, i1 false
%136 = select i1 %135, i1 %114, i1 false
%137 = select i1 %136, i1 %116, i1 false
%138 = select i1 %137, i1 %118, i1 false
br i1 %138, label %139, label %153
139: ; preds = %130, %120, %95
store i32 4, i32* %3
%140 = shl nuw nsw i32 %10, 18
%141 = and i32 %140, 1835008
%142 = and i8 %99, 63
%143 = zext i8 %142 to i32
%144 = shl nuw nsw i32 %143, 12
%145 = or i32 %144, %141
%146 = and i8 %103, 63
%147 = zext i8 %146 to i32
%148 = shl nuw nsw i32 %147, 6
%149 = or i32 %145, %148
%150 = and i8 %106, 63
%151 = zext i8 %150 to i32
%152 = or i32 %149, %151
br label %153
153: ; preds = %13, %17, %23, %28, %37, %72, %79, %92, %130, %139, %89, %4
%154 = phi i32 [ -1, %4 ], [ %10, %13 ], [ -1, %17 ], [ %33, %28 ], [ -1, %23 ], [ -1, %37 ], [ %88, %79 ], [ -1, %72 ], [ -1, %92 ], [ %152, %139 ], [ -1, %130 ], [ -1, %89 ]
ret i32 %154
}