int hangul_split(unsigned int chr, unsigned int *lead, unsigned int *vowel,
                 unsigned int *tail) {
  static const unsigned int initials[] = {
      0x3131, 0x3132, 0x3134, 0x3137, 0x3138, 0x3139, 0x3141,
      0x3142, 0x3143, 0x3145, 0x3146, 0x3147, 0x3148, 0x3149,
      0x314a, 0x314b, 0x314c, 0x314d, 0x314e};
  static const unsigned int medials[] = {
      0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155,
      0x3156, 0x3157, 0x3158, 0x3159, 0x315a, 0x315b, 0x315c,
      0x315d, 0x315e, 0x315f, 0x3160, 0x3161, 0x3162, 0x3163};
  static const unsigned int finals[] = {
      0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136,
      0x3137, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e,
      0x313f, 0x3140, 0x3141, 0x3142, 0x3144, 0x3145, 0x3146,
      0x3147, 0x3148, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e};
  unsigned int a, b, c;
  if (chr >= 0xAC00 && chr <= 0xD7A3) {
    c = chr - 0xAC00;
    a = c / (21 * 28);
    c = c % (21 * 28);
    b = c / 28;
    c = c % 28;
    if (lead)
      *lead = initials[a];
    if (vowel)
      *vowel = medials[b];
    if (tail)
      *tail = finals[c];
    return 0;
  }
  return -1;
}


x86 assembly (clang, -O0):
<hangul_split>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
cmpl   $0xac00,-0x8(%rbp)
jb     11e0 <hangul_split+0xe0>
cmpl   $0xd7a3,-0x8(%rbp)
ja     11e0 <hangul_split+0xe0>
mov    -0x8(%rbp),%eax
sub    $0xac00,%eax
mov    %eax,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    $0x24c,%ecx
xor    %edx,%edx
div    %ecx
mov    %eax,-0x24(%rbp)
mov    -0x2c(%rbp),%eax
mov    $0x24c,%ecx
xor    %edx,%edx
div    %ecx
mov    %edx,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    $0x1c,%ecx
xor    %edx,%edx
div    %ecx
mov    %eax,-0x28(%rbp)
mov    -0x2c(%rbp),%eax
mov    $0x1c,%ecx
xor    %edx,%edx
div    %ecx
mov    %edx,-0x2c(%rbp)
cmpq   $0x0,-0x10(%rbp)
je     1194 <hangul_split+0x94>
mov    -0x24(%rbp),%eax
mov    %eax,%ecx
lea    0xe75(%rip),%rax
mov    (%rax,%rcx,4),%ecx
mov    -0x10(%rbp),%rax
mov    %ecx,(%rax)
cmpq   $0x0,-0x18(%rbp)
je     11b4 <hangul_split+0xb4>
mov    -0x28(%rbp),%eax
mov    %eax,%ecx
lea    0xea5(%rip),%rax
mov    (%rax,%rcx,4),%ecx
mov    -0x18(%rbp),%rax
mov    %ecx,(%rax)
cmpq   $0x0,-0x20(%rbp)
je     11d4 <hangul_split+0xd4>
mov    -0x2c(%rbp),%eax
mov    %eax,%ecx
lea    0xee5(%rip),%rax
mov    (%rax,%rcx,4),%ecx
mov    -0x20(%rbp),%rax
mov    %ecx,(%rax)
movl   $0x0,-0x4(%rbp)
jmp    11e7 <hangul_split+0xe7>
movl   $0xffffffff,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<hangul_split>:
add    $0xffff5400,%edi
mov    $0xffffffff,%eax
cmp    $0x2ba3,%edi
ja     1189 <hangul_split+0x89>
movzwl %di,%eax
imul   $0x6f75,%eax,%r9d
shr    $0x18,%r9d
imul   $0x24c,%r9d,%eax
sub    %eax,%edi
movzwl %di,%r8d
mov    %r8d,%eax
shr    $0x2,%eax
imul   $0x4925,%eax,%edi
test   %rsi,%rsi
je     1150 <hangul_split+0x50>
movzwl %r9w,%r9d
lea    0xeb6(%rip),%rax
mov    (%rax,%r9,4),%eax
mov    %eax,(%rsi)
shr    $0x11,%edi
test   %rdx,%rdx
je     1167 <hangul_split+0x67>
movzwl %di,%eax
lea    0xeee(%rip),%rsi
mov    (%rsi,%rax,4),%eax
mov    %eax,(%rdx)
xor    %eax,%eax
test   %rcx,%rcx
je     1189 <hangul_split+0x89>
lea    (%rdi,%rdi,8),%edx
lea    (%rdx,%rdx,2),%edx
add    %edi,%edx
sub    %edx,%r8d
movzwl %r8w,%edx
lea    0xf2c(%rip),%rsi
mov    (%rsi,%rdx,4),%edx
mov    %edx,(%rcx)
ret

