int unicode_to_utf8(unsigned int codepoint, char *p, char **endp) {
  if (codepoint < 0x80)
    *p++ = codepoint;
  else if (codepoint < 0x800)
    *p++ = 192 + codepoint / 64, *p++ = 128 + codepoint % 64;
  else if (codepoint - 0xd800u < 0x800)
    return 0;
  else if (codepoint < 0x10000)
    *p++ = 224 + codepoint / 4096, *p++ = 128 + codepoint / 64 % 64,
    *p++ = 128 + codepoint % 64;
  else if (codepoint < 0x110000)
    *p++ = 240 + codepoint / 262144, *p++ = 128 + codepoint / 4096 % 64,
    *p++ = 128 + codepoint / 64 % 64, *p++ = 128 + codepoint % 64;
  else
    return 0;
  *endp = p;
  return 1;
}


x86 assembly (clang, -O0):
<unicode_to_utf8>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
cmpl   $0x80,-0x8(%rbp)
jae    1137 <unicode_to_utf8+0x37>
mov    -0x8(%rbp),%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
jmp    12c3 <unicode_to_utf8+0x1c3>
cmpl   $0x800,-0x8(%rbp)
jae    1185 <unicode_to_utf8+0x85>
mov    -0x8(%rbp),%eax
shr    $0x6,%eax
add    $0xc0,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
mov    -0x8(%rbp),%eax
and    $0x3f,%eax
add    $0x80,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
jmp    12be <unicode_to_utf8+0x1be>
mov    -0x8(%rbp),%eax
sub    $0xd800,%eax
cmp    $0x800,%eax
jae    11a4 <unicode_to_utf8+0xa4>
movl   $0x0,-0x4(%rbp)
jmp    12d5 <unicode_to_utf8+0x1d5>
cmpl   $0x10000,-0x8(%rbp)
jae    1213 <unicode_to_utf8+0x113>
mov    -0x8(%rbp),%eax
shr    $0xc,%eax
add    $0xe0,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
mov    -0x8(%rbp),%eax
shr    $0x6,%eax
and    $0x3f,%eax
add    $0x80,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
mov    -0x8(%rbp),%eax
and    $0x3f,%eax
add    $0x80,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
jmp    12b4 <unicode_to_utf8+0x1b4>
cmpl   $0x110000,-0x8(%rbp)
jae    12a3 <unicode_to_utf8+0x1a3>
mov    -0x8(%rbp),%eax
shr    $0x12,%eax
add    $0xf0,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
mov    -0x8(%rbp),%eax
shr    $0xc,%eax
and    $0x3f,%eax
add    $0x80,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
mov    -0x8(%rbp),%eax
shr    $0x6,%eax
and    $0x3f,%eax
add    $0x80,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
mov    -0x8(%rbp),%eax
and    $0x3f,%eax
add    $0x80,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
jmp    12af <unicode_to_utf8+0x1af>
movl   $0x0,-0x4(%rbp)
jmp    12d5 <unicode_to_utf8+0x1d5>
jmp    12b4 <unicode_to_utf8+0x1b4>
jmp    12b9 <unicode_to_utf8+0x1b9>
jmp    12be <unicode_to_utf8+0x1be>
jmp    12c3 <unicode_to_utf8+0x1c3>
mov    -0x10(%rbp),%rcx
mov    -0x18(%rbp),%rax
mov    %rcx,(%rax)
movl   $0x1,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<unicode_to_utf8>:
cmp    $0x7f,%edi
ja     1111 <unicode_to_utf8+0x11>
mov    %dil,(%rsi)
add    $0x1,%rsi
jmp    11ae <unicode_to_utf8+0xae>
cmp    $0x7ff,%edi
ja     1134 <unicode_to_utf8+0x34>
mov    %edi,%eax
shr    $0x6,%eax
add    $0xc0,%al
mov    %al,(%rsi)
and    $0x3f,%dil
or     $0x80,%dil
mov    %dil,0x1(%rsi)
add    $0x2,%rsi
jmp    11ae <unicode_to_utf8+0xae>
mov    %edi,%ecx
and    $0xfffff800,%ecx
xor    %eax,%eax
cmp    $0xd800,%ecx
je     11b6 <unicode_to_utf8+0xb6>
cmp    $0xffff,%edi
ja     1175 <unicode_to_utf8+0x75>
mov    %edi,%eax
shr    $0xc,%eax
add    $0xe0,%al
mov    %al,(%rsi)
mov    %edi,%eax
shr    $0x6,%eax
and    $0x3f,%al
or     $0x80,%al
mov    %al,0x1(%rsi)
and    $0x3f,%dil
or     $0x80,%dil
mov    %dil,0x2(%rsi)
add    $0x3,%rsi
jmp    11ae <unicode_to_utf8+0xae>
cmp    $0x10ffff,%edi
ja     11b6 <unicode_to_utf8+0xb6>
mov    %edi,%eax
shr    $0x12,%eax
add    $0xf0,%al
mov    %al,(%rsi)
mov    %edi,%eax
shr    $0xc,%eax
and    $0x3f,%al
or     $0x80,%al
mov    %al,0x1(%rsi)
mov    %edi,%eax
shr    $0x6,%eax
and    $0x3f,%al
or     $0x80,%al
mov    %al,0x2(%rsi)
and    $0x3f,%dil
or     $0x80,%dil
mov    %dil,0x3(%rsi)
add    $0x4,%rsi
mov    %rsi,(%rdx)
mov    $0x1,%eax
ret

