int conv_to_utf8(unsigned char *target, unsigned source, unsigned limit) {
  int rc = 0;
  if (source <= 0x0000007f)
    rc = 1;
  else if (source <= 0x000007ff)
    rc = 2;
  else if (source <= 0x0000ffff)
    rc = 3;
  else if (source <= 0x001fffff)
    rc = 4;
  else if (source <= 0x03ffffff)
    rc = 5;
  else
    rc = 6;
  if ((unsigned)rc > limit) {
    rc = 0;
  }
  if (target != 0) {
    switch (rc) {
    case 1:
      target[0] = ((unsigned char)((source) >> ((0) * 8)));
      break;
    case 2:
      target[1] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((0) * 8))) & 0x3f)));
      target[0] =
          ((unsigned char)(0xc0 |
                           (((unsigned char)((source) >> ((0) * 8))) >> 6) |
                           ((((unsigned char)((source) >> ((1) * 8))) & 0x07)
                            << 2)));
      break;
    case 3:
      target[2] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((0) * 8))) & 0x3f)));
      target[1] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((0) * 8))) >> 6) |
                           ((((unsigned char)((source) >> ((1) * 8))) & 0x0f)
                            << 2)));
      target[0] =
          ((unsigned char)(0xe0 |
                           ((int)(((unsigned char)((source) >> ((1) * 8))) &
                                  0xf0) >>
                            4)));
      break;
    case 4:
      target[3] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((0) * 8))) & 0x3f)));
      target[2] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((0) * 8))) >> 6) |
                           ((((unsigned char)((source) >> ((1) * 8))) & 0x0f)
                            << 2)));
      target[1] = ((
          unsigned char)(0x80 |
                         ((int)(((unsigned char)((source) >> ((1) * 8))) &
                                0xf0) >>
                          4) |
                         ((int)(((unsigned char)((source) >> ((2) * 8))) & 0x03)
                          << 4)));
      target[0] =
          ((unsigned char)(0xf0 |
                           ((int)(((unsigned char)((source) >> ((2) * 8))) &
                                  0x1f) >>
                            2)));
      break;
    case 5:
      target[4] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((0) * 8))) & 0x3f)));
      target[3] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((0) * 8))) >> 6) |
                           ((((unsigned char)((source) >> ((1) * 8))) & 0x0f)
                            << 2)));
      target[2] = ((
          unsigned char)(0x80 |
                         ((int)(((unsigned char)((source) >> ((1) * 8))) &
                                0xf0) >>
                          4) |
                         ((int)(((unsigned char)((source) >> ((2) * 8))) & 0x03)
                          << 4)));
      target[1] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((2) * 8))) >> 2)));
      target[0] =
          ((unsigned char)(0xf8 |
                           (((unsigned char)((source) >> ((3) * 8))) & 0x03)));
      break;
    case 6:
      target[5] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((0) * 8))) & 0x3f)));
      target[4] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((0) * 8))) >> 6) |
                           ((((unsigned char)((source) >> ((1) * 8))) & 0x0f)
                            << 2)));
      target[3] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((1) * 8))) >> 4) |
                           ((((unsigned char)((source) >> ((2) * 8))) & 0x03)
                            << 4)));
      target[2] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((2) * 8))) >> 2)));
      target[1] =
          ((unsigned char)(0x80 |
                           (((unsigned char)((source) >> ((3) * 8))) & 0x3f)));
      target[0] =
          ((unsigned char)(0xfc |
                           ((int)(((unsigned char)((source) >> ((3) * 8))) &
                                  0x40) >>
                            6)));
      break;
    }
  }
  return rc;
}


