#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 */
typedef int uint8_t;
typedef int uint32_t;

/* Variables and functions */
size_t utf32_to_8(uint32_t utf32, uint8_t *utf8) {
  if (utf32 < 0x80) {
    *utf8 = (uint8_t)utf32;
    return 1;
  }
  if (utf32 < 0x800) {
    utf8[0] = 0xc0 | ((utf32 & 0x07c0) >> 6);
    utf8[1] = 0x80 | (utf32 & 0x003f);
    return 2;
  }
  if (utf32 < 0x10000) {
    utf8[0] = 0xe0 | ((utf32 & 0xf000) >> 12);
    utf8[1] = 0x80 | ((utf32 & 0x0fc0) >> 6);
    utf8[2] = 0x80 | (utf32 & 0x003f);
    return 3;
  }
  if (utf32 < 0x110000) {
    utf8[0] = 0xf0 | ((utf32 & 0x1c0000) >> 18);
    utf8[1] = 0x80 | ((utf32 & 0x03f000) >> 12);
    utf8[2] = 0x80 | ((utf32 & 0x000fc0) >> 6);
    utf8[3] = 0x80 | (utf32 & 0x00003f);
    return 4;
  }
  return 0;
}


x86 assembly (clang, -O0):
<utf32_to_8>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0xc(%rbp)
mov    %rsi,-0x18(%rbp)
cmpl   $0x80,-0xc(%rbp)
jge    112e <utf32_to_8+0x2e>
mov    -0xc(%rbp),%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,(%rax)
movq   $0x1,-0x8(%rbp)
jmp    1250 <utf32_to_8+0x150>
cmpl   $0x800,-0xc(%rbp)
jge    1173 <utf32_to_8+0x73>
mov    -0xc(%rbp),%ecx
and    $0x7c0,%ecx
sar    $0x6,%ecx
or     $0xc0,%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,(%rax)
mov    -0xc(%rbp),%ecx
and    $0x3f,%ecx
or     $0x80,%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,0x4(%rax)
movq   $0x2,-0x8(%rbp)
jmp    1250 <utf32_to_8+0x150>
cmpl   $0x10000,-0xc(%rbp)
jge    11d1 <utf32_to_8+0xd1>
mov    -0xc(%rbp),%ecx
and    $0xf000,%ecx
sar    $0xc,%ecx
or     $0xe0,%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,(%rax)
mov    -0xc(%rbp),%ecx
and    $0xfc0,%ecx
sar    $0x6,%ecx
or     $0x80,%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,0x4(%rax)
mov    -0xc(%rbp),%ecx
and    $0x3f,%ecx
or     $0x80,%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,0x8(%rax)
movq   $0x3,-0x8(%rbp)
jmp    1250 <utf32_to_8+0x150>
cmpl   $0x110000,-0xc(%rbp)
jge    1248 <utf32_to_8+0x148>
mov    -0xc(%rbp),%ecx
and    $0x1c0000,%ecx
sar    $0x12,%ecx
or     $0xf0,%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,(%rax)
mov    -0xc(%rbp),%ecx
and    $0x3f000,%ecx
sar    $0xc,%ecx
or     $0x80,%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,0x4(%rax)
mov    -0xc(%rbp),%ecx
and    $0xfc0,%ecx
sar    $0x6,%ecx
or     $0x80,%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,0x8(%rax)
mov    -0xc(%rbp),%ecx
and    $0x3f,%ecx
or     $0x80,%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,0xc(%rax)
movq   $0x4,-0x8(%rbp)
jmp    1250 <utf32_to_8+0x150>
movq   $0x0,-0x8(%rbp)
mov    -0x8(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<utf32_to_8>:
cmp    $0x7f,%edi
jg     110d <utf32_to_8+0xd>
mov    %edi,(%rsi)
mov    $0x1,%eax
ret
cmp    $0x7ff,%edi
ja     1133 <utf32_to_8+0x33>
mov    %edi,%eax
shr    $0x6,%eax
or     $0xc0,%eax
mov    %eax,(%rsi)
and    $0x3f,%edi
or     $0x80,%edi
mov    %edi,0x4(%rsi)
mov    $0x2,%eax
ret
cmp    $0xffff,%edi
ja     1169 <utf32_to_8+0x69>
mov    %edi,%eax
shr    $0xc,%eax
or     $0xe0,%eax
mov    %eax,(%rsi)
mov    %edi,%eax
shr    $0x6,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %eax,0x4(%rsi)
and    $0x3f,%edi
or     $0x80,%edi
mov    %edi,0x8(%rsi)
mov    $0x3,%eax
ret
cmp    $0x10ffff,%edi
ja     11af <utf32_to_8+0xaf>
mov    %edi,%eax
shr    $0x12,%eax
or     $0xf0,%eax
mov    %eax,(%rsi)
mov    %edi,%eax
shr    $0xc,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %eax,0x4(%rsi)
mov    %edi,%eax
shr    $0x6,%eax
and    $0x3f,%eax
or     $0x80,%eax
mov    %eax,0x8(%rsi)
and    $0x3f,%edi
or     $0x80,%edi
mov    %edi,0xc(%rsi)
mov    $0x4,%eax
ret
xor    %eax,%eax
ret

LLVM IR (-O0):
define i64 @utf32_to_8(i32 %0, i32* %1) {
%3 = alloca i64
%4 = alloca i32
%5 = alloca i32*
store i32 %0, i32* %4
store i32* %1, i32** %5
%6 = load i32, i32* %4
%7 = icmp slt i32 %6, 128
br i1 %7, label %8, label %11
8: ; preds = %2
%9 = load i32, i32* %4
%10 = load i32*, i32** %5
store i32 %9, i32* %10
store i64 1, i64* %3
br label %75
11: ; preds = %2
%12 = load i32, i32* %4
%13 = icmp slt i32 %12, 2048
br i1 %13, label %14, label %26
14: ; preds = %11
%15 = load i32, i32* %4
%16 = and i32 %15, 1984
%17 = ashr i32 %16, 6
%18 = or i32 192, %17
%19 = load i32*, i32** %5
%20 = getelementptr inbounds i32, i32* %19, i64 0
store i32 %18, i32* %20
%21 = load i32, i32* %4
%22 = and i32 %21, 63
%23 = or i32 128, %22
%24 = load i32*, i32** %5
%25 = getelementptr inbounds i32, i32* %24, i64 1
store i32 %23, i32* %25
store i64 2, i64* %3
br label %75
26: ; preds = %11
%27 = load i32, i32* %4
%28 = icmp slt i32 %27, 65536
br i1 %28, label %29, label %47
29: ; preds = %26
%30 = load i32, i32* %4
%31 = and i32 %30, 61440
%32 = ashr i32 %31, 12
%33 = or i32 224, %32
%34 = load i32*, i32** %5
%35 = getelementptr inbounds i32, i32* %34, i64 0
store i32 %33, i32* %35
%36 = load i32, i32* %4
%37 = and i32 %36, 4032
%38 = ashr i32 %37, 6
%39 = or i32 128, %38
%40 = load i32*, i32** %5
%41 = getelementptr inbounds i32, i32* %40, i64 1
store i32 %39, i32* %41
%42 = load i32, i32* %4
%43 = and i32 %42, 63
%44 = or i32 128, %43
%45 = load i32*, i32** %5
%46 = getelementptr inbounds i32, i32* %45, i64 2
store i32 %44, i32* %46
store i64 3, i64* %3
br label %75
47: ; preds = %26
%48 = load i32, i32* %4
%49 = icmp slt i32 %48, 1114112
br i1 %49, label %50, label %74
50: ; preds = %47
%51 = load i32, i32* %4
%52 = and i32 %51, 1835008
%53 = ashr i32 %52, 18
%54 = or i32 240, %53
%55 = load i32*, i32** %5
%56 = getelementptr inbounds i32, i32* %55, i64 0
store i32 %54, i32* %56
%57 = load i32, i32* %4
%58 = and i32 %57, 258048
%59 = ashr i32 %58, 12
%60 = or i32 128, %59
%61 = load i32*, i32** %5
%62 = getelementptr inbounds i32, i32* %61, i64 1
store i32 %60, i32* %62
%63 = load i32, i32* %4
%64 = and i32 %63, 4032
%65 = ashr i32 %64, 6
%66 = or i32 128, %65
%67 = load i32*, i32** %5
%68 = getelementptr inbounds i32, i32* %67, i64 2
store i32 %66, i32* %68
%69 = load i32, i32* %4
%70 = and i32 %69, 63
%71 = or i32 128, %70
%72 = load i32*, i32** %5
%73 = getelementptr inbounds i32, i32* %72, i64 3
store i32 %71, i32* %73
store i64 4, i64* %3
br label %75
74: ; preds = %47
store i64 0, i64* %3
br label %75
75: ; preds = %74, %50, %29, %14, %8
%76 = load i64, i64* %3
ret i64 %76
}

LLVM IR (-O2):
define i64 @utf32_to_8(i32 %0, i32* nocapture writeonly %1) {
%3 = icmp slt i32 %0, 128
br i1 %3, label %4, label %5
4: ; preds = %2
store i32 %0, i32* %1
br label %41
5: ; preds = %2
%6 = icmp ult i32 %0, 2048
br i1 %6, label %7, label %13
7: ; preds = %5
%8 = lshr i32 %0, 6
%9 = or i32 %8, 192
store i32 %9, i32* %1
%10 = and i32 %0, 63
%11 = or i32 %10, 128
%12 = getelementptr inbounds i32, i32* %1, i64 1
store i32 %11, i32* %12
br label %41
13: ; preds = %5
%14 = icmp ult i32 %0, 65536
br i1 %14, label %15, label %25
15: ; preds = %13
%16 = lshr i32 %0, 12
%17 = or i32 %16, 224
store i32 %17, i32* %1
%18 = lshr i32 %0, 6
%19 = and i32 %18, 63
%20 = or i32 %19, 128
%21 = getelementptr inbounds i32, i32* %1, i64 1
store i32 %20, i32* %21
%22 = and i32 %0, 63
%23 = or i32 %22, 128
%24 = getelementptr inbounds i32, i32* %1, i64 2
store i32 %23, i32* %24
br label %41
25: ; preds = %13
%26 = icmp ult i32 %0, 1114112
br i1 %26, label %27, label %41
27: ; preds = %25
%28 = lshr i32 %0, 18
%29 = or i32 %28, 240
store i32 %29, i32* %1
%30 = lshr i32 %0, 12
%31 = and i32 %30, 63
%32 = or i32 %31, 128
%33 = getelementptr inbounds i32, i32* %1, i64 1
store i32 %32, i32* %33
%34 = lshr i32 %0, 6
%35 = and i32 %34, 63
%36 = or i32 %35, 128
%37 = getelementptr inbounds i32, i32* %1, i64 2
store i32 %36, i32* %37
%38 = and i32 %0, 63
%39 = or i32 %38, 128
%40 = getelementptr inbounds i32, i32* %1, i64 3
store i32 %39, i32* %40
br label %41
41: ; preds = %25, %27, %15, %7, %4
%42 = phi i64 [ 1, %4 ], [ 2, %7 ], [ 3, %15 ], [ 4, %27 ], [ 0, %25 ]
ret i64 %42
}