LLVM IR (-O0):
define i32 @unicode_to_utf8(i32 %0, i8* %1, i8** %2) {
%4 = alloca i32
%5 = alloca i32
%6 = alloca i8*
%7 = alloca i8**
store i32 %0, i32* %5
store i8* %1, i8** %6
store i8** %2, i8*** %7
%8 = load i32, i32* %5
%9 = icmp ult i32 %8, 128
br i1 %9, label %10, label %15
10: ; preds = %3
%11 = load i32, i32* %5
%12 = trunc i32 %11 to i8
%13 = load i8*, i8** %6
%14 = getelementptr inbounds i8, i8* %13, i32 1
store i8* %14, i8** %6
store i8 %12, i8* %13
br label %94
15: ; preds = %3
%16 = load i32, i32* %5
%17 = icmp ult i32 %16, 2048
br i1 %17, label %18, label %31
18: ; preds = %15
%19 = load i32, i32* %5
%20 = udiv i32 %19, 64
%21 = add i32 192, %20
%22 = trunc i32 %21 to i8
%23 = load i8*, i8** %6
%24 = getelementptr inbounds i8, i8* %23, i32 1
store i8* %24, i8** %6
store i8 %22, i8* %23
%25 = load i32, i32* %5
%26 = urem i32 %25, 64
%27 = add i32 128, %26
%28 = trunc i32 %27 to i8
%29 = load i8*, i8** %6
%30 = getelementptr inbounds i8, i8* %29, i32 1
store i8* %30, i8** %6
store i8 %28, i8* %29
br label %93
31: ; preds = %15
%32 = load i32, i32* %5
%33 = sub i32 %32, 55296
%34 = icmp ult i32 %33, 2048
br i1 %34, label %35, label %36
35: ; preds = %31
store i32 0, i32* %4
br label %97
36: ; preds = %31
%37 = load i32, i32* %5
%38 = icmp ult i32 %37, 65536
br i1 %38, label %39, label %59
39: ; preds = %36
%40 = load i32, i32* %5
%41 = udiv i32 %40, 4096
%42 = add i32 224, %41
%43 = trunc i32 %42 to i8
%44 = load i8*, i8** %6
%45 = getelementptr inbounds i8, i8* %44, i32 1
store i8* %45, i8** %6
store i8 %43, i8* %44
%46 = load i32, i32* %5
%47 = udiv i32 %46, 64
%48 = urem i32 %47, 64
%49 = add i32 128, %48
%50 = trunc i32 %49 to i8
%51 = load i8*, i8** %6
%52 = getelementptr inbounds i8, i8* %51, i32 1
store i8* %52, i8** %6
store i8 %50, i8* %51
%53 = load i32, i32* %5
%54 = urem i32 %53, 64
%55 = add i32 128, %54
%56 = trunc i32 %55 to i8
%57 = load i8*, i8** %6
%58 = getelementptr inbounds i8, i8* %57, i32 1
store i8* %58, i8** %6
store i8 %56, i8* %57
br label %91
59: ; preds = %36
%60 = load i32, i32* %5
%61 = icmp ult i32 %60, 1114112
br i1 %61, label %62, label %89
62: ; preds = %59
%63 = load i32, i32* %5
%64 = udiv i32 %63, 262144
%65 = add i32 240, %64
%66 = trunc i32 %65 to i8
%67 = load i8*, i8** %6
%68 = getelementptr inbounds i8, i8* %67, i32 1
store i8* %68, i8** %6
store i8 %66, i8* %67
%69 = load i32, i32* %5
%70 = udiv i32 %69, 4096
%71 = urem i32 %70, 64
%72 = add i32 128, %71
%73 = trunc i32 %72 to i8
%74 = load i8*, i8** %6
%75 = getelementptr inbounds i8, i8* %74, i32 1
store i8* %75, i8** %6
store i8 %73, i8* %74
%76 = load i32, i32* %5
%77 = udiv i32 %76, 64
%78 = urem i32 %77, 64
%79 = add i32 128, %78
%80 = trunc i32 %79 to i8
%81 = load i8*, i8** %6
%82 = getelementptr inbounds i8, i8* %81, i32 1
store i8* %82, i8** %6
store i8 %80, i8* %81
%83 = load i32, i32* %5
%84 = urem i32 %83, 64
%85 = add i32 128, %84
%86 = trunc i32 %85 to i8
%87 = load i8*, i8** %6
%88 = getelementptr inbounds i8, i8* %87, i32 1
store i8* %88, i8** %6
store i8 %86, i8* %87
br label %90
89: ; preds = %59
store i32 0, i32* %4
br label %97
90: ; preds = %62
br label %91
91: ; preds = %90, %39
br label %92
92: ; preds = %91
br label %93
93: ; preds = %92, %18
br label %94
94: ; preds = %93, %10
%95 = load i8*, i8** %6
%96 = load i8**, i8*** %7
store i8* %95, i8** %96
store i32 1, i32* %4
br label %97
97: ; preds = %94, %89, %35
%98 = load i32, i32* %4
ret i32 %98
}