LLVM IR (-O0):
@hangul_split.initials = internal constant [19 x i32] [i32 12593, i32 12594, i32 12596, i32 12599, i32 12600, i32 12601, i32 12609, i32 12610, i32 12611, i32 12613, i32 12614, i32 12615, i32 12616, i32 12617, i32 12618, i32 12619, i32 12620, i32 12621, i32 12622]
@hangul_split.medials = internal constant [21 x i32] [i32 12623, i32 12624, i32 12625, i32 12626, i32 12627, i32 12628, i32 12629, i32 12630, i32 12631, i32 12632, i32 12633, i32 12634, i32 12635, i32 12636, i32 12637, i32 12638, i32 12639, i32 12640, i32 12641, i32 12642, i32 12643]
@hangul_split.finals = internal constant [28 x i32] [i32 0, i32 12593, i32 12594, i32 12595, i32 12596, i32 12597, i32 12598, i32 12599, i32 12601, i32 12602, i32 12603, i32 12604, i32 12605, i32 12606, i32 12607, i32 12608, i32 12609, i32 12610, i32 12612, i32 12613, i32 12614, i32 12615, i32 12616, i32 12618, i32 12619, i32 12620, i32 12621, i32 12622]
define i32 @hangul_split(i32 %0, i32* %1, i32* %2, i32* %3) {
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32*
%8 = alloca i32*
%9 = alloca i32*
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
store i32 %0, i32* %6
store i32* %1, i32** %7
store i32* %2, i32** %8
store i32* %3, i32** %9
%13 = load i32, i32* %6
%14 = icmp uge i32 %13, 44032
br i1 %14, label %15, label %56
15: ; preds = %4
%16 = load i32, i32* %6
%17 = icmp ule i32 %16, 55203
br i1 %17, label %18, label %56
18: ; preds = %15
%19 = load i32, i32* %6
%20 = sub i32 %19, 44032
store i32 %20, i32* %12
%21 = load i32, i32* %12
%22 = udiv i32 %21, 588
store i32 %22, i32* %10
%23 = load i32, i32* %12
%24 = urem i32 %23, 588
store i32 %24, i32* %12
%25 = load i32, i32* %12
%26 = udiv i32 %25, 28
store i32 %26, i32* %11
%27 = load i32, i32* %12
%28 = urem i32 %27, 28
store i32 %28, i32* %12
%29 = load i32*, i32** %7
%30 = icmp ne i32* %29, null
br i1 %30, label %31, label %37
31: ; preds = %18
%32 = load i32, i32* %10
%33 = zext i32 %32 to i64
%34 = getelementptr inbounds [19 x i32], [19 x i32]* @hangul_split.initials, i64 0, i64 %33
%35 = load i32, i32* %34
%36 = load i32*, i32** %7
store i32 %35, i32* %36
br label %37
37: ; preds = %31, %18
%38 = load i32*, i32** %8
%39 = icmp ne i32* %38, null
br i1 %39, label %40, label %46
40: ; preds = %37
%41 = load i32, i32* %11
%42 = zext i32 %41 to i64
%43 = getelementptr inbounds [21 x i32], [21 x i32]* @hangul_split.medials, i64 0, i64 %42
%44 = load i32, i32* %43
%45 = load i32*, i32** %8
store i32 %44, i32* %45
br label %46
46: ; preds = %40, %37
%47 = load i32*, i32** %9
%48 = icmp ne i32* %47, null
br i1 %48, label %49, label %55
49: ; preds = %46
%50 = load i32, i32* %12
%51 = zext i32 %50 to i64
%52 = getelementptr inbounds [28 x i32], [28 x i32]* @hangul_split.finals, i64 0, i64 %51
%53 = load i32, i32* %52
%54 = load i32*, i32** %9
store i32 %53, i32* %54
br label %55
55: ; preds = %49, %46
store i32 0, i32* %5
br label %57
56: ; preds = %15, %4
store i32 -1, i32* %5
br label %57
57: ; preds = %56, %55
%58 = load i32, i32* %5
ret i32 %58
}