x86 assembly (clang, -O0):
<conv_to_utf8>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %edx,-0x10(%rbp)
movl   $0x0,-0x14(%rbp)
cmpl   $0x7f,-0xc(%rbp)
ja     112b <conv_to_utf8+0x2b>
movl   $0x1,-0x14(%rbp)
jmp    11aa <conv_to_utf8+0xaa>
cmpl   $0x7ff,-0xc(%rbp)
ja     1144 <conv_to_utf8+0x44>
movl   $0x2,-0x14(%rbp)
jmp    11a5 <conv_to_utf8+0xa5>
cmpl   $0xffff,-0xc(%rbp)
ja     115d <conv_to_utf8+0x5d>
movl   $0x3,-0x14(%rbp)
jmp    11a0 <conv_to_utf8+0xa0>
cmpl   $0x1fffff,-0xc(%rbp)
ja     1176 <conv_to_utf8+0x76>
movl   $0x4,-0x14(%rbp)
jmp    119b <conv_to_utf8+0x9b>
cmpl   $0x3ffffff,-0xc(%rbp)
ja     118f <conv_to_utf8+0x8f>
movl   $0x5,-0x14(%rbp)
jmp    1196 <conv_to_utf8+0x96>
movl   $0x6,-0x14(%rbp)
jmp    119b <conv_to_utf8+0x9b>
jmp    11a0 <conv_to_utf8+0xa0>
jmp    11a5 <conv_to_utf8+0xa5>
jmp    11aa <conv_to_utf8+0xaa>
mov    -0x14(%rbp),%eax
cmp    -0x10(%rbp),%eax
jbe    11bd <conv_to_utf8+0xbd>
movl   $0x0,-0x14(%rbp)
cmpq   $0x0,-0x8(%rbp)
je     14bd <conv_to_utf8+0x3bd>
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,%ecx
mov    %rcx,-0x20(%rbp)
sub    $0x5,%eax
ja     14b8 <conv_to_utf8+0x3b8>
mov    -0x20(%rbp),%rax
lea    0xe18(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
mov    -0xc(%rbp),%eax
shr    $0x0,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,(%rax)
jmp    14b8 <conv_to_utf8+0x3b8>
mov    -0xc(%rbp),%eax
shr    $0x0,%eax
movzbl %al,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x1(%rax)
mov    -0xc(%rbp),%eax
shr    $0x0,%eax
movzbl %al,%eax
sar    $0x6,%eax
or     $0xc0,%eax
mov    -0xc(%rbp),%ecx
shr    $0x8,%ecx
movzbl %cl,%ecx
and    $0x7,%ecx
shl    $0x2,%ecx
or     %ecx,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,(%rax)
jmp    14b8 <conv_to_utf8+0x3b8>
mov    -0xc(%rbp),%eax
shr    $0x0,%eax
movzbl %al,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x2(%rax)
mov    -0xc(%rbp),%eax
shr    $0x0,%eax
movzbl %al,%eax
sar    $0x6,%eax
or     $0x80,%eax
mov    -0xc(%rbp),%ecx
shr    $0x8,%ecx
movzbl %cl,%ecx
and    $0xf,%ecx
shl    $0x2,%ecx
or     %ecx,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x1(%rax)
mov    -0xc(%rbp),%eax
shr    $0x8,%eax
movzbl %al,%eax
and    $0xf0,%eax
sar    $0x4,%eax
or     $0xe0,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,(%rax)
jmp    14b8 <conv_to_utf8+0x3b8>
mov    -0xc(%rbp),%eax
shr    $0x0,%eax
movzbl %al,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x3(%rax)
mov    -0xc(%rbp),%eax
shr    $0x0,%eax
movzbl %al,%eax
sar    $0x6,%eax
or     $0x80,%eax
mov    -0xc(%rbp),%ecx
shr    $0x8,%ecx
movzbl %cl,%ecx
and    $0xf,%ecx
shl    $0x2,%ecx
or     %ecx,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x2(%rax)
mov    -0xc(%rbp),%eax
shr    $0x8,%eax
movzbl %al,%eax
and    $0xf0,%eax
sar    $0x4,%eax
or     $0x80,%eax
mov    -0xc(%rbp),%ecx
shr    $0x10,%ecx
movzbl %cl,%ecx
and    $0x3,%ecx
shl    $0x4,%ecx
or     %ecx,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x1(%rax)
mov    -0xc(%rbp),%eax
shr    $0x10,%eax
movzbl %al,%eax
and    $0x1f,%eax
sar    $0x2,%eax
or     $0xf0,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,(%rax)
jmp    14b8 <conv_to_utf8+0x3b8>
mov    -0xc(%rbp),%eax
shr    $0x0,%eax
movzbl %al,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x4(%rax)
mov    -0xc(%rbp),%eax
shr    $0x0,%eax
movzbl %al,%eax
sar    $0x6,%eax
or     $0x80,%eax
mov    -0xc(%rbp),%ecx
shr    $0x8,%ecx
movzbl %cl,%ecx
and    $0xf,%ecx
shl    $0x2,%ecx
or     %ecx,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x3(%rax)
mov    -0xc(%rbp),%eax
shr    $0x8,%eax
movzbl %al,%eax
and    $0xf0,%eax
sar    $0x4,%eax
or     $0x80,%eax
mov    -0xc(%rbp),%ecx
shr    $0x10,%ecx
movzbl %cl,%ecx
and    $0x3,%ecx
shl    $0x4,%ecx
or     %ecx,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x2(%rax)
mov    -0xc(%rbp),%eax
shr    $0x10,%eax
movzbl %al,%eax
sar    $0x2,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x1(%rax)
mov    -0xc(%rbp),%eax
shr    $0x18,%eax
movzbl %al,%eax
and    $0x3,%eax
or     $0xf8,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,(%rax)
jmp    14b8 <conv_to_utf8+0x3b8>
mov    -0xc(%rbp),%eax
shr    $0x0,%eax
movzbl %al,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x5(%rax)
mov    -0xc(%rbp),%eax
shr    $0x0,%eax
movzbl %al,%eax
sar    $0x6,%eax
or     $0x80,%eax
mov    -0xc(%rbp),%ecx
shr    $0x8,%ecx
movzbl %cl,%ecx
and    $0xf,%ecx
shl    $0x2,%ecx
or     %ecx,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x4(%rax)
mov    -0xc(%rbp),%eax
shr    $0x8,%eax
movzbl %al,%eax
sar    $0x4,%eax
or     $0x80,%eax
mov    -0xc(%rbp),%ecx
shr    $0x10,%ecx
movzbl %cl,%ecx
and    $0x3,%ecx
shl    $0x4,%ecx
or     %ecx,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x3(%rax)
mov    -0xc(%rbp),%eax
shr    $0x10,%eax
movzbl %al,%eax
sar    $0x2,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x2(%rax)
mov    -0xc(%rbp),%eax
shr    $0x18,%eax
movzbl %al,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,0x1(%rax)
mov    -0xc(%rbp),%eax
shr    $0x18,%eax
movzbl %al,%eax
and    $0x40,%eax
sar    $0x6,%eax
or     $0xfc,%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,(%rax)
jmp    14bd <conv_to_utf8+0x3bd>
mov    -0x14(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<conv_to_utf8>:
mov    $0x1,%ecx
cmp    $0x80,%esi
jb     1142 <conv_to_utf8+0x42>
mov    $0x2,%ecx
cmp    $0x800,%esi
jb     1142 <conv_to_utf8+0x42>
mov    $0x3,%ecx
cmp    $0x10000,%esi
jb     1142 <conv_to_utf8+0x42>
mov    $0x4,%ecx
cmp    $0x200000,%esi
jb     1142 <conv_to_utf8+0x42>
cmp    $0x4000000,%esi
mov    $0x6,%ecx
sbb    $0x0,%ecx
xor    %eax,%eax
cmp    %edx,%ecx
cmovbe %ecx,%eax
test   %rdi,%rdi
je     127c <conv_to_utf8+0x17c>
lea    -0x1(%rax),%ecx
cmp    $0x5,%ecx
ja     127c <conv_to_utf8+0x17c>
lea    0xe9b(%rip),%rdx
movslq (%rdx,%rcx,4),%rcx
add    %rdx,%rcx
jmp    *%rcx
mov    %esi,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x1(%rdi)
shr    $0x6,%esi
and    $0x1f,%sil
or     $0xc0,%sil
jmp    1279 <conv_to_utf8+0x179>
mov    %esi,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x2(%rdi)
mov    %esi,%ecx
shr    $0x6,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x1(%rdi)
shr    $0xc,%esi
and    $0xf,%sil
or     $0xe0,%sil
jmp    1279 <conv_to_utf8+0x179>
mov    %esi,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x3(%rdi)
mov    %esi,%ecx
shr    $0x6,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x2(%rdi)
mov    %esi,%ecx
shr    $0xc,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x1(%rdi)
shr    $0x12,%esi
and    $0x7,%sil
or     $0xf0,%sil
jmp    1279 <conv_to_utf8+0x179>
mov    %esi,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x4(%rdi)
mov    %esi,%ecx
shr    $0x6,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x3(%rdi)
mov    %esi,%ecx
shr    $0xc,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x2(%rdi)
mov    %esi,%ecx
shr    $0x12,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x1(%rdi)
shr    $0x18,%esi
and    $0x3,%sil
or     $0xf8,%sil
jmp    1279 <conv_to_utf8+0x179>
mov    %esi,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x5(%rdi)
mov    %esi,%ecx
shr    $0x6,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x4(%rdi)
mov    %esi,%ecx
shr    $0xc,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x3(%rdi)
mov    %esi,%ecx
shr    $0x12,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x2(%rdi)
mov    %esi,%ecx
shr    $0x18,%ecx
and    $0x3f,%cl
or     $0x80,%cl
mov    %cl,0x1(%rdi)
shr    $0x1e,%esi
and    $0x1,%sil
or     $0xfc,%sil
mov    %sil,(%rdi)
ret

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

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