LLVM IR (-O2):
define i32 @unicode_to_utf8(i32 %0, i8* %1, i8** nocapture writeonly %2) {
%4 = icmp ult i32 %0, 128
br i1 %4, label %5, label %8
5: ; preds = %3
%6 = trunc i32 %0 to i8
%7 = getelementptr inbounds i8, i8* %1, i64 1
store i8 %6, i8* %1
br label %59
8: ; preds = %3
%9 = icmp ult i32 %0, 2048
br i1 %9, label %10, label %19
10: ; preds = %8
%11 = lshr i32 %0, 6
%12 = trunc i32 %11 to i8
%13 = add nuw nsw i8 %12, -64
%14 = getelementptr inbounds i8, i8* %1, i64 1
store i8 %13, i8* %1
%15 = trunc i32 %0 to i8
%16 = and i8 %15, 63
%17 = or i8 %16, -128
%18 = getelementptr inbounds i8, i8* %1, i64 2
store i8 %17, i8* %14
br label %59
19: ; preds = %8
%20 = and i32 %0, -2048
%21 = icmp eq i32 %20, 55296
br i1 %21, label %61, label %22
22: ; preds = %19
%23 = icmp ult i32 %0, 65536
br i1 %23, label %24, label %38
24: ; preds = %22
%25 = lshr i32 %0, 12
%26 = trunc i32 %25 to i8
%27 = add nuw nsw i8 %26, -32
%28 = getelementptr inbounds i8, i8* %1, i64 1
store i8 %27, i8* %1
%29 = lshr i32 %0, 6
%30 = trunc i32 %29 to i8
%31 = and i8 %30, 63
%32 = or i8 %31, -128
%33 = getelementptr inbounds i8, i8* %1, i64 2
store i8 %32, i8* %28
%34 = trunc i32 %0 to i8
%35 = and i8 %34, 63
%36 = or i8 %35, -128
%37 = getelementptr inbounds i8, i8* %1, i64 3
store i8 %36, i8* %33
br label %59
38: ; preds = %22
%39 = icmp ult i32 %0, 1114112
br i1 %39, label %40, label %61
40: ; preds = %38
%41 = lshr i32 %0, 18
%42 = trunc i32 %41 to i8
%43 = add nuw nsw i8 %42, -16
%44 = getelementptr inbounds i8, i8* %1, i64 1
store i8 %43, i8* %1
%45 = lshr i32 %0, 12
%46 = trunc i32 %45 to i8
%47 = and i8 %46, 63
%48 = or i8 %47, -128
%49 = getelementptr inbounds i8, i8* %1, i64 2
store i8 %48, i8* %44
%50 = lshr i32 %0, 6
%51 = trunc i32 %50 to i8
%52 = and i8 %51, 63
%53 = or i8 %52, -128
%54 = getelementptr inbounds i8, i8* %1, i64 3
store i8 %53, i8* %49
%55 = trunc i32 %0 to i8
%56 = and i8 %55, 63
%57 = or i8 %56, -128
%58 = getelementptr inbounds i8, i8* %1, i64 4
store i8 %57, i8* %54
br label %59
59: ; preds = %10, %24, %40, %5
%60 = phi i8* [ %7, %5 ], [ %18, %10 ], [ %37, %24 ], [ %58, %40 ]
store i8* %60, i8** %2
br label %61
61: ; preds = %38, %19, %59
%62 = phi i32 [ 1, %59 ], [ 0, %19 ], [ 0, %38 ]
ret i32 %62
}