LLVM IR (-O2):
@hangul_split.initials = internal unnamed_addr constant [19 x i32] [i32 12593, i32 12594, i32 12596, i32 12599, i32 12600, i32 12601, i32 12609, i32 12610, i32 12611, i32 12613, i32 12614, i32 12615, i32 12616, i32 12617, i32 12618, i32 12619, i32 12620, i32 12621, i32 12622]
@hangul_split.medials = internal unnamed_addr constant [21 x i32] [i32 12623, i32 12624, i32 12625, i32 12626, i32 12627, i32 12628, i32 12629, i32 12630, i32 12631, i32 12632, i32 12633, i32 12634, i32 12635, i32 12636, i32 12637, i32 12638, i32 12639, i32 12640, i32 12641, i32 12642, i32 12643]
@hangul_split.finals = internal unnamed_addr constant [28 x i32] [i32 0, i32 12593, i32 12594, i32 12595, i32 12596, i32 12597, i32 12598, i32 12599, i32 12601, i32 12602, i32 12603, i32 12604, i32 12605, i32 12606, i32 12607, i32 12608, i32 12609, i32 12610, i32 12612, i32 12613, i32 12614, i32 12615, i32 12616, i32 12618, i32 12619, i32 12620, i32 12621, i32 12622]
define i32 @hangul_split(i32 %0, i32* writeonly %1, i32* writeonly %2, i32* writeonly %3) {
%5 = add i32 %0, -44032
%6 = icmp ult i32 %5, 11172
br i1 %6, label %7, label %30
7: ; preds = %4
%8 = trunc i32 %5 to i16
%9 = urem i16 %8, 588
%10 = udiv i16 %8, 588
%11 = udiv i16 %9, 28
%12 = urem i16 %9, 28
%13 = icmp eq i32* %1, null
br i1 %13, label %18, label %14
14: ; preds = %7
%15 = zext i16 %10 to i64
%16 = getelementptr inbounds [19 x i32], [19 x i32]* @hangul_split.initials, i64 0, i64 %15
%17 = load i32, i32* %16
store i32 %17, i32* %1
br label %18
18: ; preds = %14, %7
%19 = icmp eq i32* %2, null
br i1 %19, label %24, label %20
20: ; preds = %18
%21 = zext i16 %11 to i64
%22 = getelementptr inbounds [21 x i32], [21 x i32]* @hangul_split.medials, i64 0, i64 %21
%23 = load i32, i32* %22
store i32 %23, i32* %2
br label %24
24: ; preds = %20, %18
%25 = icmp eq i32* %3, null
br i1 %25, label %30, label %26
26: ; preds = %24
%27 = zext i16 %12 to i64
%28 = getelementptr inbounds [28 x i32], [28 x i32]* @hangul_split.finals, i64 0, i64 %27
%29 = load i32, i32* %28
store i32 %29, i32* %3
br label %30
30: ; preds = %4, %24, %26
%31 = phi i32 [ 0, %26 ], [ 0, %24 ], [ -1, %4 ]
ret i32 %31
}